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.content.res.Resources.ID_NULL;
     20 import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS;
     21 import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS;
     22 import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP;
     23 import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION;
     24 import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
     25 import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED;
     26 
     27 import static java.lang.Math.max;
     28 
     29 import android.animation.AnimatorInflater;
     30 import android.animation.StateListAnimator;
     31 import android.annotation.AttrRes;
     32 import android.annotation.CallSuper;
     33 import android.annotation.ColorInt;
     34 import android.annotation.DrawableRes;
     35 import android.annotation.FloatRange;
     36 import android.annotation.IdRes;
     37 import android.annotation.IntDef;
     38 import android.annotation.IntRange;
     39 import android.annotation.LayoutRes;
     40 import android.annotation.NonNull;
     41 import android.annotation.Nullable;
     42 import android.annotation.Size;
     43 import android.annotation.StyleRes;
     44 import android.annotation.TestApi;
     45 import android.annotation.UiThread;
     46 import android.annotation.UnsupportedAppUsage;
     47 import android.content.AutofillOptions;
     48 import android.content.ClipData;
     49 import android.content.Context;
     50 import android.content.ContextWrapper;
     51 import android.content.Intent;
     52 import android.content.res.ColorStateList;
     53 import android.content.res.Configuration;
     54 import android.content.res.Resources;
     55 import android.content.res.TypedArray;
     56 import android.graphics.Bitmap;
     57 import android.graphics.BlendMode;
     58 import android.graphics.Canvas;
     59 import android.graphics.Color;
     60 import android.graphics.Insets;
     61 import android.graphics.Interpolator;
     62 import android.graphics.LinearGradient;
     63 import android.graphics.Matrix;
     64 import android.graphics.Outline;
     65 import android.graphics.Paint;
     66 import android.graphics.PixelFormat;
     67 import android.graphics.Point;
     68 import android.graphics.PorterDuff;
     69 import android.graphics.PorterDuffXfermode;
     70 import android.graphics.RecordingCanvas;
     71 import android.graphics.Rect;
     72 import android.graphics.RectF;
     73 import android.graphics.Region;
     74 import android.graphics.RenderNode;
     75 import android.graphics.Shader;
     76 import android.graphics.drawable.ColorDrawable;
     77 import android.graphics.drawable.Drawable;
     78 import android.hardware.display.DisplayManagerGlobal;
     79 import android.net.Uri;
     80 import android.os.Build;
     81 import android.os.Bundle;
     82 import android.os.Handler;
     83 import android.os.IBinder;
     84 import android.os.Message;
     85 import android.os.Parcel;
     86 import android.os.Parcelable;
     87 import android.os.RemoteException;
     88 import android.os.SystemClock;
     89 import android.os.Trace;
     90 import android.sysprop.DisplayProperties;
     91 import android.text.InputType;
     92 import android.text.TextUtils;
     93 import android.util.AttributeSet;
     94 import android.util.FloatProperty;
     95 import android.util.LayoutDirection;
     96 import android.util.Log;
     97 import android.util.LongSparseLongArray;
     98 import android.util.Pools.SynchronizedPool;
     99 import android.util.Property;
    100 import android.util.SparseArray;
    101 import android.util.SparseIntArray;
    102 import android.util.StateSet;
    103 import android.util.StatsLog;
    104 import android.util.SuperNotCalledException;
    105 import android.util.TypedValue;
    106 import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
    107 import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
    108 import android.view.AccessibilityIterators.TextSegmentIterator;
    109 import android.view.AccessibilityIterators.WordTextSegmentIterator;
    110 import android.view.ContextMenu.ContextMenuInfo;
    111 import android.view.WindowInsetsAnimationListener.InsetsAnimation;
    112 import android.view.accessibility.AccessibilityEvent;
    113 import android.view.accessibility.AccessibilityEventSource;
    114 import android.view.accessibility.AccessibilityManager;
    115 import android.view.accessibility.AccessibilityNodeIdManager;
    116 import android.view.accessibility.AccessibilityNodeInfo;
    117 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
    118 import android.view.accessibility.AccessibilityNodeProvider;
    119 import android.view.accessibility.AccessibilityWindowInfo;
    120 import android.view.animation.Animation;
    121 import android.view.animation.AnimationUtils;
    122 import android.view.animation.Transformation;
    123 import android.view.autofill.AutofillId;
    124 import android.view.autofill.AutofillManager;
    125 import android.view.autofill.AutofillValue;
    126 import android.view.contentcapture.ContentCaptureContext;
    127 import android.view.contentcapture.ContentCaptureManager;
    128 import android.view.contentcapture.ContentCaptureSession;
    129 import android.view.inputmethod.EditorInfo;
    130 import android.view.inputmethod.InputConnection;
    131 import android.view.inputmethod.InputMethodManager;
    132 import android.view.inspector.InspectableProperty;
    133 import android.view.inspector.InspectableProperty.EnumEntry;
    134 import android.view.inspector.InspectableProperty.FlagEntry;
    135 import android.widget.Checkable;
    136 import android.widget.FrameLayout;
    137 import android.widget.ScrollBarDrawable;
    138 
    139 import com.android.internal.R;
    140 import com.android.internal.view.TooltipPopup;
    141 import com.android.internal.view.menu.MenuBuilder;
    142 import com.android.internal.widget.ScrollBarUtils;
    143 
    144 import com.google.android.collect.Lists;
    145 import com.google.android.collect.Maps;
    146 
    147 import java.lang.annotation.Retention;
    148 import java.lang.annotation.RetentionPolicy;
    149 import java.lang.ref.WeakReference;
    150 import java.lang.reflect.Field;
    151 import java.lang.reflect.InvocationTargetException;
    152 import java.lang.reflect.Method;
    153 import java.lang.reflect.Modifier;
    154 import java.util.ArrayList;
    155 import java.util.Arrays;
    156 import java.util.Calendar;
    157 import java.util.Collection;
    158 import java.util.Collections;
    159 import java.util.HashMap;
    160 import java.util.List;
    161 import java.util.Locale;
    162 import java.util.Map;
    163 import java.util.concurrent.CopyOnWriteArrayList;
    164 import java.util.concurrent.atomic.AtomicInteger;
    165 import java.util.function.Predicate;
    166 
    167 /**
    168  * <p>
    169  * This class represents the basic building block for user interface components. A View
    170  * occupies a rectangular area on the screen and is responsible for drawing and
    171  * event handling. View is the base class for <em>widgets</em>, which are
    172  * used to create interactive UI components (buttons, text fields, etc.). The
    173  * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
    174  * are invisible containers that hold other Views (or other ViewGroups) and define
    175  * their layout properties.
    176  * </p>
    177  *
    178  * <div class="special reference">
    179  * <h3>Developer Guides</h3>
    180  * <p>For information about using this class to develop your application's user interface,
    181  * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
    182  * </div>
    183  *
    184  * <a name="Using"></a>
    185  * <h3>Using Views</h3>
    186  * <p>
    187  * All of the views in a window are arranged in a single tree. You can add views
    188  * either from code or by specifying a tree of views in one or more XML layout
    189  * files. There are many specialized subclasses of views that act as controls or
    190  * are capable of displaying text, images, or other content.
    191  * </p>
    192  * <p>
    193  * Once you have created a tree of views, there are typically a few types of
    194  * common operations you may wish to perform:
    195  * <ul>
    196  * <li><strong>Set properties:</strong> for example setting the text of a
    197  * {@link android.widget.TextView}. The available properties and the methods
    198  * that set them will vary among the different subclasses of views. Note that
    199  * properties that are known at build time can be set in the XML layout
    200  * files.</li>
    201  * <li><strong>Set focus:</strong> The framework will handle moving focus in
    202  * response to user input. To force focus to a specific view, call
    203  * {@link #requestFocus}.</li>
    204  * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
    205  * that will be notified when something interesting happens to the view. For
    206  * example, all views will let you set a listener to be notified when the view
    207  * gains or loses focus. You can register such a listener using
    208  * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
    209  * Other view subclasses offer more specialized listeners. For example, a Button
    210  * exposes a listener to notify clients when the button is clicked.</li>
    211  * <li><strong>Set visibility:</strong> You can hide or show views using
    212  * {@link #setVisibility(int)}.</li>
    213  * </ul>
    214  * </p>
    215  * <p><em>
    216  * Note: The Android framework is responsible for measuring, laying out and
    217  * drawing views. You should not call methods that perform these actions on
    218  * views yourself unless you are actually implementing a
    219  * {@link android.view.ViewGroup}.
    220  * </em></p>
    221  *
    222  * <a name="Lifecycle"></a>
    223  * <h3>Implementing a Custom View</h3>
    224  *
    225  * <p>
    226  * To implement a custom view, you will usually begin by providing overrides for
    227  * some of the standard methods that the framework calls on all views. You do
    228  * not need to override all of these methods. In fact, you can start by just
    229  * overriding {@link #onDraw(android.graphics.Canvas)}.
    230  * <table border="2" width="85%" align="center" cellpadding="5">
    231  *     <thead>
    232  *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
    233  *     </thead>
    234  *
    235  *     <tbody>
    236  *     <tr>
    237  *         <td rowspan="2">Creation</td>
    238  *         <td>Constructors</td>
    239  *         <td>There is a form of the constructor that are called when the view
    240  *         is created from code and a form that is called when the view is
    241  *         inflated from a layout file. The second form should parse and apply
    242  *         any attributes defined in the layout file.
    243  *         </td>
    244  *     </tr>
    245  *     <tr>
    246  *         <td><code>{@link #onFinishInflate()}</code></td>
    247  *         <td>Called after a view and all of its children has been inflated
    248  *         from XML.</td>
    249  *     </tr>
    250  *
    251  *     <tr>
    252  *         <td rowspan="3">Layout</td>
    253  *         <td><code>{@link #onMeasure(int, int)}</code></td>
    254  *         <td>Called to determine the size requirements for this view and all
    255  *         of its children.
    256  *         </td>
    257  *     </tr>
    258  *     <tr>
    259  *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
    260  *         <td>Called when this view should assign a size and position to all
    261  *         of its children.
    262  *         </td>
    263  *     </tr>
    264  *     <tr>
    265  *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
    266  *         <td>Called when the size of this view has changed.
    267  *         </td>
    268  *     </tr>
    269  *
    270  *     <tr>
    271  *         <td>Drawing</td>
    272  *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
    273  *         <td>Called when the view should render its content.
    274  *         </td>
    275  *     </tr>
    276  *
    277  *     <tr>
    278  *         <td rowspan="4">Event processing</td>
    279  *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
    280  *         <td>Called when a new hardware key event occurs.
    281  *         </td>
    282  *     </tr>
    283  *     <tr>
    284  *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
    285  *         <td>Called when a hardware key up event occurs.
    286  *         </td>
    287  *     </tr>
    288  *     <tr>
    289  *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
    290  *         <td>Called when a trackball motion event occurs.
    291  *         </td>
    292  *     </tr>
    293  *     <tr>
    294  *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
    295  *         <td>Called when a touch screen motion event occurs.
    296  *         </td>
    297  *     </tr>
    298  *
    299  *     <tr>
    300  *         <td rowspan="2">Focus</td>
    301  *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
    302  *         <td>Called when the view gains or loses focus.
    303  *         </td>
    304  *     </tr>
    305  *
    306  *     <tr>
    307  *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
    308  *         <td>Called when the window containing the view gains or loses focus.
    309  *         </td>
    310  *     </tr>
    311  *
    312  *     <tr>
    313  *         <td rowspan="3">Attaching</td>
    314  *         <td><code>{@link #onAttachedToWindow()}</code></td>
    315  *         <td>Called when the view is attached to a window.
    316  *         </td>
    317  *     </tr>
    318  *
    319  *     <tr>
    320  *         <td><code>{@link #onDetachedFromWindow}</code></td>
    321  *         <td>Called when the view is detached from its window.
    322  *         </td>
    323  *     </tr>
    324  *
    325  *     <tr>
    326  *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
    327  *         <td>Called when the visibility of the window containing the view
    328  *         has changed.
    329  *         </td>
    330  *     </tr>
    331  *     </tbody>
    332  *
    333  * </table>
    334  * </p>
    335  *
    336  * <a name="IDs"></a>
    337  * <h3>IDs</h3>
    338  * Views may have an integer id associated with them. These ids are typically
    339  * assigned in the layout XML files, and are used to find specific views within
    340  * the view tree. A common pattern is to:
    341  * <ul>
    342  * <li>Define a Button in the layout file and assign it a unique ID.
    343  * <pre>
    344  * &lt;Button
    345  *     android:id="@+id/my_button"
    346  *     android:layout_width="wrap_content"
    347  *     android:layout_height="wrap_content"
    348  *     android:text="@string/my_button_text"/&gt;
    349  * </pre></li>
    350  * <li>From the onCreate method of an Activity, find the Button
    351  * <pre class="prettyprint">
    352  *      Button myButton = findViewById(R.id.my_button);
    353  * </pre></li>
    354  * </ul>
    355  * <p>
    356  * View IDs need not be unique throughout the tree, but it is good practice to
    357  * ensure that they are at least unique within the part of the tree you are
    358  * searching.
    359  * </p>
    360  *
    361  * <a name="Position"></a>
    362  * <h3>Position</h3>
    363  * <p>
    364  * The geometry of a view is that of a rectangle. A view has a location,
    365  * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
    366  * two dimensions, expressed as a width and a height. The unit for location
    367  * and dimensions is the pixel.
    368  * </p>
    369  *
    370  * <p>
    371  * It is possible to retrieve the location of a view by invoking the methods
    372  * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
    373  * coordinate of the rectangle representing the view. The latter returns the
    374  * top, or Y, coordinate of the rectangle representing the view. These methods
    375  * both return the location of the view relative to its parent. For instance,
    376  * when getLeft() returns 20, that means the view is located 20 pixels to the
    377  * right of the left edge of its direct parent.
    378  * </p>
    379  *
    380  * <p>
    381  * In addition, several convenience methods are offered to avoid unnecessary
    382  * computations, namely {@link #getRight()} and {@link #getBottom()}.
    383  * These methods return the coordinates of the right and bottom edges of the
    384  * rectangle representing the view. For instance, calling {@link #getRight()}
    385  * is similar to the following computation: <code>getLeft() + getWidth()</code>
    386  * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
    387  * </p>
    388  *
    389  * <a name="SizePaddingMargins"></a>
    390  * <h3>Size, padding and margins</h3>
    391  * <p>
    392  * The size of a view is expressed with a width and a height. A view actually
    393  * possess two pairs of width and height values.
    394  * </p>
    395  *
    396  * <p>
    397  * The first pair is known as <em>measured width</em> and
    398  * <em>measured height</em>. These dimensions define how big a view wants to be
    399  * within its parent (see <a href="#Layout">Layout</a> for more details.) The
    400  * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
    401  * and {@link #getMeasuredHeight()}.
    402  * </p>
    403  *
    404  * <p>
    405  * The second pair is simply known as <em>width</em> and <em>height</em>, or
    406  * sometimes <em>drawing width</em> and <em>drawing height</em>. These
    407  * dimensions define the actual size of the view on screen, at drawing time and
    408  * after layout. These values may, but do not have to, be different from the
    409  * measured width and height. The width and height can be obtained by calling
    410  * {@link #getWidth()} and {@link #getHeight()}.
    411  * </p>
    412  *
    413  * <p>
    414  * To measure its dimensions, a view takes into account its padding. The padding
    415  * is expressed in pixels for the left, top, right and bottom parts of the view.
    416  * Padding can be used to offset the content of the view by a specific amount of
    417  * pixels. For instance, a left padding of 2 will push the view's content by
    418  * 2 pixels to the right of the left edge. Padding can be set using the
    419  * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
    420  * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
    421  * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
    422  * {@link #getPaddingEnd()}.
    423  * </p>
    424  *
    425  * <p>
    426  * Even though a view can define a padding, it does not provide any support for
    427  * margins. However, view groups provide such a support. Refer to
    428  * {@link android.view.ViewGroup} and
    429  * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
    430  * </p>
    431  *
    432  * <a name="Layout"></a>
    433  * <h3>Layout</h3>
    434  * <p>
    435  * Layout is a two pass process: a measure pass and a layout pass. The measuring
    436  * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
    437  * of the view tree. Each view pushes dimension specifications down the tree
    438  * during the recursion. At the end of the measure pass, every view has stored
    439  * its measurements. The second pass happens in
    440  * {@link #layout(int,int,int,int)} and is also top-down. During
    441  * this pass each parent is responsible for positioning all of its children
    442  * using the sizes computed in the measure pass.
    443  * </p>
    444  *
    445  * <p>
    446  * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
    447  * {@link #getMeasuredHeight()} values must be set, along with those for all of
    448  * that view's descendants. A view's measured width and measured height values
    449  * must respect the constraints imposed by the view's parents. This guarantees
    450  * that at the end of the measure pass, all parents accept all of their
    451  * children's measurements. A parent view may call measure() more than once on
    452  * its children. For example, the parent may measure each child once with
    453  * unspecified dimensions to find out how big they want to be, then call
    454  * measure() on them again with actual numbers if the sum of all the children's
    455  * unconstrained sizes is too big or too small.
    456  * </p>
    457  *
    458  * <p>
    459  * The measure pass uses two classes to communicate dimensions. The
    460  * {@link MeasureSpec} class is used by views to tell their parents how they
    461  * want to be measured and positioned. The base LayoutParams class just
    462  * describes how big the view wants to be for both width and height. For each
    463  * dimension, it can specify one of:
    464  * <ul>
    465  * <li> an exact number
    466  * <li>MATCH_PARENT, which means the view wants to be as big as its parent
    467  * (minus padding)
    468  * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
    469  * enclose its content (plus padding).
    470  * </ul>
    471  * There are subclasses of LayoutParams for different subclasses of ViewGroup.
    472  * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
    473  * an X and Y value.
    474  * </p>
    475  *
    476  * <p>
    477  * MeasureSpecs are used to push requirements down the tree from parent to
    478  * child. A MeasureSpec can be in one of three modes:
    479  * <ul>
    480  * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
    481  * of a child view. For example, a LinearLayout may call measure() on its child
    482  * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
    483  * tall the child view wants to be given a width of 240 pixels.
    484  * <li>EXACTLY: This is used by the parent to impose an exact size on the
    485  * child. The child must use this size, and guarantee that all of its
    486  * descendants will fit within this size.
    487  * <li>AT_MOST: This is used by the parent to impose a maximum size on the
    488  * child. The child must guarantee that it and all of its descendants will fit
    489  * within this size.
    490  * </ul>
    491  * </p>
    492  *
    493  * <p>
    494  * To initiate a layout, call {@link #requestLayout}. This method is typically
    495  * called by a view on itself when it believes that is can no longer fit within
    496  * its current bounds.
    497  * </p>
    498  *
    499  * <a name="Drawing"></a>
    500  * <h3>Drawing</h3>
    501  * <p>
    502  * Drawing is handled by walking the tree and recording the drawing commands of
    503  * any View that needs to update. After this, the drawing commands of the
    504  * entire tree are issued to screen, clipped to the newly damaged area.
    505  * </p>
    506  *
    507  * <p>
    508  * The tree is largely recorded and drawn in order, with parents drawn before
    509  * (i.e., behind) their children, with siblings drawn in the order they appear
    510  * in the tree. If you set a background drawable for a View, then the View will
    511  * draw it before calling back to its <code>onDraw()</code> method. The child
    512  * drawing order can be overridden with
    513  * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
    514  * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
    515  * </p>
    516  *
    517  * <p>
    518  * To force a view to draw, call {@link #invalidate()}.
    519  * </p>
    520  *
    521  * <a name="EventHandlingThreading"></a>
    522  * <h3>Event Handling and Threading</h3>
    523  * <p>
    524  * The basic cycle of a view is as follows:
    525  * <ol>
    526  * <li>An event comes in and is dispatched to the appropriate view. The view
    527  * handles the event and notifies any listeners.</li>
    528  * <li>If in the course of processing the event, the view's bounds may need
    529  * to be changed, the view will call {@link #requestLayout()}.</li>
    530  * <li>Similarly, if in the course of processing the event the view's appearance
    531  * may need to be changed, the view will call {@link #invalidate()}.</li>
    532  * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
    533  * the framework will take care of measuring, laying out, and drawing the tree
    534  * as appropriate.</li>
    535  * </ol>
    536  * </p>
    537  *
    538  * <p><em>Note: The entire view tree is single threaded. You must always be on
    539  * the UI thread when calling any method on any view.</em>
    540  * If you are doing work on other threads and want to update the state of a view
    541  * from that thread, you should use a {@link Handler}.
    542  * </p>
    543  *
    544  * <a name="FocusHandling"></a>
    545  * <h3>Focus Handling</h3>
    546  * <p>
    547  * The framework will handle routine focus movement in response to user input.
    548  * This includes changing the focus as views are removed or hidden, or as new
    549  * views become available. Views indicate their willingness to take focus
    550  * through the {@link #isFocusable} method. To change whether a view can take
    551  * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
    552  * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
    553  * and can change this via {@link #setFocusableInTouchMode(boolean)}.
    554  * </p>
    555  * <p>
    556  * Focus movement is based on an algorithm which finds the nearest neighbor in a
    557  * given direction. In rare cases, the default algorithm may not match the
    558  * intended behavior of the developer. In these situations, you can provide
    559  * explicit overrides by using these XML attributes in the layout file:
    560  * <pre>
    561  * nextFocusDown
    562  * nextFocusLeft
    563  * nextFocusRight
    564  * nextFocusUp
    565  * </pre>
    566  * </p>
    567  *
    568  *
    569  * <p>
    570  * To get a particular view to take focus, call {@link #requestFocus()}.
    571  * </p>
    572  *
    573  * <a name="TouchMode"></a>
    574  * <h3>Touch Mode</h3>
    575  * <p>
    576  * When a user is navigating a user interface via directional keys such as a D-pad, it is
    577  * necessary to give focus to actionable items such as buttons so the user can see
    578  * what will take input.  If the device has touch capabilities, however, and the user
    579  * begins interacting with the interface by touching it, it is no longer necessary to
    580  * always highlight, or give focus to, a particular view.  This motivates a mode
    581  * for interaction named 'touch mode'.
    582  * </p>
    583  * <p>
    584  * For a touch capable device, once the user touches the screen, the device
    585  * will enter touch mode.  From this point onward, only views for which
    586  * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
    587  * Other views that are touchable, like buttons, will not take focus when touched; they will
    588  * only fire the on click listeners.
    589  * </p>
    590  * <p>
    591  * Any time a user hits a directional key, such as a D-pad direction, the view device will
    592  * exit touch mode, and find a view to take focus, so that the user may resume interacting
    593  * with the user interface without touching the screen again.
    594  * </p>
    595  * <p>
    596  * The touch mode state is maintained across {@link android.app.Activity}s.  Call
    597  * {@link #isInTouchMode} to see whether the device is currently in touch mode.
    598  * </p>
    599  *
    600  * <a name="Scrolling"></a>
    601  * <h3>Scrolling</h3>
    602  * <p>
    603  * The framework provides basic support for views that wish to internally
    604  * scroll their content. This includes keeping track of the X and Y scroll
    605  * offset as well as mechanisms for drawing scrollbars. See
    606  * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
    607  * {@link #awakenScrollBars()} for more details.
    608  * </p>
    609  *
    610  * <a name="Tags"></a>
    611  * <h3>Tags</h3>
    612  * <p>
    613  * Unlike IDs, tags are not used to identify views. Tags are essentially an
    614  * extra piece of information that can be associated with a view. They are most
    615  * often used as a convenience to store data related to views in the views
    616  * themselves rather than by putting them in a separate structure.
    617  * </p>
    618  * <p>
    619  * Tags may be specified with character sequence values in layout XML as either
    620  * a single tag using the {@link android.R.styleable#View_tag android:tag}
    621  * attribute or multiple tags using the {@code <tag>} child element:
    622  * <pre>
    623  *     &lt;View ...
    624  *           android:tag="@string/mytag_value" /&gt;
    625  *     &lt;View ...&gt;
    626  *         &lt;tag android:id="@+id/mytag"
    627  *              android:value="@string/mytag_value" /&gt;
    628  *     &lt;/View>
    629  * </pre>
    630  * </p>
    631  * <p>
    632  * Tags may also be specified with arbitrary objects from code using
    633  * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
    634  * </p>
    635  *
    636  * <a name="Themes"></a>
    637  * <h3>Themes</h3>
    638  * <p>
    639  * By default, Views are created using the theme of the Context object supplied
    640  * to their constructor; however, a different theme may be specified by using
    641  * the {@link android.R.styleable#View_theme android:theme} attribute in layout
    642  * XML or by passing a {@link ContextThemeWrapper} to the constructor from
    643  * code.
    644  * </p>
    645  * <p>
    646  * When the {@link android.R.styleable#View_theme android:theme} attribute is
    647  * used in XML, the specified theme is applied on top of the inflation
    648  * context's theme (see {@link LayoutInflater}) and used for the view itself as
    649  * well as any child elements.
    650  * </p>
    651  * <p>
    652  * In the following example, both views will be created using the Material dark
    653  * color scheme; however, because an overlay theme is used which only defines a
    654  * subset of attributes, the value of
    655  * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
    656  * the inflation context's theme (e.g. the Activity theme) will be preserved.
    657  * <pre>
    658  *     &lt;LinearLayout
    659  *             ...
    660  *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
    661  *         &lt;View ...&gt;
    662  *     &lt;/LinearLayout&gt;
    663  * </pre>
    664  * </p>
    665  *
    666  * <a name="Properties"></a>
    667  * <h3>Properties</h3>
    668  * <p>
    669  * The View class exposes an {@link #ALPHA} property, as well as several transform-related
    670  * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
    671  * available both in the {@link Property} form as well as in similarly-named setter/getter
    672  * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
    673  * be used to set persistent state associated with these rendering-related properties on the view.
    674  * The properties and methods can also be used in conjunction with
    675  * {@link android.animation.Animator Animator}-based animations, described more in the
    676  * <a href="#Animation">Animation</a> section.
    677  * </p>
    678  *
    679  * <a name="Animation"></a>
    680  * <h3>Animation</h3>
    681  * <p>
    682  * Starting with Android 3.0, the preferred way of animating views is to use the
    683  * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
    684  * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
    685  * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
    686  * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
    687  * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
    688  * makes animating these View properties particularly easy and efficient.
    689  * </p>
    690  * <p>
    691  * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
    692  * You can attach an {@link Animation} object to a view using
    693  * {@link #setAnimation(Animation)} or
    694  * {@link #startAnimation(Animation)}. The animation can alter the scale,
    695  * rotation, translation and alpha of a view over time. If the animation is
    696  * attached to a view that has children, the animation will affect the entire
    697  * subtree rooted by that node. When an animation is started, the framework will
    698  * take care of redrawing the appropriate views until the animation completes.
    699  * </p>
    700  *
    701  * <a name="Security"></a>
    702  * <h3>Security</h3>
    703  * <p>
    704  * Sometimes it is essential that an application be able to verify that an action
    705  * is being performed with the full knowledge and consent of the user, such as
    706  * granting a permission request, making a purchase or clicking on an advertisement.
    707  * Unfortunately, a malicious application could try to spoof the user into
    708  * performing these actions, unaware, by concealing the intended purpose of the view.
    709  * As a remedy, the framework offers a touch filtering mechanism that can be used to
    710  * improve the security of views that provide access to sensitive functionality.
    711  * </p><p>
    712  * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
    713  * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
    714  * will discard touches that are received whenever the view's window is obscured by
    715  * another visible window.  As a result, the view will not receive touches whenever a
    716  * toast, dialog or other window appears above the view's window.
    717  * </p><p>
    718  * For more fine-grained control over security, consider overriding the
    719  * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
    720  * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
    721  * </p>
    722  *
    723  * @attr ref android.R.styleable#View_accessibilityHeading
    724  * @attr ref android.R.styleable#View_alpha
    725  * @attr ref android.R.styleable#View_background
    726  * @attr ref android.R.styleable#View_clickable
    727  * @attr ref android.R.styleable#View_contentDescription
    728  * @attr ref android.R.styleable#View_drawingCacheQuality
    729  * @attr ref android.R.styleable#View_duplicateParentState
    730  * @attr ref android.R.styleable#View_id
    731  * @attr ref android.R.styleable#View_requiresFadingEdge
    732  * @attr ref android.R.styleable#View_fadeScrollbars
    733  * @attr ref android.R.styleable#View_fadingEdgeLength
    734  * @attr ref android.R.styleable#View_filterTouchesWhenObscured
    735  * @attr ref android.R.styleable#View_fitsSystemWindows
    736  * @attr ref android.R.styleable#View_isScrollContainer
    737  * @attr ref android.R.styleable#View_focusable
    738  * @attr ref android.R.styleable#View_focusableInTouchMode
    739  * @attr ref android.R.styleable#View_focusedByDefault
    740  * @attr ref android.R.styleable#View_hapticFeedbackEnabled
    741  * @attr ref android.R.styleable#View_keepScreenOn
    742  * @attr ref android.R.styleable#View_keyboardNavigationCluster
    743  * @attr ref android.R.styleable#View_layerType
    744  * @attr ref android.R.styleable#View_layoutDirection
    745  * @attr ref android.R.styleable#View_longClickable
    746  * @attr ref android.R.styleable#View_minHeight
    747  * @attr ref android.R.styleable#View_minWidth
    748  * @attr ref android.R.styleable#View_nextClusterForward
    749  * @attr ref android.R.styleable#View_nextFocusDown
    750  * @attr ref android.R.styleable#View_nextFocusLeft
    751  * @attr ref android.R.styleable#View_nextFocusRight
    752  * @attr ref android.R.styleable#View_nextFocusUp
    753  * @attr ref android.R.styleable#View_onClick
    754  * @attr ref android.R.styleable#View_outlineSpotShadowColor
    755  * @attr ref android.R.styleable#View_outlineAmbientShadowColor
    756  * @attr ref android.R.styleable#View_padding
    757  * @attr ref android.R.styleable#View_paddingHorizontal
    758  * @attr ref android.R.styleable#View_paddingVertical
    759  * @attr ref android.R.styleable#View_paddingBottom
    760  * @attr ref android.R.styleable#View_paddingLeft
    761  * @attr ref android.R.styleable#View_paddingRight
    762  * @attr ref android.R.styleable#View_paddingTop
    763  * @attr ref android.R.styleable#View_paddingStart
    764  * @attr ref android.R.styleable#View_paddingEnd
    765  * @attr ref android.R.styleable#View_saveEnabled
    766  * @attr ref android.R.styleable#View_rotation
    767  * @attr ref android.R.styleable#View_rotationX
    768  * @attr ref android.R.styleable#View_rotationY
    769  * @attr ref android.R.styleable#View_scaleX
    770  * @attr ref android.R.styleable#View_scaleY
    771  * @attr ref android.R.styleable#View_scrollX
    772  * @attr ref android.R.styleable#View_scrollY
    773  * @attr ref android.R.styleable#View_scrollbarSize
    774  * @attr ref android.R.styleable#View_scrollbarStyle
    775  * @attr ref android.R.styleable#View_scrollbars
    776  * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
    777  * @attr ref android.R.styleable#View_scrollbarFadeDuration
    778  * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
    779  * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
    780  * @attr ref android.R.styleable#View_scrollbarThumbVertical
    781  * @attr ref android.R.styleable#View_scrollbarTrackVertical
    782  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
    783  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
    784  * @attr ref android.R.styleable#View_stateListAnimator
    785  * @attr ref android.R.styleable#View_transitionName
    786  * @attr ref android.R.styleable#View_soundEffectsEnabled
    787  * @attr ref android.R.styleable#View_tag
    788  * @attr ref android.R.styleable#View_textAlignment
    789  * @attr ref android.R.styleable#View_textDirection
    790  * @attr ref android.R.styleable#View_transformPivotX
    791  * @attr ref android.R.styleable#View_transformPivotY
    792  * @attr ref android.R.styleable#View_translationX
    793  * @attr ref android.R.styleable#View_translationY
    794  * @attr ref android.R.styleable#View_translationZ
    795  * @attr ref android.R.styleable#View_visibility
    796  * @attr ref android.R.styleable#View_theme
    797  *
    798  * @see android.view.ViewGroup
    799  */
    800 @UiThread
    801 public class View implements Drawable.Callback, KeyEvent.Callback,
    802         AccessibilityEventSource {
    803     @UnsupportedAppUsage
    804     private static final boolean DBG = false;
    805 
    806     /** @hide */
    807     public static boolean DEBUG_DRAW = false;
    808 
    809     /**
    810      * The logging tag used by this class with android.util.Log.
    811      */
    812     protected static final String VIEW_LOG_TAG = "View";
    813 
    814     /**
    815      * The logging tag used by this class when logging verbose, autofill-related messages.
    816      */
    817     // NOTE: We cannot use android.view.autofill.Helper.sVerbose because that variable is not
    818     // set if a session is not started.
    819     private static final String AUTOFILL_LOG_TAG = "View.Autofill";
    820 
    821     /**
    822      * The logging tag used by this class when logging content capture-related messages.
    823      */
    824     private static final String CONTENT_CAPTURE_LOG_TAG = "View.ContentCapture";
    825 
    826     private static final boolean DEBUG_CONTENT_CAPTURE = false;
    827 
    828     /**
    829      * When set to true, this view will save its attribute data.
    830      *
    831      * @hide
    832      */
    833     public static boolean sDebugViewAttributes = false;
    834 
    835     /**
    836      * When set to this application package view will save its attribute data.
    837      *
    838      * @hide
    839      */
    840     public static String sDebugViewAttributesApplicationPackage;
    841 
    842     /**
    843      * Used to mark a View that has no ID.
    844      */
    845     public static final int NO_ID = -1;
    846 
    847     /**
    848      * Last ID that is given to Views that are no part of activities.
    849      *
    850      * {@hide}
    851      */
    852     public static final int LAST_APP_AUTOFILL_ID = Integer.MAX_VALUE / 2;
    853 
    854     /**
    855      * Attribute to find the autofilled highlight
    856      *
    857      * @see #getAutofilledDrawable()
    858      */
    859     private static final int[] AUTOFILL_HIGHLIGHT_ATTR =
    860             new int[]{android.R.attr.autofilledHighlight};
    861 
    862     /**
    863      * Signals that compatibility booleans have been initialized according to
    864      * target SDK versions.
    865      */
    866     private static boolean sCompatibilityDone = false;
    867 
    868     /**
    869      * Use the old (broken) way of building MeasureSpecs.
    870      */
    871     private static boolean sUseBrokenMakeMeasureSpec = false;
    872 
    873     /**
    874      * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
    875      */
    876     static boolean sUseZeroUnspecifiedMeasureSpec = false;
    877 
    878     /**
    879      * Ignore any optimizations using the measure cache.
    880      */
    881     private static boolean sIgnoreMeasureCache = false;
    882 
    883     /**
    884      * Ignore an optimization that skips unnecessary EXACTLY layout passes.
    885      */
    886     private static boolean sAlwaysRemeasureExactly = false;
    887 
    888     /**
    889      * Allow setForeground/setBackground to be called (and ignored) on a textureview,
    890      * without throwing
    891      */
    892     static boolean sTextureViewIgnoresDrawableSetters = false;
    893 
    894     /**
    895      * Prior to N, some ViewGroups would not convert LayoutParams properly even though both extend
    896      * MarginLayoutParams. For instance, converting LinearLayout.LayoutParams to
    897      * RelativeLayout.LayoutParams would lose margin information. This is fixed on N but target API
    898      * check is implemented for backwards compatibility.
    899      *
    900      * {@hide}
    901      */
    902     protected static boolean sPreserveMarginParamsInLayoutParamConversion;
    903 
    904     /**
    905      * Prior to N, when drag enters into child of a view that has already received an
    906      * ACTION_DRAG_ENTERED event, the parent doesn't get a ACTION_DRAG_EXITED event.
    907      * ACTION_DRAG_LOCATION and ACTION_DROP were delivered to the parent of a view that returned
    908      * false from its event handler for these events.
    909      * Starting from N, the parent will get ACTION_DRAG_EXITED event before the child gets its
    910      * ACTION_DRAG_ENTERED. ACTION_DRAG_LOCATION and ACTION_DROP are never propagated to the parent.
    911      * sCascadedDragDrop is true for pre-N apps for backwards compatibility implementation.
    912      */
    913     static boolean sCascadedDragDrop;
    914 
    915     /**
    916      * Prior to O, auto-focusable didn't exist and widgets such as ListView use hasFocusable
    917      * to determine things like whether or not to permit item click events. We can't break
    918      * apps that do this just because more things (clickable things) are now auto-focusable
    919      * and they would get different results, so give old behavior to old apps.
    920      */
    921     static boolean sHasFocusableExcludeAutoFocusable;
    922 
    923     /**
    924      * Prior to O, auto-focusable didn't exist and views marked as clickable weren't implicitly
    925      * made focusable by default. As a result, apps could (incorrectly) change the clickable
    926      * setting of views off the UI thread. Now that clickable can effect the focusable state,
    927      * changing the clickable attribute off the UI thread will cause an exception (since changing
    928      * the focusable state checks). In order to prevent apps from crashing, we will handle this
    929      * specific case and just not notify parents on new focusables resulting from marking views
    930      * clickable from outside the UI thread.
    931      */
    932     private static boolean sAutoFocusableOffUIThreadWontNotifyParents;
    933 
    934     /**
    935      * Prior to P things like setScaleX() allowed passing float values that were bogus such as
    936      * Float.NaN. If the app is targetting P or later then passing these values will result in an
    937      * exception being thrown. If the app is targetting an earlier SDK version, then we will
    938      * silently clamp these values to avoid crashes elsewhere when the rendering code hits
    939      * these bogus values.
    940      */
    941     private static boolean sThrowOnInvalidFloatProperties;
    942 
    943     /**
    944      * Prior to P, {@code #startDragAndDrop} accepts a builder which produces an empty drag shadow.
    945      * Currently zero size SurfaceControl cannot be created thus we create a dummy 1x1 surface
    946      * instead.
    947      */
    948     private static boolean sAcceptZeroSizeDragShadow;
    949 
    950     /**
    951      * Prior to Q, {@link #dispatchApplyWindowInsets} had some issues:
    952      * <ul>
    953      *     <li>The modified insets changed by {@link #onApplyWindowInsets} were passed to the
    954      *     entire view hierarchy in prefix order, including siblings as well as siblings of parents
    955      *     further down the hierarchy. This violates the basic concepts of the view hierarchy, and
    956      *     thus, the hierarchical dispatching mechanism was hard to use for apps.</li>
    957      *
    958      *     <li>Dispatch was stopped after the insets were fully consumed. This is somewhat confusing
    959      *     for developers, but more importantly, by adding more granular information to
    960      *     {@link WindowInsets} it becomes really cumbersome to define what consumed actually means
    961      *     </li>
    962      * </ul>
    963      *
    964      * In order to make window inset dispatching work properly, we dispatch window insets
    965      * in the view hierarchy in a proper hierarchical manner and don't stop dispatching if the
    966      * insets are consumed if this flag is set to {@code false}.
    967      */
    968     static boolean sBrokenInsetsDispatch;
    969 
    970     /**
    971      * Prior to Q, calling
    972      * {@link com.android.internal.policy.DecorView#setBackgroundDrawable(Drawable)}
    973      * did not call update the window format so the opacity of the background was not correctly
    974      * applied to the window. Some applications rely on this misbehavior to work properly.
    975      * <p>
    976      * From Q, {@link com.android.internal.policy.DecorView#setBackgroundDrawable(Drawable)} is
    977      * the same as {@link com.android.internal.policy.DecorView#setWindowBackground(Drawable)}
    978      * which updates the window format.
    979      * @hide
    980      */
    981     protected static boolean sBrokenWindowBackground;
    982 
    983     /** @hide */
    984     @IntDef({NOT_FOCUSABLE, FOCUSABLE, FOCUSABLE_AUTO})
    985     @Retention(RetentionPolicy.SOURCE)
    986     public @interface Focusable {}
    987 
    988     /**
    989      * This view does not want keystrokes.
    990      * <p>
    991      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
    992      * android:focusable}.
    993      */
    994     public static final int NOT_FOCUSABLE = 0x00000000;
    995 
    996     /**
    997      * This view wants keystrokes.
    998      * <p>
    999      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
   1000      * android:focusable}.
   1001      */
   1002     public static final int FOCUSABLE = 0x00000001;
   1003 
   1004     /**
   1005      * This view determines focusability automatically. This is the default.
   1006      * <p>
   1007      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
   1008      * android:focusable}.
   1009      */
   1010     public static final int FOCUSABLE_AUTO = 0x00000010;
   1011 
   1012     /**
   1013      * Mask for use with setFlags indicating bits used for focus.
   1014      */
   1015     private static final int FOCUSABLE_MASK = 0x00000011;
   1016 
   1017     /**
   1018      * This view will adjust its padding to fit sytem windows (e.g. status bar)
   1019      */
   1020     private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
   1021 
   1022     /** @hide */
   1023     @IntDef({VISIBLE, INVISIBLE, GONE})
   1024     @Retention(RetentionPolicy.SOURCE)
   1025     public @interface Visibility {}
   1026 
   1027     /**
   1028      * This view is visible.
   1029      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
   1030      * android:visibility}.
   1031      */
   1032     public static final int VISIBLE = 0x00000000;
   1033 
   1034     /**
   1035      * This view is invisible, but it still takes up space for layout purposes.
   1036      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
   1037      * android:visibility}.
   1038      */
   1039     public static final int INVISIBLE = 0x00000004;
   1040 
   1041     /**
   1042      * This view is invisible, and it doesn't take any space for layout
   1043      * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
   1044      * android:visibility}.
   1045      */
   1046     public static final int GONE = 0x00000008;
   1047 
   1048     /**
   1049      * Mask for use with setFlags indicating bits used for visibility.
   1050      * {@hide}
   1051      */
   1052     static final int VISIBILITY_MASK = 0x0000000C;
   1053 
   1054     private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
   1055 
   1056     /**
   1057      * Hint indicating that this view can be autofilled with an email address.
   1058      *
   1059      * <p>Can be used with either {@link #setAutofillHints(String[])} or
   1060      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
   1061      * value should be <code>{@value #AUTOFILL_HINT_EMAIL_ADDRESS}</code>).
   1062      *
   1063      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
   1064      */
   1065     public static final String AUTOFILL_HINT_EMAIL_ADDRESS = "emailAddress";
   1066 
   1067     /**
   1068      * Hint indicating that this view can be autofilled with a user's real name.
   1069      *
   1070      * <p>Can be used with either {@link #setAutofillHints(String[])} or
   1071      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
   1072      * value should be <code>{@value #AUTOFILL_HINT_NAME}</code>).
   1073      *
   1074      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
   1075      */
   1076     public static final String AUTOFILL_HINT_NAME = "name";
   1077 
   1078     /**
   1079      * Hint indicating that this view can be autofilled with a username.
   1080      *
   1081      * <p>Can be used with either {@link #setAutofillHints(String[])} or
   1082      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
   1083      * value should be <code>{@value #AUTOFILL_HINT_USERNAME}</code>).
   1084      *
   1085      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
   1086      */
   1087     public static final String AUTOFILL_HINT_USERNAME = "username";
   1088 
   1089     /**
   1090      * Hint indicating that this view can be autofilled with a password.
   1091      *
   1092      * <p>Can be used with either {@link #setAutofillHints(String[])} or
   1093      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
   1094      * value should be <code>{@value #AUTOFILL_HINT_PASSWORD}</code>).
   1095      *
   1096      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
   1097      */
   1098     public static final String AUTOFILL_HINT_PASSWORD = "password";
   1099 
   1100     /**
   1101      * Hint indicating that this view can be autofilled with a phone number.
   1102      *
   1103      * <p>Can be used with either {@link #setAutofillHints(String[])} or
   1104      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
   1105      * value should be <code>{@value #AUTOFILL_HINT_PHONE}</code>).
   1106      *
   1107      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
   1108      */
   1109     public static final String AUTOFILL_HINT_PHONE = "phone";
   1110 
   1111     /**
   1112      * Hint indicating that this view can be autofilled with a postal address.
   1113      *
   1114      * <p>Can be used with either {@link #setAutofillHints(String[])} or
   1115      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
   1116      * value should be <code>{@value #AUTOFILL_HINT_POSTAL_ADDRESS}</code>).
   1117      *
   1118      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
   1119      */
   1120     public static final String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress";
   1121 
   1122     /**
   1123      * Hint indicating that this view can be autofilled with a postal code.
   1124      *
   1125      * <p>Can be used with either {@link #setAutofillHints(String[])} or
   1126      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
   1127      * value should be <code>{@value #AUTOFILL_HINT_POSTAL_CODE}</code>).
   1128      *
   1129      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
   1130      */
   1131     public static final String AUTOFILL_HINT_POSTAL_CODE = "postalCode";
   1132 
   1133     /**
   1134      * Hint indicating that this view can be autofilled with a credit card number.
   1135      *
   1136      * <p>Can be used with either {@link #setAutofillHints(String[])} or
   1137      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
   1138      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_NUMBER}</code>).
   1139      *
   1140      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
   1141      */
   1142     public static final String AUTOFILL_HINT_CREDIT_CARD_NUMBER = "creditCardNumber";
   1143 
   1144     /**
   1145      * Hint indicating that this view can be autofilled with a credit card security code.
   1146      *
   1147      * <p>Can be used with either {@link #setAutofillHints(String[])} or
   1148      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
   1149      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE}</code>).
   1150      *
   1151      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
   1152      */
   1153     public static final String AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE = "creditCardSecurityCode";
   1154 
   1155     /**
   1156      * Hint indicating that this view can be autofilled with a credit card expiration date.
   1157      *
   1158      * <p>It should be used when the credit card expiration date is represented by just one view;
   1159      * if it is represented by more than one (for example, one view for the month and another view
   1160      * for the year), then each of these views should use the hint specific for the unit
   1161      * ({@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
   1162      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH},
   1163      * or {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}).
   1164      *
   1165      * <p>Can be used with either {@link #setAutofillHints(String[])} or
   1166      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
   1167      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE}</code>).
   1168      *
   1169      * <p>When annotating a view with this hint, it's recommended to use a date autofill value to
   1170      * avoid ambiguity when the autofill service provides a value for it. To understand why a
   1171      * value can be ambiguous, consider "April of 2020", which could be represented as either of
   1172      * the following options:
   1173      *
   1174      * <ul>
   1175      *   <li>{@code "04/2020"}
   1176      *   <li>{@code "4/2020"}
   1177      *   <li>{@code "2020/04"}
   1178      *   <li>{@code "2020/4"}
   1179      *   <li>{@code "April/2020"}
   1180      *   <li>{@code "Apr/2020"}
   1181      * </ul>
   1182      *
   1183      * <p>You define a date autofill value for the view by overriding the following methods:
   1184      *
   1185      * <ol>
   1186      *   <li>{@link #getAutofillType()} to return {@link #AUTOFILL_TYPE_DATE}.
   1187      *   <li>{@link #getAutofillValue()} to return a
   1188      *       {@link AutofillValue#forDate(long) date autofillvalue}.
   1189      *   <li>{@link #autofill(AutofillValue)} to expect a data autofillvalue.
   1190      * </ol>
   1191      *
   1192      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
   1193      */
   1194     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE =
   1195             "creditCardExpirationDate";
   1196 
   1197     /**
   1198      * Hint indicating that this view can be autofilled with a credit card expiration month.
   1199      *
   1200      * <p>Can be used with either {@link #setAutofillHints(String[])} or
   1201      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
   1202      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH}</code>).
   1203      *
   1204      * <p>When annotating a view with this hint, it's recommended to use a text autofill value
   1205      * whose value is the numerical representation of the month, starting on {@code 1} to avoid
   1206      * ambiguity when the autofill service provides a value for it. To understand why a
   1207      * value can be ambiguous, consider "January", which could be represented as either of
   1208      *
   1209      * <ul>
   1210      *   <li>{@code "1"}: recommended way.
   1211      *   <li>{@code "0"}: if following the {@link Calendar#MONTH} convention.
   1212      *   <li>{@code "January"}: full name, in English.
   1213      *   <li>{@code "jan"}: abbreviated name, in English.
   1214      *   <li>{@code "Janeiro"}: full name, in another language.
   1215      * </ul>
   1216      *
   1217      * <p>Another recommended approach is to use a date autofill value - see
   1218      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE} for more details.
   1219      *
   1220      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
   1221      */
   1222     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH =
   1223             "creditCardExpirationMonth";
   1224 
   1225     /**
   1226      * Hint indicating that this view can be autofilled with a credit card expiration year.
   1227      *
   1228      * <p>Can be used with either {@link #setAutofillHints(String[])} or
   1229      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
   1230      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}</code>).
   1231      *
   1232      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
   1233      */
   1234     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR =
   1235             "creditCardExpirationYear";
   1236 
   1237     /**
   1238      * Hint indicating that this view can be autofilled with a credit card expiration day.
   1239      *
   1240      * <p>Can be used with either {@link #setAutofillHints(String[])} or
   1241      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
   1242      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY}</code>).
   1243      *
   1244      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
   1245      */
   1246     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY = "creditCardExpirationDay";
   1247 
   1248     /**
   1249      * Hints for the autofill services that describes the content of the view.
   1250      */
   1251     private @Nullable String[] mAutofillHints;
   1252 
   1253     /**
   1254      * Autofill id, lazily created on calls to {@link #getAutofillId()}.
   1255      */
   1256     private AutofillId mAutofillId;
   1257 
   1258     /** @hide */
   1259     @IntDef(prefix = { "AUTOFILL_TYPE_" }, value = {
   1260             AUTOFILL_TYPE_NONE,
   1261             AUTOFILL_TYPE_TEXT,
   1262             AUTOFILL_TYPE_TOGGLE,
   1263             AUTOFILL_TYPE_LIST,
   1264             AUTOFILL_TYPE_DATE
   1265     })
   1266     @Retention(RetentionPolicy.SOURCE)
   1267     public @interface AutofillType {}
   1268 
   1269     /**
   1270      * Autofill type for views that cannot be autofilled.
   1271      *
   1272      * <p>Typically used when the view is read-only; for example, a text label.
   1273      *
   1274      * @see #getAutofillType()
   1275      */
   1276     public static final int AUTOFILL_TYPE_NONE = 0;
   1277 
   1278     /**
   1279      * Autofill type for a text field, which is filled by a {@link CharSequence}.
   1280      *
   1281      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
   1282      * {@link AutofillValue#forText(CharSequence)}, and the value passed to autofill a
   1283      * {@link View} can be fetched through {@link AutofillValue#getTextValue()}.
   1284      *
   1285      * @see #getAutofillType()
   1286      */
   1287     public static final int AUTOFILL_TYPE_TEXT = 1;
   1288 
   1289     /**
   1290      * Autofill type for a togglable field, which is filled by a {@code boolean}.
   1291      *
   1292      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
   1293      * {@link AutofillValue#forToggle(boolean)}, and the value passed to autofill a
   1294      * {@link View} can be fetched through {@link AutofillValue#getToggleValue()}.
   1295      *
   1296      * @see #getAutofillType()
   1297      */
   1298     public static final int AUTOFILL_TYPE_TOGGLE = 2;
   1299 
   1300     /**
   1301      * Autofill type for a selection list field, which is filled by an {@code int}
   1302      * representing the element index inside the list (starting at {@code 0}).
   1303      *
   1304      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
   1305      * {@link AutofillValue#forList(int)}, and the value passed to autofill a
   1306      * {@link View} can be fetched through {@link AutofillValue#getListValue()}.
   1307      *
   1308      * <p>The available options in the selection list are typically provided by
   1309      * {@link android.app.assist.AssistStructure.ViewNode#getAutofillOptions()}.
   1310      *
   1311      * @see #getAutofillType()
   1312      */
   1313     public static final int AUTOFILL_TYPE_LIST = 3;
   1314 
   1315 
   1316     /**
   1317      * Autofill type for a field that contains a date, which is represented by a long representing
   1318      * the number of milliseconds since the standard base time known as "the epoch", namely
   1319      * January 1, 1970, 00:00:00 GMT (see {@link java.util.Date#getTime()}.
   1320      *
   1321      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
   1322      * {@link AutofillValue#forDate(long)}, and the values passed to
   1323      * autofill a {@link View} can be fetched through {@link AutofillValue#getDateValue()}.
   1324      *
   1325      * @see #getAutofillType()
   1326      */
   1327     public static final int AUTOFILL_TYPE_DATE = 4;
   1328 
   1329     /** @hide */
   1330     @IntDef(prefix = { "IMPORTANT_FOR_AUTOFILL_" }, value = {
   1331             IMPORTANT_FOR_AUTOFILL_AUTO,
   1332             IMPORTANT_FOR_AUTOFILL_YES,
   1333             IMPORTANT_FOR_AUTOFILL_NO,
   1334             IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
   1335             IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
   1336     })
   1337     @Retention(RetentionPolicy.SOURCE)
   1338     public @interface AutofillImportance {}
   1339 
   1340     /**
   1341      * Automatically determine whether a view is important for autofill.
   1342      *
   1343      * @see #isImportantForAutofill()
   1344      * @see #setImportantForAutofill(int)
   1345      */
   1346     public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0x0;
   1347 
   1348     /**
   1349      * The view is important for autofill, and its children (if any) will be traversed.
   1350      *
   1351      * @see #isImportantForAutofill()
   1352      * @see #setImportantForAutofill(int)
   1353      */
   1354     public static final int IMPORTANT_FOR_AUTOFILL_YES = 0x1;
   1355 
   1356     /**
   1357      * The view is not important for autofill, but its children (if any) will be traversed.
   1358      *
   1359      * @see #isImportantForAutofill()
   1360      * @see #setImportantForAutofill(int)
   1361      */
   1362     public static final int IMPORTANT_FOR_AUTOFILL_NO = 0x2;
   1363 
   1364     /**
   1365      * The view is important for autofill, but its children (if any) will not be traversed.
   1366      *
   1367      * @see #isImportantForAutofill()
   1368      * @see #setImportantForAutofill(int)
   1369      */
   1370     public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 0x4;
   1371 
   1372     /**
   1373      * The view is not important for autofill, and its children (if any) will not be traversed.
   1374      *
   1375      * @see #isImportantForAutofill()
   1376      * @see #setImportantForAutofill(int)
   1377      */
   1378     public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 0x8;
   1379 
   1380     /** @hide */
   1381     @IntDef(flag = true, prefix = { "AUTOFILL_FLAG_" }, value = {
   1382             AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
   1383     })
   1384     @Retention(RetentionPolicy.SOURCE)
   1385     public @interface AutofillFlags {}
   1386 
   1387     /**
   1388      * Flag requesting you to add views that are marked as not important for autofill
   1389      * (see {@link #setImportantForAutofill(int)}) to a {@link ViewStructure}.
   1390      */
   1391     public static final int AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x1;
   1392 
   1393     /**
   1394      * This view is enabled. Interpretation varies by subclass.
   1395      * Use with ENABLED_MASK when calling setFlags.
   1396      * {@hide}
   1397      */
   1398     static final int ENABLED = 0x00000000;
   1399 
   1400     /**
   1401      * This view is disabled. Interpretation varies by subclass.
   1402      * Use with ENABLED_MASK when calling setFlags.
   1403      * {@hide}
   1404      */
   1405     static final int DISABLED = 0x00000020;
   1406 
   1407    /**
   1408     * Mask for use with setFlags indicating bits used for indicating whether
   1409     * this view is enabled
   1410     * {@hide}
   1411     */
   1412     static final int ENABLED_MASK = 0x00000020;
   1413 
   1414     /**
   1415      * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
   1416      * called and further optimizations will be performed. It is okay to have
   1417      * this flag set and a background. Use with DRAW_MASK when calling setFlags.
   1418      * {@hide}
   1419      */
   1420     static final int WILL_NOT_DRAW = 0x00000080;
   1421 
   1422     /**
   1423      * Mask for use with setFlags indicating bits used for indicating whether
   1424      * this view is will draw
   1425      * {@hide}
   1426      */
   1427     static final int DRAW_MASK = 0x00000080;
   1428 
   1429     /**
   1430      * <p>This view doesn't show scrollbars.</p>
   1431      * {@hide}
   1432      */
   1433     static final int SCROLLBARS_NONE = 0x00000000;
   1434 
   1435     /**
   1436      * <p>This view shows horizontal scrollbars.</p>
   1437      * {@hide}
   1438      */
   1439     static final int SCROLLBARS_HORIZONTAL = 0x00000100;
   1440 
   1441     /**
   1442      * <p>This view shows vertical scrollbars.</p>
   1443      * {@hide}
   1444      */
   1445     static final int SCROLLBARS_VERTICAL = 0x00000200;
   1446 
   1447     /**
   1448      * <p>Mask for use with setFlags indicating bits used for indicating which
   1449      * scrollbars are enabled.</p>
   1450      * {@hide}
   1451      */
   1452     static final int SCROLLBARS_MASK = 0x00000300;
   1453 
   1454     /**
   1455      * Indicates that the view should filter touches when its window is obscured.
   1456      * Refer to the class comments for more information about this security feature.
   1457      * {@hide}
   1458      */
   1459     static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
   1460 
   1461     /**
   1462      * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
   1463      * that they are optional and should be skipped if the window has
   1464      * requested system UI flags that ignore those insets for layout.
   1465      */
   1466     static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
   1467 
   1468     /**
   1469      * <p>This view doesn't show fading edges.</p>
   1470      * {@hide}
   1471      */
   1472     static final int FADING_EDGE_NONE = 0x00000000;
   1473 
   1474     /**
   1475      * <p>This view shows horizontal fading edges.</p>
   1476      * {@hide}
   1477      */
   1478     static final int FADING_EDGE_HORIZONTAL = 0x00001000;
   1479 
   1480     /**
   1481      * <p>This view shows vertical fading edges.</p>
   1482      * {@hide}
   1483      */
   1484     static final int FADING_EDGE_VERTICAL = 0x00002000;
   1485 
   1486     /**
   1487      * <p>Mask for use with setFlags indicating bits used for indicating which
   1488      * fading edges are enabled.</p>
   1489      * {@hide}
   1490      */
   1491     static final int FADING_EDGE_MASK = 0x00003000;
   1492 
   1493     /**
   1494      * <p>Indicates this view can be clicked. When clickable, a View reacts
   1495      * to clicks by notifying the OnClickListener.<p>
   1496      * {@hide}
   1497      */
   1498     static final int CLICKABLE = 0x00004000;
   1499 
   1500     /**
   1501      * <p>Indicates this view is caching its drawing into a bitmap.</p>
   1502      * {@hide}
   1503      */
   1504     static final int DRAWING_CACHE_ENABLED = 0x00008000;
   1505 
   1506     /**
   1507      * <p>Indicates that no icicle should be saved for this view.<p>
   1508      * {@hide}
   1509      */
   1510     static final int SAVE_DISABLED = 0x000010000;
   1511 
   1512     /**
   1513      * <p>Mask for use with setFlags indicating bits used for the saveEnabled
   1514      * property.</p>
   1515      * {@hide}
   1516      */
   1517     static final int SAVE_DISABLED_MASK = 0x000010000;
   1518 
   1519     /**
   1520      * <p>Indicates that no drawing cache should ever be created for this view.<p>
   1521      * {@hide}
   1522      */
   1523     static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
   1524 
   1525     /**
   1526      * <p>Indicates this view can take / keep focus when int touch mode.</p>
   1527      * {@hide}
   1528      */
   1529     static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
   1530 
   1531     /** @hide */
   1532     @Retention(RetentionPolicy.SOURCE)
   1533     @IntDef(prefix = { "DRAWING_CACHE_QUALITY_" }, value = {
   1534             DRAWING_CACHE_QUALITY_LOW,
   1535             DRAWING_CACHE_QUALITY_HIGH,
   1536             DRAWING_CACHE_QUALITY_AUTO
   1537     })
   1538     public @interface DrawingCacheQuality {}
   1539 
   1540     /**
   1541      * <p>Enables low quality mode for the drawing cache.</p>
   1542      *
   1543      * @deprecated The view drawing cache was largely made obsolete with the introduction of
   1544      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
   1545      * layers are largely unnecessary and can easily result in a net loss in performance due to the
   1546      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
   1547      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
   1548      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
   1549      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
   1550      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
   1551      * software-rendered usages are discouraged and have compatibility issues with hardware-only
   1552      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
   1553      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
   1554      * reports or unit testing the {@link PixelCopy} API is recommended.
   1555      */
   1556     @Deprecated
   1557     public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
   1558 
   1559     /**
   1560      * <p>Enables high quality mode for the drawing cache.</p>
   1561      *
   1562      * @deprecated The view drawing cache was largely made obsolete with the introduction of
   1563      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
   1564      * layers are largely unnecessary and can easily result in a net loss in performance due to the
   1565      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
   1566      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
   1567      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
   1568      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
   1569      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
   1570      * software-rendered usages are discouraged and have compatibility issues with hardware-only
   1571      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
   1572      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
   1573      * reports or unit testing the {@link PixelCopy} API is recommended.
   1574      */
   1575     @Deprecated
   1576     public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
   1577 
   1578     /**
   1579      * <p>Enables automatic quality mode for the drawing cache.</p>
   1580      *
   1581      * @deprecated The view drawing cache was largely made obsolete with the introduction of
   1582      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
   1583      * layers are largely unnecessary and can easily result in a net loss in performance due to the
   1584      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
   1585      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
   1586      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
   1587      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
   1588      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
   1589      * software-rendered usages are discouraged and have compatibility issues with hardware-only
   1590      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
   1591      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
   1592      * reports or unit testing the {@link PixelCopy} API is recommended.
   1593      */
   1594     @Deprecated
   1595     public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
   1596 
   1597     private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
   1598             DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
   1599     };
   1600 
   1601     /**
   1602      * <p>Mask for use with setFlags indicating bits used for the cache
   1603      * quality property.</p>
   1604      * {@hide}
   1605      */
   1606     static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
   1607 
   1608     /**
   1609      * <p>
   1610      * Indicates this view can be long clicked. When long clickable, a View
   1611      * reacts to long clicks by notifying the OnLongClickListener or showing a
   1612      * context menu.
   1613      * </p>
   1614      * {@hide}
   1615      */
   1616     static final int LONG_CLICKABLE = 0x00200000;
   1617 
   1618     /**
   1619      * <p>Indicates that this view gets its drawable states from its direct parent
   1620      * and ignores its original internal states.</p>
   1621      *
   1622      * @hide
   1623      */
   1624     static final int DUPLICATE_PARENT_STATE = 0x00400000;
   1625 
   1626     /**
   1627      * <p>
   1628      * Indicates this view can be context clicked. When context clickable, a View reacts to a
   1629      * context click (e.g. a primary stylus button press or right mouse click) by notifying the
   1630      * OnContextClickListener.
   1631      * </p>
   1632      * {@hide}
   1633      */
   1634     static final int CONTEXT_CLICKABLE = 0x00800000;
   1635 
   1636     /** @hide */
   1637     @IntDef(prefix = { "SCROLLBARS_" }, value = {
   1638             SCROLLBARS_INSIDE_OVERLAY,
   1639             SCROLLBARS_INSIDE_INSET,
   1640             SCROLLBARS_OUTSIDE_OVERLAY,
   1641             SCROLLBARS_OUTSIDE_INSET
   1642     })
   1643     @Retention(RetentionPolicy.SOURCE)
   1644     public @interface ScrollBarStyle {}
   1645 
   1646     /**
   1647      * The scrollbar style to display the scrollbars inside the content area,
   1648      * without increasing the padding. The scrollbars will be overlaid with
   1649      * translucency on the view's content.
   1650      */
   1651     public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
   1652 
   1653     /**
   1654      * The scrollbar style to display the scrollbars inside the padded area,
   1655      * increasing the padding of the view. The scrollbars will not overlap the
   1656      * content area of the view.
   1657      */
   1658     public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
   1659 
   1660     /**
   1661      * The scrollbar style to display the scrollbars at the edge of the view,
   1662      * without increasing the padding. The scrollbars will be overlaid with
   1663      * translucency.
   1664      */
   1665     public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
   1666 
   1667     /**
   1668      * The scrollbar style to display the scrollbars at the edge of the view,
   1669      * increasing the padding of the view. The scrollbars will only overlap the
   1670      * background, if any.
   1671      */
   1672     public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
   1673 
   1674     /**
   1675      * Mask to check if the scrollbar style is overlay or inset.
   1676      * {@hide}
   1677      */
   1678     static final int SCROLLBARS_INSET_MASK = 0x01000000;
   1679 
   1680     /**
   1681      * Mask to check if the scrollbar style is inside or outside.
   1682      * {@hide}
   1683      */
   1684     static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
   1685 
   1686     /**
   1687      * Mask for scrollbar style.
   1688      * {@hide}
   1689      */
   1690     static final int SCROLLBARS_STYLE_MASK = 0x03000000;
   1691 
   1692     /**
   1693      * View flag indicating that the screen should remain on while the
   1694      * window containing this view is visible to the user.  This effectively
   1695      * takes care of automatically setting the WindowManager's
   1696      * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
   1697      */
   1698     public static final int KEEP_SCREEN_ON = 0x04000000;
   1699 
   1700     /**
   1701      * View flag indicating whether this view should have sound effects enabled
   1702      * for events such as clicking and touching.
   1703      */
   1704     public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
   1705 
   1706     /**
   1707      * View flag indicating whether this view should have haptic feedback
   1708      * enabled for events such as long presses.
   1709      */
   1710     public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
   1711 
   1712     /**
   1713      * <p>Indicates that the view hierarchy should stop saving state when
   1714      * it reaches this view.  If state saving is initiated immediately at
   1715      * the view, it will be allowed.
   1716      * {@hide}
   1717      */
   1718     static final int PARENT_SAVE_DISABLED = 0x20000000;
   1719 
   1720     /**
   1721      * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
   1722      * {@hide}
   1723      */
   1724     static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
   1725 
   1726     private static Paint sDebugPaint;
   1727 
   1728     /**
   1729      * <p>Indicates this view can display a tooltip on hover or long press.</p>
   1730      * {@hide}
   1731      */
   1732     static final int TOOLTIP = 0x40000000;
   1733 
   1734     /** @hide */
   1735     @IntDef(flag = true, prefix = { "FOCUSABLES_" }, value = {
   1736             FOCUSABLES_ALL,
   1737             FOCUSABLES_TOUCH_MODE
   1738     })
   1739     @Retention(RetentionPolicy.SOURCE)
   1740     public @interface FocusableMode {}
   1741 
   1742     /**
   1743      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
   1744      * should add all focusable Views regardless if they are focusable in touch mode.
   1745      */
   1746     public static final int FOCUSABLES_ALL = 0x00000000;
   1747 
   1748     /**
   1749      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
   1750      * should add only Views focusable in touch mode.
   1751      */
   1752     public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
   1753 
   1754     /** @hide */
   1755     @IntDef(prefix = { "FOCUS_" }, value = {
   1756             FOCUS_BACKWARD,
   1757             FOCUS_FORWARD,
   1758             FOCUS_LEFT,
   1759             FOCUS_UP,
   1760             FOCUS_RIGHT,
   1761             FOCUS_DOWN
   1762     })
   1763     @Retention(RetentionPolicy.SOURCE)
   1764     public @interface FocusDirection {}
   1765 
   1766     /** @hide */
   1767     @IntDef(prefix = { "FOCUS_" }, value = {
   1768             FOCUS_LEFT,
   1769             FOCUS_UP,
   1770             FOCUS_RIGHT,
   1771             FOCUS_DOWN
   1772     })
   1773     @Retention(RetentionPolicy.SOURCE)
   1774     public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
   1775 
   1776     /**
   1777      * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
   1778      * item.
   1779      */
   1780     public static final int FOCUS_BACKWARD = 0x00000001;
   1781 
   1782     /**
   1783      * Use with {@link #focusSearch(int)}. Move focus to the next selectable
   1784      * item.
   1785      */
   1786     public static final int FOCUS_FORWARD = 0x00000002;
   1787 
   1788     /**
   1789      * Use with {@link #focusSearch(int)}. Move focus to the left.
   1790      */
   1791     public static final int FOCUS_LEFT = 0x00000011;
   1792 
   1793     /**
   1794      * Use with {@link #focusSearch(int)}. Move focus up.
   1795      */
   1796     public static final int FOCUS_UP = 0x00000021;
   1797 
   1798     /**
   1799      * Use with {@link #focusSearch(int)}. Move focus to the right.
   1800      */
   1801     public static final int FOCUS_RIGHT = 0x00000042;
   1802 
   1803     /**
   1804      * Use with {@link #focusSearch(int)}. Move focus down.
   1805      */
   1806     public static final int FOCUS_DOWN = 0x00000082;
   1807 
   1808     /**
   1809      * Bits of {@link #getMeasuredWidthAndState()} and
   1810      * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
   1811      */
   1812     public static final int MEASURED_SIZE_MASK = 0x00ffffff;
   1813 
   1814     /**
   1815      * Bits of {@link #getMeasuredWidthAndState()} and
   1816      * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
   1817      */
   1818     public static final int MEASURED_STATE_MASK = 0xff000000;
   1819 
   1820     /**
   1821      * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
   1822      * for functions that combine both width and height into a single int,
   1823      * such as {@link #getMeasuredState()} and the childState argument of
   1824      * {@link #resolveSizeAndState(int, int, int)}.
   1825      */
   1826     public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
   1827 
   1828     /**
   1829      * Bit of {@link #getMeasuredWidthAndState()} and
   1830      * {@link #getMeasuredWidthAndState()} that indicates the measured size
   1831      * is smaller that the space the view would like to have.
   1832      */
   1833     public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
   1834 
   1835     /**
   1836      * Base View state sets
   1837      */
   1838     // Singles
   1839     /**
   1840      * Indicates the view has no states set. States are used with
   1841      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1842      * view depending on its state.
   1843      *
   1844      * @see android.graphics.drawable.Drawable
   1845      * @see #getDrawableState()
   1846      */
   1847     protected static final int[] EMPTY_STATE_SET;
   1848     /**
   1849      * Indicates the view is enabled. States are used with
   1850      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1851      * view depending on its state.
   1852      *
   1853      * @see android.graphics.drawable.Drawable
   1854      * @see #getDrawableState()
   1855      */
   1856     protected static final int[] ENABLED_STATE_SET;
   1857     /**
   1858      * Indicates the view is focused. States are used with
   1859      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1860      * view depending on its state.
   1861      *
   1862      * @see android.graphics.drawable.Drawable
   1863      * @see #getDrawableState()
   1864      */
   1865     protected static final int[] FOCUSED_STATE_SET;
   1866     /**
   1867      * Indicates the view is selected. States are used with
   1868      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1869      * view depending on its state.
   1870      *
   1871      * @see android.graphics.drawable.Drawable
   1872      * @see #getDrawableState()
   1873      */
   1874     protected static final int[] SELECTED_STATE_SET;
   1875     /**
   1876      * Indicates the view is pressed. States are used with
   1877      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1878      * view depending on its state.
   1879      *
   1880      * @see android.graphics.drawable.Drawable
   1881      * @see #getDrawableState()
   1882      */
   1883     protected static final int[] PRESSED_STATE_SET;
   1884     /**
   1885      * Indicates the view's window has focus. States are used with
   1886      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1887      * view depending on its state.
   1888      *
   1889      * @see android.graphics.drawable.Drawable
   1890      * @see #getDrawableState()
   1891      */
   1892     protected static final int[] WINDOW_FOCUSED_STATE_SET;
   1893     // Doubles
   1894     /**
   1895      * Indicates the view is enabled and has the focus.
   1896      *
   1897      * @see #ENABLED_STATE_SET
   1898      * @see #FOCUSED_STATE_SET
   1899      */
   1900     protected static final int[] ENABLED_FOCUSED_STATE_SET;
   1901     /**
   1902      * Indicates the view is enabled and selected.
   1903      *
   1904      * @see #ENABLED_STATE_SET
   1905      * @see #SELECTED_STATE_SET
   1906      */
   1907     protected static final int[] ENABLED_SELECTED_STATE_SET;
   1908     /**
   1909      * Indicates the view is enabled and that its window has focus.
   1910      *
   1911      * @see #ENABLED_STATE_SET
   1912      * @see #WINDOW_FOCUSED_STATE_SET
   1913      */
   1914     protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
   1915     /**
   1916      * Indicates the view is focused and selected.
   1917      *
   1918      * @see #FOCUSED_STATE_SET
   1919      * @see #SELECTED_STATE_SET
   1920      */
   1921     protected static final int[] FOCUSED_SELECTED_STATE_SET;
   1922     /**
   1923      * Indicates the view has the focus and that its window has the focus.
   1924      *
   1925      * @see #FOCUSED_STATE_SET
   1926      * @see #WINDOW_FOCUSED_STATE_SET
   1927      */
   1928     protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
   1929     /**
   1930      * Indicates the view is selected and that its window has the focus.
   1931      *
   1932      * @see #SELECTED_STATE_SET
   1933      * @see #WINDOW_FOCUSED_STATE_SET
   1934      */
   1935     protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
   1936     // Triples
   1937     /**
   1938      * Indicates the view is enabled, focused and selected.
   1939      *
   1940      * @see #ENABLED_STATE_SET
   1941      * @see #FOCUSED_STATE_SET
   1942      * @see #SELECTED_STATE_SET
   1943      */
   1944     protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
   1945     /**
   1946      * Indicates the view is enabled, focused and its window has the focus.
   1947      *
   1948      * @see #ENABLED_STATE_SET
   1949      * @see #FOCUSED_STATE_SET
   1950      * @see #WINDOW_FOCUSED_STATE_SET
   1951      */
   1952     protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
   1953     /**
   1954      * Indicates the view is enabled, selected and its window has the focus.
   1955      *
   1956      * @see #ENABLED_STATE_SET
   1957      * @see #SELECTED_STATE_SET
   1958      * @see #WINDOW_FOCUSED_STATE_SET
   1959      */
   1960     protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1961     /**
   1962      * Indicates the view is focused, selected and its window has the focus.
   1963      *
   1964      * @see #FOCUSED_STATE_SET
   1965      * @see #SELECTED_STATE_SET
   1966      * @see #WINDOW_FOCUSED_STATE_SET
   1967      */
   1968     protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1969     /**
   1970      * Indicates the view is enabled, focused, selected and its window
   1971      * has the focus.
   1972      *
   1973      * @see #ENABLED_STATE_SET
   1974      * @see #FOCUSED_STATE_SET
   1975      * @see #SELECTED_STATE_SET
   1976      * @see #WINDOW_FOCUSED_STATE_SET
   1977      */
   1978     protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1979     /**
   1980      * Indicates the view is pressed and its window has the focus.
   1981      *
   1982      * @see #PRESSED_STATE_SET
   1983      * @see #WINDOW_FOCUSED_STATE_SET
   1984      */
   1985     protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
   1986     /**
   1987      * Indicates the view is pressed and selected.
   1988      *
   1989      * @see #PRESSED_STATE_SET
   1990      * @see #SELECTED_STATE_SET
   1991      */
   1992     protected static final int[] PRESSED_SELECTED_STATE_SET;
   1993     /**
   1994      * Indicates the view is pressed, selected and its window has the focus.
   1995      *
   1996      * @see #PRESSED_STATE_SET
   1997      * @see #SELECTED_STATE_SET
   1998      * @see #WINDOW_FOCUSED_STATE_SET
   1999      */
   2000     protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   2001     /**
   2002      * Indicates the view is pressed and focused.
   2003      *
   2004      * @see #PRESSED_STATE_SET
   2005      * @see #FOCUSED_STATE_SET
   2006      */
   2007     protected static final int[] PRESSED_FOCUSED_STATE_SET;
   2008     /**
   2009      * Indicates the view is pressed, focused and its window has the focus.
   2010      *
   2011      * @see #PRESSED_STATE_SET
   2012      * @see #FOCUSED_STATE_SET
   2013      * @see #WINDOW_FOCUSED_STATE_SET
   2014      */
   2015     protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
   2016     /**
   2017      * Indicates the view is pressed, focused and selected.
   2018      *
   2019      * @see #PRESSED_STATE_SET
   2020      * @see #SELECTED_STATE_SET
   2021      * @see #FOCUSED_STATE_SET
   2022      */
   2023     protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
   2024     /**
   2025      * Indicates the view is pressed, focused, selected and its window has the focus.
   2026      *
   2027      * @see #PRESSED_STATE_SET
   2028      * @see #FOCUSED_STATE_SET
   2029      * @see #SELECTED_STATE_SET
   2030      * @see #WINDOW_FOCUSED_STATE_SET
   2031      */
   2032     protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   2033     /**
   2034      * Indicates the view is pressed and enabled.
   2035      *
   2036      * @see #PRESSED_STATE_SET
   2037      * @see #ENABLED_STATE_SET
   2038      */
   2039     protected static final int[] PRESSED_ENABLED_STATE_SET;
   2040     /**
   2041      * Indicates the view is pressed, enabled and its window has the focus.
   2042      *
   2043      * @see #PRESSED_STATE_SET
   2044      * @see #ENABLED_STATE_SET
   2045      * @see #WINDOW_FOCUSED_STATE_SET
   2046      */
   2047     protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
   2048     /**
   2049      * Indicates the view is pressed, enabled and selected.
   2050      *
   2051      * @see #PRESSED_STATE_SET
   2052      * @see #ENABLED_STATE_SET
   2053      * @see #SELECTED_STATE_SET
   2054      */
   2055     protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
   2056     /**
   2057      * Indicates the view is pressed, enabled, selected and its window has the
   2058      * focus.
   2059      *
   2060      * @see #PRESSED_STATE_SET
   2061      * @see #ENABLED_STATE_SET
   2062      * @see #SELECTED_STATE_SET
   2063      * @see #WINDOW_FOCUSED_STATE_SET
   2064      */
   2065     protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   2066     /**
   2067      * Indicates the view is pressed, enabled and focused.
   2068      *
   2069      * @see #PRESSED_STATE_SET
   2070      * @see #ENABLED_STATE_SET
   2071      * @see #FOCUSED_STATE_SET
   2072      */
   2073     protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
   2074     /**
   2075      * Indicates the view is pressed, enabled, focused and its window has the
   2076      * focus.
   2077      *
   2078      * @see #PRESSED_STATE_SET
   2079      * @see #ENABLED_STATE_SET
   2080      * @see #FOCUSED_STATE_SET
   2081      * @see #WINDOW_FOCUSED_STATE_SET
   2082      */
   2083     protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
   2084     /**
   2085      * Indicates the view is pressed, enabled, focused and selected.
   2086      *
   2087      * @see #PRESSED_STATE_SET
   2088      * @see #ENABLED_STATE_SET
   2089      * @see #SELECTED_STATE_SET
   2090      * @see #FOCUSED_STATE_SET
   2091      */
   2092     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
   2093     /**
   2094      * Indicates the view is pressed, enabled, focused, selected and its window
   2095      * has the focus.
   2096      *
   2097      * @see #PRESSED_STATE_SET
   2098      * @see #ENABLED_STATE_SET
   2099      * @see #SELECTED_STATE_SET
   2100      * @see #FOCUSED_STATE_SET
   2101      * @see #WINDOW_FOCUSED_STATE_SET
   2102      */
   2103     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   2104 
   2105     static {
   2106         EMPTY_STATE_SET = StateSet.get(0);
   2107 
   2108         WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
   2109 
   2110         SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
   2111         SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   2112                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
   2113 
   2114         FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
   2115         FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   2116                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
   2117         FOCUSED_SELECTED_STATE_SET = StateSet.get(
   2118                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
   2119         FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   2120                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   2121                         | StateSet.VIEW_STATE_FOCUSED);
   2122 
   2123         ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
   2124         ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   2125                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
   2126         ENABLED_SELECTED_STATE_SET = StateSet.get(
   2127                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
   2128         ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   2129                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   2130                         | StateSet.VIEW_STATE_ENABLED);
   2131         ENABLED_FOCUSED_STATE_SET = StateSet.get(
   2132                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
   2133         ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   2134                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
   2135                         | StateSet.VIEW_STATE_ENABLED);
   2136         ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
   2137                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
   2138                         | StateSet.VIEW_STATE_ENABLED);
   2139         ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   2140                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   2141                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
   2142 
   2143         PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
   2144         PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   2145                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
   2146         PRESSED_SELECTED_STATE_SET = StateSet.get(
   2147                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
   2148         PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   2149                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   2150                         | StateSet.VIEW_STATE_PRESSED);
   2151         PRESSED_FOCUSED_STATE_SET = StateSet.get(
   2152                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
   2153         PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   2154                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
   2155                         | StateSet.VIEW_STATE_PRESSED);
   2156         PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
   2157                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
   2158                         | StateSet.VIEW_STATE_PRESSED);
   2159         PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   2160                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   2161                         | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
   2162         PRESSED_ENABLED_STATE_SET = StateSet.get(
   2163                 StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
   2164         PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   2165                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
   2166                         | StateSet.VIEW_STATE_PRESSED);
   2167         PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
   2168                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
   2169                         | StateSet.VIEW_STATE_PRESSED);
   2170         PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   2171                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   2172                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
   2173         PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
   2174                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
   2175                         | StateSet.VIEW_STATE_PRESSED);
   2176         PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   2177                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
   2178                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
   2179         PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
   2180                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
   2181                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
   2182         PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   2183                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   2184                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
   2185                         | StateSet.VIEW_STATE_PRESSED);
   2186     }
   2187 
   2188     /**
   2189      * Accessibility event types that are dispatched for text population.
   2190      */
   2191     private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
   2192             AccessibilityEvent.TYPE_VIEW_CLICKED
   2193             | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
   2194             | AccessibilityEvent.TYPE_VIEW_SELECTED
   2195             | AccessibilityEvent.TYPE_VIEW_FOCUSED
   2196             | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
   2197             | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
   2198             | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
   2199             | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
   2200             | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
   2201             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
   2202             | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
   2203 
   2204     static final int DEBUG_CORNERS_COLOR = Color.rgb(63, 127, 255);
   2205 
   2206     static final int DEBUG_CORNERS_SIZE_DIP = 8;
   2207 
   2208     /**
   2209      * Temporary Rect currently for use in setBackground().  This will probably
   2210      * be extended in the future to hold our own class with more than just
   2211      * a Rect. :)
   2212      */
   2213     static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
   2214 
   2215     /**
   2216      * Map used to store views' tags.
   2217      */
   2218     @UnsupportedAppUsage
   2219     private SparseArray<Object> mKeyedTags;
   2220 
   2221     /**
   2222      * The next available accessibility id.
   2223      */
   2224     private static int sNextAccessibilityViewId;
   2225 
   2226     /**
   2227      * The animation currently associated with this view.
   2228      * @hide
   2229      */
   2230     protected Animation mCurrentAnimation = null;
   2231 
   2232     /**
   2233      * Width as measured during measure pass.
   2234      * {@hide}
   2235      */
   2236     @ViewDebug.ExportedProperty(category = "measurement")
   2237     @UnsupportedAppUsage
   2238     int mMeasuredWidth;
   2239 
   2240     /**
   2241      * Height as measured during measure pass.
   2242      * {@hide}
   2243      */
   2244     @ViewDebug.ExportedProperty(category = "measurement")
   2245     @UnsupportedAppUsage
   2246     int mMeasuredHeight;
   2247 
   2248     /**
   2249      * Flag to indicate that this view was marked INVALIDATED, or had its display list
   2250      * invalidated, prior to the current drawing iteration. If true, the view must re-draw
   2251      * its display list. This flag, used only when hw accelerated, allows us to clear the
   2252      * flag while retaining this information until it's needed (at getDisplayList() time and
   2253      * in drawChild(), when we decide to draw a view's children's display lists into our own).
   2254      *
   2255      * {@hide}
   2256      */
   2257     @UnsupportedAppUsage
   2258     boolean mRecreateDisplayList = false;
   2259 
   2260     /**
   2261      * The view's identifier.
   2262      * {@hide}
   2263      *
   2264      * @see #setId(int)
   2265      * @see #getId()
   2266      */
   2267     @IdRes
   2268     @ViewDebug.ExportedProperty(resolveId = true)
   2269     int mID = NO_ID;
   2270 
   2271     /** The ID of this view for autofill purposes.
   2272      * <ul>
   2273      *     <li>== {@link #NO_ID}: ID has not been assigned yet
   2274      *     <li>&le; {@link #LAST_APP_AUTOFILL_ID}: View is not part of a activity. The ID is
   2275      *                                                  unique in the process. This might change
   2276      *                                                  over activity lifecycle events.
   2277      *     <li>&gt; {@link #LAST_APP_AUTOFILL_ID}: View is part of a activity. The ID is
   2278      *                                                  unique in the activity. This stays the same
   2279      *                                                  over activity lifecycle events.
   2280      */
   2281     private int mAutofillViewId = NO_ID;
   2282 
   2283     // ID for accessibility purposes. This ID must be unique for every window
   2284     @UnsupportedAppUsage
   2285     private int mAccessibilityViewId = NO_ID;
   2286 
   2287     private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
   2288 
   2289     /**
   2290      * The view's tag.
   2291      * {@hide}
   2292      *
   2293      * @see #setTag(Object)
   2294      * @see #getTag()
   2295      */
   2296     @UnsupportedAppUsage
   2297     protected Object mTag = null;
   2298 
   2299     /*
   2300      * Masks for mPrivateFlags, as generated by dumpFlags():
   2301      *
   2302      * |-------|-------|-------|-------|
   2303      *                                 1 PFLAG_WANTS_FOCUS
   2304      *                                1  PFLAG_FOCUSED
   2305      *                               1   PFLAG_SELECTED
   2306      *                              1    PFLAG_IS_ROOT_NAMESPACE
   2307      *                             1     PFLAG_HAS_BOUNDS
   2308      *                            1      PFLAG_DRAWN
   2309      *                           1       PFLAG_DRAW_ANIMATION
   2310      *                          1        PFLAG_SKIP_DRAW
   2311      *                        1          PFLAG_REQUEST_TRANSPARENT_REGIONS
   2312      *                       1           PFLAG_DRAWABLE_STATE_DIRTY
   2313      *                      1            PFLAG_MEASURED_DIMENSION_SET
   2314      *                     1             PFLAG_FORCE_LAYOUT
   2315      *                    1              PFLAG_LAYOUT_REQUIRED
   2316      *                   1               PFLAG_PRESSED
   2317      *                  1                PFLAG_DRAWING_CACHE_VALID
   2318      *                 1                 PFLAG_ANIMATION_STARTED
   2319      *                1                  PFLAG_SAVE_STATE_CALLED
   2320      *               1                   PFLAG_ALPHA_SET
   2321      *              1                    PFLAG_SCROLL_CONTAINER
   2322      *             1                     PFLAG_SCROLL_CONTAINER_ADDED
   2323      *            1                      PFLAG_DIRTY
   2324      *            1                      PFLAG_DIRTY_MASK
   2325      *          1                        PFLAG_OPAQUE_BACKGROUND
   2326      *         1                         PFLAG_OPAQUE_SCROLLBARS
   2327      *         11                        PFLAG_OPAQUE_MASK
   2328      *        1                          PFLAG_PREPRESSED
   2329      *       1                           PFLAG_CANCEL_NEXT_UP_EVENT
   2330      *      1                            PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH
   2331      *     1                             PFLAG_HOVERED
   2332      *    1                              PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK
   2333      *   1                               PFLAG_ACTIVATED
   2334      *  1                                PFLAG_INVALIDATED
   2335      * |-------|-------|-------|-------|
   2336      */
   2337     /** {@hide} */
   2338     static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
   2339     /** {@hide} */
   2340     static final int PFLAG_FOCUSED                     = 0x00000002;
   2341     /** {@hide} */
   2342     static final int PFLAG_SELECTED                    = 0x00000004;
   2343     /** {@hide} */
   2344     static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
   2345     /** {@hide} */
   2346     static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
   2347     /** {@hide} */
   2348     static final int PFLAG_DRAWN                       = 0x00000020;
   2349     /**
   2350      * When this flag is set, this view is running an animation on behalf of its
   2351      * children and should therefore not cancel invalidate requests, even if they
   2352      * lie outside of this view's bounds.
   2353      *
   2354      * {@hide}
   2355      */
   2356     static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
   2357     /** {@hide} */
   2358     static final int PFLAG_SKIP_DRAW                   = 0x00000080;
   2359     /** {@hide} */
   2360     static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
   2361     /** {@hide} */
   2362     static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
   2363     /** {@hide} */
   2364     static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
   2365     /** {@hide} */
   2366     static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
   2367     /** {@hide} */
   2368     static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
   2369 
   2370     private static final int PFLAG_PRESSED             = 0x00004000;
   2371 
   2372     /** {@hide} */
   2373     static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
   2374     /**
   2375      * Flag used to indicate that this view should be drawn once more (and only once
   2376      * more) after its animation has completed.
   2377      * {@hide}
   2378      */
   2379     static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
   2380 
   2381     private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
   2382 
   2383     /**
   2384      * Indicates that the View returned true when onSetAlpha() was called and that
   2385      * the alpha must be restored.
   2386      * {@hide}
   2387      */
   2388     static final int PFLAG_ALPHA_SET                   = 0x00040000;
   2389 
   2390     /**
   2391      * Set by {@link #setScrollContainer(boolean)}.
   2392      */
   2393     static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
   2394 
   2395     /**
   2396      * Set by {@link #setScrollContainer(boolean)}.
   2397      */
   2398     static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
   2399 
   2400     /**
   2401      * View flag indicating whether this view was invalidated (fully or partially.)
   2402      *
   2403      * @hide
   2404      */
   2405     static final int PFLAG_DIRTY                       = 0x00200000;
   2406 
   2407     /**
   2408      * Mask for {@link #PFLAG_DIRTY}.
   2409      *
   2410      * @hide
   2411      */
   2412     static final int PFLAG_DIRTY_MASK                  = 0x00200000;
   2413 
   2414     /**
   2415      * Indicates whether the background is opaque.
   2416      *
   2417      * @hide
   2418      */
   2419     static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
   2420 
   2421     /**
   2422      * Indicates whether the scrollbars are opaque.
   2423      *
   2424      * @hide
   2425      */
   2426     static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
   2427 
   2428     /**
   2429      * Indicates whether the view is opaque.
   2430      *
   2431      * @hide
   2432      */
   2433     static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
   2434 
   2435     /**
   2436      * Indicates a prepressed state;
   2437      * the short time between ACTION_DOWN and recognizing
   2438      * a 'real' press. Prepressed is used to recognize quick taps
   2439      * even when they are shorter than ViewConfiguration.getTapTimeout().
   2440      *
   2441      * @hide
   2442      */
   2443     private static final int PFLAG_PREPRESSED          = 0x02000000;
   2444 
   2445     /**
   2446      * Indicates whether the view is temporarily detached.
   2447      *
   2448      * @hide
   2449      */
   2450     static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
   2451 
   2452     /**
   2453      * Indicates that we should awaken scroll bars once attached
   2454      *
   2455      * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
   2456      * during window attachment and it is no longer needed. Feel free to repurpose it.
   2457      *
   2458      * @hide
   2459      */
   2460     private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
   2461 
   2462     /**
   2463      * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
   2464      * @hide
   2465      */
   2466     private static final int PFLAG_HOVERED             = 0x10000000;
   2467 
   2468     /**
   2469      * Flag set by {@link AutofillManager} if it needs to be notified when this view is clicked.
   2470      */
   2471     private static final int PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK = 0x20000000;
   2472 
   2473     /** {@hide} */
   2474     static final int PFLAG_ACTIVATED                   = 0x40000000;
   2475 
   2476     /**
   2477      * Indicates that this view was specifically invalidated, not just dirtied because some
   2478      * child view was invalidated. The flag is used to determine when we need to recreate
   2479      * a view's display list (as opposed to just returning a reference to its existing
   2480      * display list).
   2481      *
   2482      * @hide
   2483      */
   2484     static final int PFLAG_INVALIDATED                 = 0x80000000;
   2485 
   2486     /* End of masks for mPrivateFlags */
   2487 
   2488     /*
   2489      * Masks for mPrivateFlags2, as generated by dumpFlags():
   2490      *
   2491      * |-------|-------|-------|-------|
   2492      *                                 1 PFLAG2_DRAG_CAN_ACCEPT
   2493      *                                1  PFLAG2_DRAG_HOVERED
   2494      *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
   2495      *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
   2496      *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
   2497      *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
   2498      *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
   2499      *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
   2500      *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
   2501      *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
   2502      *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
   2503      *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
   2504      *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
   2505      *                         111       PFLAG2_TEXT_DIRECTION_MASK
   2506      *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
   2507      *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
   2508      *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
   2509      *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
   2510      *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
   2511      *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
   2512      *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
   2513      *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
   2514      *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
   2515      *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
   2516      *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
   2517      *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
   2518      *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
   2519      *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
   2520      *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
   2521      *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
   2522      *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
   2523      *     1                             PFLAG2_VIEW_QUICK_REJECTED
   2524      *    1                              PFLAG2_PADDING_RESOLVED
   2525      *   1                               PFLAG2_DRAWABLE_RESOLVED
   2526      *  1                                PFLAG2_HAS_TRANSIENT_STATE
   2527      * |-------|-------|-------|-------|
   2528      */
   2529 
   2530     /**
   2531      * Indicates that this view has reported that it can accept the current drag's content.
   2532      * Cleared when the drag operation concludes.
   2533      * @hide
   2534      */
   2535     static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
   2536 
   2537     /**
   2538      * Indicates that this view is currently directly under the drag location in a
   2539      * drag-and-drop operation involving content that it can accept.  Cleared when
   2540      * the drag exits the view, or when the drag operation concludes.
   2541      * @hide
   2542      */
   2543     static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
   2544 
   2545     /** @hide */
   2546     @IntDef(prefix = { "LAYOUT_DIRECTION_" }, value = {
   2547             LAYOUT_DIRECTION_LTR,
   2548             LAYOUT_DIRECTION_RTL,
   2549             LAYOUT_DIRECTION_INHERIT,
   2550             LAYOUT_DIRECTION_LOCALE
   2551     })
   2552     @Retention(RetentionPolicy.SOURCE)
   2553     // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
   2554     public @interface LayoutDir {}
   2555 
   2556     /** @hide */
   2557     @IntDef(prefix = { "LAYOUT_DIRECTION_" }, value = {
   2558             LAYOUT_DIRECTION_LTR,
   2559             LAYOUT_DIRECTION_RTL
   2560     })
   2561     @Retention(RetentionPolicy.SOURCE)
   2562     public @interface ResolvedLayoutDir {}
   2563 
   2564     /**
   2565      * A flag to indicate that the layout direction of this view has not been defined yet.
   2566      * @hide
   2567      */
   2568     public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
   2569 
   2570     /**
   2571      * Horizontal layout direction of this view is from Left to Right.
   2572      * Use with {@link #setLayoutDirection}.
   2573      */
   2574     public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
   2575 
   2576     /**
   2577      * Horizontal layout direction of this view is from Right to Left.
   2578      * Use with {@link #setLayoutDirection}.
   2579      */
   2580     public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
   2581 
   2582     /**
   2583      * Horizontal layout direction of this view is inherited from its parent.
   2584      * Use with {@link #setLayoutDirection}.
   2585      */
   2586     public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
   2587 
   2588     /**
   2589      * Horizontal layout direction of this view is from deduced from the default language
   2590      * script for the locale. Use with {@link #setLayoutDirection}.
   2591      */
   2592     public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
   2593 
   2594     /**
   2595      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
   2596      * @hide
   2597      */
   2598     static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
   2599 
   2600     /**
   2601      * Mask for use with private flags indicating bits used for horizontal layout direction.
   2602      * @hide
   2603      */
   2604     static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
   2605 
   2606     /**
   2607      * Indicates whether the view horizontal layout direction has been resolved and drawn to the
   2608      * right-to-left direction.
   2609      * @hide
   2610      */
   2611     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
   2612 
   2613     /**
   2614      * Indicates whether the view horizontal layout direction has been resolved.
   2615      * @hide
   2616      */
   2617     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
   2618 
   2619     /**
   2620      * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
   2621      * @hide
   2622      */
   2623     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
   2624             << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
   2625 
   2626     /*
   2627      * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
   2628      * flag value.
   2629      * @hide
   2630      */
   2631     private static final int[] LAYOUT_DIRECTION_FLAGS = {
   2632             LAYOUT_DIRECTION_LTR,
   2633             LAYOUT_DIRECTION_RTL,
   2634             LAYOUT_DIRECTION_INHERIT,
   2635             LAYOUT_DIRECTION_LOCALE
   2636     };
   2637 
   2638     /**
   2639      * Default horizontal layout direction.
   2640      */
   2641     private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
   2642 
   2643     /**
   2644      * Default horizontal layout direction.
   2645      * @hide
   2646      */
   2647     static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
   2648 
   2649     /**
   2650      * Text direction is inherited through {@link ViewGroup}
   2651      */
   2652     public static final int TEXT_DIRECTION_INHERIT = 0;
   2653 
   2654     /**
   2655      * Text direction is using "first strong algorithm". The first strong directional character
   2656      * determines the paragraph direction. If there is no strong directional character, the
   2657      * paragraph direction is the view's resolved layout direction.
   2658      */
   2659     public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
   2660 
   2661     /**
   2662      * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
   2663      * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
   2664      * If there are neither, the paragraph direction is the view's resolved layout direction.
   2665      */
   2666     public static final int TEXT_DIRECTION_ANY_RTL = 2;
   2667 
   2668     /**
   2669      * Text direction is forced to LTR.
   2670      */
   2671     public static final int TEXT_DIRECTION_LTR = 3;
   2672 
   2673     /**
   2674      * Text direction is forced to RTL.
   2675      */
   2676     public static final int TEXT_DIRECTION_RTL = 4;
   2677 
   2678     /**
   2679      * Text direction is coming from the system Locale.
   2680      */
   2681     public static final int TEXT_DIRECTION_LOCALE = 5;
   2682 
   2683     /**
   2684      * Text direction is using "first strong algorithm". The first strong directional character
   2685      * determines the paragraph direction. If there is no strong directional character, the
   2686      * paragraph direction is LTR.
   2687      */
   2688     public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
   2689 
   2690     /**
   2691      * Text direction is using "first strong algorithm". The first strong directional character
   2692      * determines the paragraph direction. If there is no strong directional character, the
   2693      * paragraph direction is RTL.
   2694      */
   2695     public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
   2696 
   2697     /**
   2698      * Default text direction is inherited
   2699      */
   2700     private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
   2701 
   2702     /**
   2703      * Default resolved text direction
   2704      * @hide
   2705      */
   2706     static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
   2707 
   2708     /**
   2709      * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
   2710      * @hide
   2711      */
   2712     static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
   2713 
   2714     /**
   2715      * Mask for use with private flags indicating bits used for text direction.
   2716      * @hide
   2717      */
   2718     static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
   2719             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
   2720 
   2721     /**
   2722      * Array of text direction flags for mapping attribute "textDirection" to correct
   2723      * flag value.
   2724      * @hide
   2725      */
   2726     private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
   2727             TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2728             TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2729             TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2730             TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2731             TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2732             TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2733             TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2734             TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
   2735     };
   2736 
   2737     /**
   2738      * Indicates whether the view text direction has been resolved.
   2739      * @hide
   2740      */
   2741     static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
   2742             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
   2743 
   2744     /**
   2745      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
   2746      * @hide
   2747      */
   2748     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
   2749 
   2750     /**
   2751      * Mask for use with private flags indicating bits used for resolved text direction.
   2752      * @hide
   2753      */
   2754     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
   2755             << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
   2756 
   2757     /**
   2758      * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
   2759      * @hide
   2760      */
   2761     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
   2762             TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
   2763 
   2764     /** @hide */
   2765     @IntDef(prefix = { "TEXT_ALIGNMENT_" }, value = {
   2766             TEXT_ALIGNMENT_INHERIT,
   2767             TEXT_ALIGNMENT_GRAVITY,
   2768             TEXT_ALIGNMENT_CENTER,
   2769             TEXT_ALIGNMENT_TEXT_START,
   2770             TEXT_ALIGNMENT_TEXT_END,
   2771             TEXT_ALIGNMENT_VIEW_START,
   2772             TEXT_ALIGNMENT_VIEW_END
   2773     })
   2774     @Retention(RetentionPolicy.SOURCE)
   2775     public @interface TextAlignment {}
   2776 
   2777     /**
   2778      * Default text alignment. The text alignment of this View is inherited from its parent.
   2779      * Use with {@link #setTextAlignment(int)}
   2780      */
   2781     public static final int TEXT_ALIGNMENT_INHERIT = 0;
   2782 
   2783     /**
   2784      * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
   2785      * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraphs text direction.
   2786      *
   2787      * Use with {@link #setTextAlignment(int)}
   2788      */
   2789     public static final int TEXT_ALIGNMENT_GRAVITY = 1;
   2790 
   2791     /**
   2792      * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
   2793      *
   2794      * Use with {@link #setTextAlignment(int)}
   2795      */
   2796     public static final int TEXT_ALIGNMENT_TEXT_START = 2;
   2797 
   2798     /**
   2799      * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
   2800      *
   2801      * Use with {@link #setTextAlignment(int)}
   2802      */
   2803     public static final int TEXT_ALIGNMENT_TEXT_END = 3;
   2804 
   2805     /**
   2806      * Center the paragraph, e.g. ALIGN_CENTER.
   2807      *
   2808      * Use with {@link #setTextAlignment(int)}
   2809      */
   2810     public static final int TEXT_ALIGNMENT_CENTER = 4;
   2811 
   2812     /**
   2813      * Align to the start of the view, which is ALIGN_LEFT if the views resolved
   2814      * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
   2815      *
   2816      * Use with {@link #setTextAlignment(int)}
   2817      */
   2818     public static final int TEXT_ALIGNMENT_VIEW_START = 5;
   2819 
   2820     /**
   2821      * Align to the end of the view, which is ALIGN_RIGHT if the views resolved
   2822      * layoutDirection is LTR, and ALIGN_LEFT otherwise.
   2823      *
   2824      * Use with {@link #setTextAlignment(int)}
   2825      */
   2826     public static final int TEXT_ALIGNMENT_VIEW_END = 6;
   2827 
   2828     /**
   2829      * Default text alignment is inherited
   2830      */
   2831     private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
   2832 
   2833     /**
   2834      * Default resolved text alignment
   2835      * @hide
   2836      */
   2837     static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
   2838 
   2839     /**
   2840       * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
   2841       * @hide
   2842       */
   2843     static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
   2844 
   2845     /**
   2846       * Mask for use with private flags indicating bits used for text alignment.
   2847       * @hide
   2848       */
   2849     static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
   2850 
   2851     /**
   2852      * Array of text direction flags for mapping attribute "textAlignment" to correct
   2853      * flag value.
   2854      * @hide
   2855      */
   2856     private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
   2857             TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
   2858             TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
   2859             TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
   2860             TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
   2861             TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
   2862             TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
   2863             TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
   2864     };
   2865 
   2866     /**
   2867      * Indicates whether the view text alignment has been resolved.
   2868      * @hide
   2869      */
   2870     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
   2871 
   2872     /**
   2873      * Bit shift to get the resolved text alignment.
   2874      * @hide
   2875      */
   2876     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
   2877 
   2878     /**
   2879      * Mask for use with private flags indicating bits used for text alignment.
   2880      * @hide
   2881      */
   2882     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
   2883             << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
   2884 
   2885     /**
   2886      * Indicates whether if the view text alignment has been resolved to gravity
   2887      */
   2888     private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
   2889             TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
   2890 
   2891     // Accessiblity constants for mPrivateFlags2
   2892 
   2893     /**
   2894      * Shift for the bits in {@link #mPrivateFlags2} related to the
   2895      * "importantForAccessibility" attribute.
   2896      */
   2897     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
   2898 
   2899     /**
   2900      * Automatically determine whether a view is important for accessibility.
   2901      */
   2902     public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
   2903 
   2904     /**
   2905      * The view is important for accessibility.
   2906      */
   2907     public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
   2908 
   2909     /**
   2910      * The view is not important for accessibility.
   2911      */
   2912     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
   2913 
   2914     /**
   2915      * The view is not important for accessibility, nor are any of its
   2916      * descendant views.
   2917      */
   2918     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
   2919 
   2920     /**
   2921      * The default whether the view is important for accessibility.
   2922      */
   2923     static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
   2924 
   2925     /**
   2926      * Mask for obtaining the bits which specify how to determine
   2927      * whether a view is important for accessibility.
   2928      */
   2929     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
   2930         | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
   2931         | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
   2932         << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
   2933 
   2934     /**
   2935      * Shift for the bits in {@link #mPrivateFlags2} related to the
   2936      * "accessibilityLiveRegion" attribute.
   2937      */
   2938     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
   2939 
   2940     /**
   2941      * Live region mode specifying that accessibility services should not
   2942      * automatically announce changes to this view. This is the default live
   2943      * region mode for most views.
   2944      * <p>
   2945      * Use with {@link #setAccessibilityLiveRegion(int)}.
   2946      */
   2947     public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
   2948 
   2949     /**
   2950      * Live region mode specifying that accessibility services should announce
   2951      * changes to this view.
   2952      * <p>
   2953      * Use with {@link #setAccessibilityLiveRegion(int)}.
   2954      */
   2955     public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
   2956 
   2957     /**
   2958      * Live region mode specifying that accessibility services should interrupt
   2959      * ongoing speech to immediately announce changes to this view.
   2960      * <p>
   2961      * Use with {@link #setAccessibilityLiveRegion(int)}.
   2962      */
   2963     public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
   2964 
   2965     /**
   2966      * The default whether the view is important for accessibility.
   2967      */
   2968     static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
   2969 
   2970     /**
   2971      * Mask for obtaining the bits which specify a view's accessibility live
   2972      * region mode.
   2973      */
   2974     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
   2975             | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
   2976             << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
   2977 
   2978     /**
   2979      * Flag indicating whether a view has accessibility focus.
   2980      */
   2981     static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
   2982 
   2983     /**
   2984      * Flag whether the accessibility state of the subtree rooted at this view changed.
   2985      */
   2986     static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
   2987 
   2988     /**
   2989      * Flag indicating whether a view failed the quickReject() check in draw(). This condition
   2990      * is used to check whether later changes to the view's transform should invalidate the
   2991      * view to force the quickReject test to run again.
   2992      */
   2993     static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
   2994 
   2995     /**
   2996      * Flag indicating that start/end padding has been resolved into left/right padding
   2997      * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
   2998      * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
   2999      * during measurement. In some special cases this is required such as when an adapter-based
   3000      * view measures prospective children without attaching them to a window.
   3001      */
   3002     static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
   3003 
   3004     /**
   3005      * Flag indicating that the start/end drawables has been resolved into left/right ones.
   3006      */
   3007     static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
   3008 
   3009     /**
   3010      * Indicates that the view is tracking some sort of transient state
   3011      * that the app should not need to be aware of, but that the framework
   3012      * should take special care to preserve.
   3013      */
   3014     static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
   3015 
   3016     /**
   3017      * Group of bits indicating that RTL properties resolution is done.
   3018      */
   3019     static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
   3020             PFLAG2_TEXT_DIRECTION_RESOLVED |
   3021             PFLAG2_TEXT_ALIGNMENT_RESOLVED |
   3022             PFLAG2_PADDING_RESOLVED |
   3023             PFLAG2_DRAWABLE_RESOLVED;
   3024 
   3025     // There are a couple of flags left in mPrivateFlags2
   3026 
   3027     /* End of masks for mPrivateFlags2 */
   3028 
   3029     /*
   3030      * Masks for mPrivateFlags3, as generated by dumpFlags():
   3031      *
   3032      * |-------|-------|-------|-------|
   3033      *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
   3034      *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
   3035      *                               1   PFLAG3_IS_LAID_OUT
   3036      *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
   3037      *                             1     PFLAG3_CALLED_SUPER
   3038      *                            1      PFLAG3_APPLYING_INSETS
   3039      *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
   3040      *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
   3041      *                         1         PFLAG3_SCROLL_INDICATOR_TOP
   3042      *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
   3043      *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
   3044      *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
   3045      *                     1             PFLAG3_SCROLL_INDICATOR_START
   3046      *                    1              PFLAG3_SCROLL_INDICATOR_END
   3047      *                   1               PFLAG3_ASSIST_BLOCKED
   3048      *                  1                PFLAG3_CLUSTER
   3049      *                 1                 PFLAG3_IS_AUTOFILLED
   3050      *                1                  PFLAG3_FINGER_DOWN
   3051      *               1                   PFLAG3_FOCUSED_BY_DEFAULT
   3052      *           1111                    PFLAG3_IMPORTANT_FOR_AUTOFILL
   3053      *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
   3054      *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
   3055      *        1                          PFLAG3_TEMPORARY_DETACH
   3056      *       1                           PFLAG3_NO_REVEAL_ON_FOCUS
   3057      *      1                            PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT
   3058      *     1                             PFLAG3_SCREEN_READER_FOCUSABLE
   3059      *    1                              PFLAG3_AGGREGATED_VISIBLE
   3060      *   1                               PFLAG3_AUTOFILLID_EXPLICITLY_SET
   3061      *  1                                PFLAG3_ACCESSIBILITY_HEADING
   3062      * |-------|-------|-------|-------|
   3063      */
   3064 
   3065     /**
   3066      * Flag indicating that view has a transform animation set on it. This is used to track whether
   3067      * an animation is cleared between successive frames, in order to tell the associated
   3068      * DisplayList to clear its animation matrix.
   3069      */
   3070     static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
   3071 
   3072     /**
   3073      * Flag indicating that view has an alpha animation set on it. This is used to track whether an
   3074      * animation is cleared between successive frames, in order to tell the associated
   3075      * DisplayList to restore its alpha value.
   3076      */
   3077     static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
   3078 
   3079     /**
   3080      * Flag indicating that the view has been through at least one layout since it
   3081      * was last attached to a window.
   3082      */
   3083     static final int PFLAG3_IS_LAID_OUT = 0x4;
   3084 
   3085     /**
   3086      * Flag indicating that a call to measure() was skipped and should be done
   3087      * instead when layout() is invoked.
   3088      */
   3089     static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
   3090 
   3091     /**
   3092      * Flag indicating that an overridden method correctly called down to
   3093      * the superclass implementation as required by the API spec.
   3094      */
   3095     static final int PFLAG3_CALLED_SUPER = 0x10;
   3096 
   3097     /**
   3098      * Flag indicating that we're in the process of applying window insets.
   3099      */
   3100     static final int PFLAG3_APPLYING_INSETS = 0x20;
   3101 
   3102     /**
   3103      * Flag indicating that we're in the process of fitting system windows using the old method.
   3104      */
   3105     static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
   3106 
   3107     /**
   3108      * Flag indicating that nested scrolling is enabled for this view.
   3109      * The view will optionally cooperate with views up its parent chain to allow for
   3110      * integrated nested scrolling along the same axis.
   3111      */
   3112     static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
   3113 
   3114     /**
   3115      * Flag indicating that the bottom scroll indicator should be displayed
   3116      * when this view can scroll up.
   3117      */
   3118     static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
   3119 
   3120     /**
   3121      * Flag indicating that the bottom scroll indicator should be displayed
   3122      * when this view can scroll down.
   3123      */
   3124     static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
   3125 
   3126     /**
   3127      * Flag indicating that the left scroll indicator should be displayed
   3128      * when this view can scroll left.
   3129      */
   3130     static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
   3131 
   3132     /**
   3133      * Flag indicating that the right scroll indicator should be displayed
   3134      * when this view can scroll right.
   3135      */
   3136     static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
   3137 
   3138     /**
   3139      * Flag indicating that the start scroll indicator should be displayed
   3140      * when this view can scroll in the start direction.
   3141      */
   3142     static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
   3143 
   3144     /**
   3145      * Flag indicating that the end scroll indicator should be displayed
   3146      * when this view can scroll in the end direction.
   3147      */
   3148     static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
   3149 
   3150     static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
   3151 
   3152     static final int SCROLL_INDICATORS_NONE = 0x0000;
   3153 
   3154     /**
   3155      * Mask for use with setFlags indicating bits used for indicating which
   3156      * scroll indicators are enabled.
   3157      */
   3158     static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
   3159             | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
   3160             | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
   3161             | PFLAG3_SCROLL_INDICATOR_END;
   3162 
   3163     /**
   3164      * Left-shift required to translate between public scroll indicator flags
   3165      * and internal PFLAGS3 flags. When used as a right-shift, translates
   3166      * PFLAGS3 flags to public flags.
   3167      */
   3168     static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
   3169 
   3170     /** @hide */
   3171     @Retention(RetentionPolicy.SOURCE)
   3172     @IntDef(flag = true, prefix = { "SCROLL_INDICATOR_" }, value = {
   3173             SCROLL_INDICATOR_TOP,
   3174             SCROLL_INDICATOR_BOTTOM,
   3175             SCROLL_INDICATOR_LEFT,
   3176             SCROLL_INDICATOR_RIGHT,
   3177             SCROLL_INDICATOR_START,
   3178             SCROLL_INDICATOR_END,
   3179     })
   3180     public @interface ScrollIndicators {}
   3181 
   3182     /**
   3183      * Scroll indicator direction for the top edge of the view.
   3184      *
   3185      * @see #setScrollIndicators(int)
   3186      * @see #setScrollIndicators(int, int)
   3187      * @see #getScrollIndicators()
   3188      */
   3189     public static final int SCROLL_INDICATOR_TOP =
   3190             PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   3191 
   3192     /**
   3193      * Scroll indicator direction for the bottom edge of the view.
   3194      *
   3195      * @see #setScrollIndicators(int)
   3196      * @see #setScrollIndicators(int, int)
   3197      * @see #getScrollIndicators()
   3198      */
   3199     public static final int SCROLL_INDICATOR_BOTTOM =
   3200             PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   3201 
   3202     /**
   3203      * Scroll indicator direction for the left edge of the view.
   3204      *
   3205      * @see #setScrollIndicators(int)
   3206      * @see #setScrollIndicators(int, int)
   3207      * @see #getScrollIndicators()
   3208      */
   3209     public static final int SCROLL_INDICATOR_LEFT =
   3210             PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   3211 
   3212     /**
   3213      * Scroll indicator direction for the right edge of the view.
   3214      *
   3215      * @see #setScrollIndicators(int)
   3216      * @see #setScrollIndicators(int, int)
   3217      * @see #getScrollIndicators()
   3218      */
   3219     public static final int SCROLL_INDICATOR_RIGHT =
   3220             PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   3221 
   3222     /**
   3223      * Scroll indicator direction for the starting edge of the view.
   3224      * <p>
   3225      * Resolved according to the view's layout direction, see
   3226      * {@link #getLayoutDirection()} for more information.
   3227      *
   3228      * @see #setScrollIndicators(int)
   3229      * @see #setScrollIndicators(int, int)
   3230      * @see #getScrollIndicators()
   3231      */
   3232     public static final int SCROLL_INDICATOR_START =
   3233             PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   3234 
   3235     /**
   3236      * Scroll indicator direction for the ending edge of the view.
   3237      * <p>
   3238      * Resolved according to the view's layout direction, see
   3239      * {@link #getLayoutDirection()} for more information.
   3240      *
   3241      * @see #setScrollIndicators(int)
   3242      * @see #setScrollIndicators(int, int)
   3243      * @see #getScrollIndicators()
   3244      */
   3245     public static final int SCROLL_INDICATOR_END =
   3246             PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   3247 
   3248     /**
   3249      * <p>Indicates that we are allowing {@link ViewStructure} to traverse
   3250      * into this view.<p>
   3251      */
   3252     static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
   3253 
   3254     /**
   3255      * Flag indicating that the view is a root of a keyboard navigation cluster.
   3256      *
   3257      * @see #isKeyboardNavigationCluster()
   3258      * @see #setKeyboardNavigationCluster(boolean)
   3259      */
   3260     private static final int PFLAG3_CLUSTER = 0x8000;
   3261 
   3262     /**
   3263      * Flag indicating that the view is autofilled
   3264      *
   3265      * @see #isAutofilled()
   3266      * @see #setAutofilled(boolean)
   3267      */
   3268     private static final int PFLAG3_IS_AUTOFILLED = 0x10000;
   3269 
   3270     /**
   3271      * Indicates that the user is currently touching the screen.
   3272      * Currently used for the tooltip positioning only.
   3273      */
   3274     private static final int PFLAG3_FINGER_DOWN = 0x20000;
   3275 
   3276     /**
   3277      * Flag indicating that this view is the default-focus view.
   3278      *
   3279      * @see #isFocusedByDefault()
   3280      * @see #setFocusedByDefault(boolean)
   3281      */
   3282     private static final int PFLAG3_FOCUSED_BY_DEFAULT = 0x40000;
   3283 
   3284     /**
   3285      * Shift for the bits in {@link #mPrivateFlags3} related to the
   3286      * "importantForAutofill" attribute.
   3287      */
   3288     static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT = 19;
   3289 
   3290     /**
   3291      * Mask for obtaining the bits which specify how to determine
   3292      * whether a view is important for autofill.
   3293      */
   3294     static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK = (IMPORTANT_FOR_AUTOFILL_AUTO
   3295             | IMPORTANT_FOR_AUTOFILL_YES | IMPORTANT_FOR_AUTOFILL_NO
   3296             | IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
   3297             | IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS)
   3298             << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
   3299 
   3300     /**
   3301      * Whether this view has rendered elements that overlap (see {@link
   3302      * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
   3303      * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
   3304      * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
   3305      * determined by whatever {@link #hasOverlappingRendering()} returns.
   3306      */
   3307     private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
   3308 
   3309     /**
   3310      * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
   3311      * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
   3312      */
   3313     private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
   3314 
   3315     /**
   3316      * Flag indicating that the view is temporarily detached from the parent view.
   3317      *
   3318      * @see #onStartTemporaryDetach()
   3319      * @see #onFinishTemporaryDetach()
   3320      */
   3321     static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
   3322 
   3323     /**
   3324      * Flag indicating that the view does not wish to be revealed within its parent
   3325      * hierarchy when it gains focus. Expressed in the negative since the historical
   3326      * default behavior is to reveal on focus; this flag suppresses that behavior.
   3327      *
   3328      * @see #setRevealOnFocusHint(boolean)
   3329      * @see #getRevealOnFocusHint()
   3330      */
   3331     private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
   3332 
   3333     /**
   3334      * Flag indicating that when layout is completed we should notify
   3335      * that the view was entered for autofill purposes. To minimize
   3336      * showing autofill for views not visible to the user we evaluate
   3337      * user visibility which cannot be done until the view is laid out.
   3338      */
   3339     static final int PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT = 0x8000000;
   3340 
   3341     /**
   3342      * Works like focusable for screen readers, but without the side effects on input focus.
   3343      * @see #setScreenReaderFocusable(boolean)
   3344      */
   3345     private static final int PFLAG3_SCREEN_READER_FOCUSABLE = 0x10000000;
   3346 
   3347     /**
   3348      * The last aggregated visibility. Used to detect when it truly changes.
   3349      */
   3350     private static final int PFLAG3_AGGREGATED_VISIBLE = 0x20000000;
   3351 
   3352     /**
   3353      * Used to indicate that {@link #mAutofillId} was explicitly set through
   3354      * {@link #setAutofillId(AutofillId)}.
   3355      */
   3356     private static final int PFLAG3_AUTOFILLID_EXPLICITLY_SET = 0x40000000;
   3357 
   3358     /**
   3359      * Indicates if the View is a heading for accessibility purposes
   3360      */
   3361     private static final int PFLAG3_ACCESSIBILITY_HEADING = 0x80000000;
   3362 
   3363     /* End of masks for mPrivateFlags3 */
   3364 
   3365     /** @hide */
   3366     protected static final int VIEW_STRUCTURE_FOR_ASSIST = 0;
   3367     /** @hide */
   3368     protected  static final int VIEW_STRUCTURE_FOR_AUTOFILL = 1;
   3369     /** @hide */
   3370     protected  static final int VIEW_STRUCTURE_FOR_CONTENT_CAPTURE = 2;
   3371 
   3372     /** @hide */
   3373     @IntDef(flag = true, prefix = { "VIEW_STRUCTURE_FOR" }, value = {
   3374             VIEW_STRUCTURE_FOR_ASSIST,
   3375             VIEW_STRUCTURE_FOR_AUTOFILL,
   3376             VIEW_STRUCTURE_FOR_CONTENT_CAPTURE
   3377     })
   3378     @Retention(RetentionPolicy.SOURCE)
   3379     public @interface ViewStructureType {}
   3380 
   3381     /**
   3382      * Always allow a user to over-scroll this view, provided it is a
   3383      * view that can scroll.
   3384      *
   3385      * @see #getOverScrollMode()
   3386      * @see #setOverScrollMode(int)
   3387      */
   3388     public static final int OVER_SCROLL_ALWAYS = 0;
   3389 
   3390     /**
   3391      * Allow a user to over-scroll this view only if the content is large
   3392      * enough to meaningfully scroll, provided it is a view that can scroll.
   3393      *
   3394      * @see #getOverScrollMode()
   3395      * @see #setOverScrollMode(int)
   3396      */
   3397     public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
   3398 
   3399     /**
   3400      * Never allow a user to over-scroll this view.
   3401      *
   3402      * @see #getOverScrollMode()
   3403      * @see #setOverScrollMode(int)
   3404      */
   3405     public static final int OVER_SCROLL_NEVER = 2;
   3406 
   3407     /**
   3408      * Special constant for {@link #setSystemUiVisibility(int)}: View has
   3409      * requested the system UI (status bar) to be visible (the default).
   3410      *
   3411      * @see #setSystemUiVisibility(int)
   3412      */
   3413     public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
   3414 
   3415     /**
   3416      * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
   3417      * system UI to enter an unobtrusive "low profile" mode.
   3418      *
   3419      * <p>This is for use in games, book readers, video players, or any other
   3420      * "immersive" application where the usual system chrome is deemed too distracting.
   3421      *
   3422      * <p>In low profile mode, the status bar and/or navigation icons may dim.
   3423      *
   3424      * @see #setSystemUiVisibility(int)
   3425      */
   3426     public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
   3427 
   3428     /**
   3429      * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
   3430      * system navigation be temporarily hidden.
   3431      *
   3432      * <p>This is an even less obtrusive state than that called for by
   3433      * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
   3434      * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
   3435      * those to disappear. This is useful (in conjunction with the
   3436      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
   3437      * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
   3438      * window flags) for displaying content using every last pixel on the display.
   3439      *
   3440      * <p>There is a limitation: because navigation controls are so important, the least user
   3441      * interaction will cause them to reappear immediately.  When this happens, both
   3442      * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
   3443      * so that both elements reappear at the same time.
   3444      *
   3445      * @see #setSystemUiVisibility(int)
   3446      */
   3447     public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
   3448 
   3449     /**
   3450      * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
   3451      * into the normal fullscreen mode so that its content can take over the screen
   3452      * while still allowing the user to interact with the application.
   3453      *
   3454      * <p>This has the same visual effect as
   3455      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
   3456      * WindowManager.LayoutParams.FLAG_FULLSCREEN},
   3457      * meaning that non-critical screen decorations (such as the status bar) will be
   3458      * hidden while the user is in the View's window, focusing the experience on
   3459      * that content.  Unlike the window flag, if you are using ActionBar in
   3460      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
   3461      * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
   3462      * hide the action bar.
   3463      *
   3464      * <p>This approach to going fullscreen is best used over the window flag when
   3465      * it is a transient state -- that is, the application does this at certain
   3466      * points in its user interaction where it wants to allow the user to focus
   3467      * on content, but not as a continuous state.  For situations where the application
   3468      * would like to simply stay full screen the entire time (such as a game that
   3469      * wants to take over the screen), the
   3470      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
   3471      * is usually a better approach.  The state set here will be removed by the system
   3472      * in various situations (such as the user moving to another application) like
   3473      * the other system UI states.
   3474      *
   3475      * <p>When using this flag, the application should provide some easy facility
   3476      * for the user to go out of it.  A common example would be in an e-book
   3477      * reader, where tapping on the screen brings back whatever screen and UI
   3478      * decorations that had been hidden while the user was immersed in reading
   3479      * the book.
   3480      *
   3481      * @see #setSystemUiVisibility(int)
   3482      */
   3483     public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
   3484 
   3485     /**
   3486      * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
   3487      * flags, we would like a stable view of the content insets given to
   3488      * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
   3489      * will always represent the worst case that the application can expect
   3490      * as a continuous state.  In the stock Android UI this is the space for
   3491      * the system bar, nav bar, and status bar, but not more transient elements
   3492      * such as an input method.
   3493      *
   3494      * The stable layout your UI sees is based on the system UI modes you can
   3495      * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
   3496      * then you will get a stable layout for changes of the
   3497      * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
   3498      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
   3499      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
   3500      * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
   3501      * with a stable layout.  (Note that you should avoid using
   3502      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
   3503      *
   3504      * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
   3505      * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
   3506      * then a hidden status bar will be considered a "stable" state for purposes
   3507      * here.  This allows your UI to continually hide the status bar, while still
   3508      * using the system UI flags to hide the action bar while still retaining
   3509      * a stable layout.  Note that changing the window fullscreen flag will never
   3510      * provide a stable layout for a clean transition.
   3511      *
   3512      * <p>If you are using ActionBar in
   3513      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
   3514      * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
   3515      * insets it adds to those given to the application.
   3516      */
   3517     public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
   3518 
   3519     /**
   3520      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
   3521      * to be laid out as if it has requested
   3522      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
   3523      * allows it to avoid artifacts when switching in and out of that mode, at
   3524      * the expense that some of its user interface may be covered by screen
   3525      * decorations when they are shown.  You can perform layout of your inner
   3526      * UI elements to account for the navigation system UI through the
   3527      * {@link #fitSystemWindows(Rect)} method.
   3528      */
   3529     public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
   3530 
   3531     /**
   3532      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
   3533      * to be laid out as if it has requested
   3534      * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
   3535      * allows it to avoid artifacts when switching in and out of that mode, at
   3536      * the expense that some of its user interface may be covered by screen
   3537      * decorations when they are shown.  You can perform layout of your inner
   3538      * UI elements to account for non-fullscreen system UI through the
   3539      * {@link #fitSystemWindows(Rect)} method.
   3540      *
   3541      * <p>Note: on displays that have a {@link DisplayCutout}, the window may still be placed
   3542      *  differently than if {@link #SYSTEM_UI_FLAG_FULLSCREEN} was set, if the
   3543      *  window's {@link WindowManager.LayoutParams#layoutInDisplayCutoutMode
   3544      *  layoutInDisplayCutoutMode} is
   3545      *  {@link WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
   3546      *  LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT}. To avoid this, use either of the other modes.
   3547      *
   3548      * @see WindowManager.LayoutParams#layoutInDisplayCutoutMode
   3549      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
   3550      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
   3551      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
   3552      */
   3553     public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
   3554 
   3555     /**
   3556      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
   3557      * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
   3558      * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
   3559      * user interaction.
   3560      * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
   3561      * has an effect when used in combination with that flag.</p>
   3562      */
   3563     public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
   3564 
   3565     /**
   3566      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
   3567      * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
   3568      * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
   3569      * experience while also hiding the system bars.  If this flag is not set,
   3570      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
   3571      * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
   3572      * if the user swipes from the top of the screen.
   3573      * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
   3574      * system gestures, such as swiping from the top of the screen.  These transient system bars
   3575      * will overlay apps content, may have some degree of transparency, and will automatically
   3576      * hide after a short timeout.
   3577      * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
   3578      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
   3579      * with one or both of those flags.</p>
   3580      */
   3581     public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
   3582 
   3583     /**
   3584      * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
   3585      * is compatible with light status bar backgrounds.
   3586      *
   3587      * <p>For this to take effect, the window must request
   3588      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
   3589      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
   3590      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
   3591      *         FLAG_TRANSLUCENT_STATUS}.
   3592      *
   3593      * @see android.R.attr#windowLightStatusBar
   3594      */
   3595     public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
   3596 
   3597     /**
   3598      * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
   3599      * trigger undefined behavior on older platforms with apps compiled against a new SDK.
   3600      */
   3601     private static final int SYSTEM_UI_RESERVED_LEGACY1 = 0x00004000;
   3602 
   3603     /**
   3604      * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
   3605      * trigger undefined behavior on older platforms with apps compiled against a new SDK.
   3606      */
   3607     private static final int SYSTEM_UI_RESERVED_LEGACY2 = 0x00010000;
   3608 
   3609     /**
   3610      * Flag for {@link #setSystemUiVisibility(int)}: Requests the navigation bar to draw in a mode
   3611      * that is compatible with light navigation bar backgrounds.
   3612      *
   3613      * <p>For this to take effect, the window must request
   3614      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
   3615      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
   3616      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION
   3617      *         FLAG_TRANSLUCENT_NAVIGATION}.
   3618      *
   3619      * @see android.R.attr#windowLightNavigationBar
   3620      */
   3621     public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010;
   3622 
   3623     /**
   3624      * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
   3625      */
   3626     @Deprecated
   3627     public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
   3628 
   3629     /**
   3630      * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
   3631      */
   3632     @Deprecated
   3633     public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
   3634 
   3635     /**
   3636      * @hide
   3637      *
   3638      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3639      * out of the public fields to keep the undefined bits out of the developer's way.
   3640      *
   3641      * Flag to make the status bar not expandable.  Unless you also
   3642      * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
   3643      */
   3644     @UnsupportedAppUsage
   3645     public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
   3646 
   3647     /**
   3648      * @hide
   3649      *
   3650      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3651      * out of the public fields to keep the undefined bits out of the developer's way.
   3652      *
   3653      * Flag to hide notification icons and scrolling ticker text.
   3654      */
   3655     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
   3656 
   3657     /**
   3658      * @hide
   3659      *
   3660      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3661      * out of the public fields to keep the undefined bits out of the developer's way.
   3662      *
   3663      * Flag to disable incoming notification alerts.  This will not block
   3664      * icons, but it will block sound, vibrating and other visual or aural notifications.
   3665      */
   3666     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
   3667 
   3668     /**
   3669      * @hide
   3670      *
   3671      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3672      * out of the public fields to keep the undefined bits out of the developer's way.
   3673      *
   3674      * Flag to hide only the scrolling ticker.  Note that
   3675      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
   3676      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
   3677      */
   3678     public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
   3679 
   3680     /**
   3681      * @hide
   3682      *
   3683      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3684      * out of the public fields to keep the undefined bits out of the developer's way.
   3685      *
   3686      * Flag to hide the center system info area.
   3687      */
   3688     public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
   3689 
   3690     /**
   3691      * @hide
   3692      *
   3693      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3694      * out of the public fields to keep the undefined bits out of the developer's way.
   3695      *
   3696      * Flag to hide only the home button.  Don't use this
   3697      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
   3698      */
   3699     @UnsupportedAppUsage
   3700     public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
   3701 
   3702     /**
   3703      * @hide
   3704      *
   3705      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3706      * out of the public fields to keep the undefined bits out of the developer's way.
   3707      *
   3708      * Flag to hide only the back button. Don't use this
   3709      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
   3710      */
   3711     @UnsupportedAppUsage
   3712     public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
   3713 
   3714     /**
   3715      * @hide
   3716      *
   3717      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3718      * out of the public fields to keep the undefined bits out of the developer's way.
   3719      *
   3720      * Flag to hide only the clock.  You might use this if your activity has
   3721      * its own clock making the status bar's clock redundant.
   3722      */
   3723     public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
   3724 
   3725     /**
   3726      * @hide
   3727      *
   3728      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3729      * out of the public fields to keep the undefined bits out of the developer's way.
   3730      *
   3731      * Flag to hide only the recent apps button. Don't use this
   3732      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
   3733      */
   3734     @UnsupportedAppUsage
   3735     public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
   3736 
   3737     /**
   3738      * @hide
   3739      *
   3740      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3741      * out of the public fields to keep the undefined bits out of the developer's way.
   3742      *
   3743      * Flag to disable the global search gesture. Don't use this
   3744      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
   3745      */
   3746     public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
   3747 
   3748     /**
   3749      * @hide
   3750      *
   3751      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3752      * out of the public fields to keep the undefined bits out of the developer's way.
   3753      *
   3754      * Flag to specify that the status bar is displayed in transient mode.
   3755      */
   3756     public static final int STATUS_BAR_TRANSIENT = 0x04000000;
   3757 
   3758     /**
   3759      * @hide
   3760      *
   3761      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3762      * out of the public fields to keep the undefined bits out of the developer's way.
   3763      *
   3764      * Flag to specify that the navigation bar is displayed in transient mode.
   3765      */
   3766     @UnsupportedAppUsage
   3767     public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
   3768 
   3769     /**
   3770      * @hide
   3771      *
   3772      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3773      * out of the public fields to keep the undefined bits out of the developer's way.
   3774      *
   3775      * Flag to specify that the hidden status bar would like to be shown.
   3776      */
   3777     public static final int STATUS_BAR_UNHIDE = 0x10000000;
   3778 
   3779     /**
   3780      * @hide
   3781      *
   3782      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3783      * out of the public fields to keep the undefined bits out of the developer's way.
   3784      *
   3785      * Flag to specify that the hidden navigation bar would like to be shown.
   3786      */
   3787     public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
   3788 
   3789     /**
   3790      * @hide
   3791      *
   3792      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3793      * out of the public fields to keep the undefined bits out of the developer's way.
   3794      *
   3795      * Flag to specify that the status bar is displayed in translucent mode.
   3796      */
   3797     public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
   3798 
   3799     /**
   3800      * @hide
   3801      *
   3802      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   3803      * out of the public fields to keep the undefined bits out of the developer's way.
   3804      *
   3805      * Flag to specify that the navigation bar is displayed in translucent mode.
   3806      */
   3807     public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
   3808 
   3809     /**
   3810      * @hide
   3811      *
   3812      * Makes navigation bar transparent (but not the status bar).
   3813      */
   3814     public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
   3815 
   3816     /**
   3817      * @hide
   3818      *
   3819      * Makes status bar transparent (but not the navigation bar).
   3820      */
   3821     public static final int STATUS_BAR_TRANSPARENT = 0x00000008;
   3822 
   3823     /**
   3824      * @hide
   3825      *
   3826      * Makes both status bar and navigation bar transparent.
   3827      */
   3828     public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
   3829             | STATUS_BAR_TRANSPARENT;
   3830 
   3831     /**
   3832      * @hide
   3833      */
   3834     public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
   3835 
   3836     /**
   3837      * These are the system UI flags that can be cleared by events outside
   3838      * of an application.  Currently this is just the ability to tap on the
   3839      * screen while hiding the navigation bar to have it return.
   3840      * @hide
   3841      */
   3842     public static final int SYSTEM_UI_CLEARABLE_FLAGS =
   3843             SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
   3844             | SYSTEM_UI_FLAG_FULLSCREEN;
   3845 
   3846     /**
   3847      * Flags that can impact the layout in relation to system UI.
   3848      */
   3849     public static final int SYSTEM_UI_LAYOUT_FLAGS =
   3850             SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
   3851             | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
   3852 
   3853     /** @hide */
   3854     @IntDef(flag = true, prefix = { "FIND_VIEWS_" }, value = {
   3855             FIND_VIEWS_WITH_TEXT,
   3856             FIND_VIEWS_WITH_CONTENT_DESCRIPTION
   3857     })
   3858     @Retention(RetentionPolicy.SOURCE)
   3859     public @interface FindViewFlags {}
   3860 
   3861     /**
   3862      * Find views that render the specified text.
   3863      *
   3864      * @see #findViewsWithText(ArrayList, CharSequence, int)
   3865      */
   3866     public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
   3867 
   3868     /**
   3869      * Find find views that contain the specified content description.
   3870      *
   3871      * @see #findViewsWithText(ArrayList, CharSequence, int)
   3872      */
   3873     public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
   3874 
   3875     /**
   3876      * Find views that contain {@link AccessibilityNodeProvider}. Such
   3877      * a View is a root of virtual view hierarchy and may contain the searched
   3878      * text. If this flag is set Views with providers are automatically
   3879      * added and it is a responsibility of the client to call the APIs of
   3880      * the provider to determine whether the virtual tree rooted at this View
   3881      * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
   3882      * representing the virtual views with this text.
   3883      *
   3884      * @see #findViewsWithText(ArrayList, CharSequence, int)
   3885      *
   3886      * @hide
   3887      */
   3888     public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
   3889 
   3890     /**
   3891      * The undefined cursor position.
   3892      *
   3893      * @hide
   3894      */
   3895     public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
   3896 
   3897     /**
   3898      * Indicates that the screen has changed state and is now off.
   3899      *
   3900      * @see #onScreenStateChanged(int)
   3901      */
   3902     public static final int SCREEN_STATE_OFF = 0x0;
   3903 
   3904     /**
   3905      * Indicates that the screen has changed state and is now on.
   3906      *
   3907      * @see #onScreenStateChanged(int)
   3908      */
   3909     public static final int SCREEN_STATE_ON = 0x1;
   3910 
   3911     /**
   3912      * Indicates no axis of view scrolling.
   3913      */
   3914     public static final int SCROLL_AXIS_NONE = 0;
   3915 
   3916     /**
   3917      * Indicates scrolling along the horizontal axis.
   3918      */
   3919     public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
   3920 
   3921     /**
   3922      * Indicates scrolling along the vertical axis.
   3923      */
   3924     public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
   3925 
   3926     /**
   3927      * Controls the over-scroll mode for this view.
   3928      * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
   3929      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
   3930      * and {@link #OVER_SCROLL_NEVER}.
   3931      */
   3932     private int mOverScrollMode;
   3933 
   3934     /**
   3935      * The parent this view is attached to.
   3936      * {@hide}
   3937      *
   3938      * @see #getParent()
   3939      */
   3940     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
   3941     protected ViewParent mParent;
   3942 
   3943     /**
   3944      * {@hide}
   3945      *
   3946      * Not available for general use. If you need help, hang up and then dial one of the following
   3947      * public APIs:
   3948      *
   3949      * @see #isAttachedToWindow() for current attach state
   3950      * @see #onAttachedToWindow() for subclasses performing work when becoming attached
   3951      * @see #onDetachedFromWindow() for subclasses performing work when becoming detached
   3952      * @see OnAttachStateChangeListener for other code performing work on attach/detach
   3953      * @see #getHandler() for posting messages to this view's UI thread/looper
   3954      * @see #getParent() for interacting with the parent chain
   3955      * @see #getWindowToken() for the current window token
   3956      * @see #getRootView() for the view at the root of the attached hierarchy
   3957      * @see #getDisplay() for the Display this view is presented on
   3958      * @see #getRootWindowInsets() for the current insets applied to the whole attached window
   3959      * @see #hasWindowFocus() for whether the attached window is currently focused
   3960      * @see #getWindowVisibility() for checking the visibility of the attached window
   3961      */
   3962     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
   3963     AttachInfo mAttachInfo;
   3964 
   3965     /**
   3966      * {@hide}
   3967      */
   3968     @ViewDebug.ExportedProperty(flagMapping = {
   3969         @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
   3970                 name = "FORCE_LAYOUT"),
   3971         @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
   3972                 name = "LAYOUT_REQUIRED"),
   3973         @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
   3974             name = "DRAWING_CACHE_INVALID", outputIf = false),
   3975         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
   3976         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
   3977         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
   3978     }, formatToHexString = true)
   3979 
   3980     /* @hide */
   3981     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769414)
   3982     public int mPrivateFlags;
   3983     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768943)
   3984     int mPrivateFlags2;
   3985     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 129147060)
   3986     int mPrivateFlags3;
   3987 
   3988     /**
   3989      * This view's request for the visibility of the status bar.
   3990      * @hide
   3991      */
   3992     @ViewDebug.ExportedProperty(flagMapping = {
   3993             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
   3994                     equals = SYSTEM_UI_FLAG_LOW_PROFILE,
   3995                     name = "LOW_PROFILE"),
   3996             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
   3997                     equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
   3998                     name = "HIDE_NAVIGATION"),
   3999             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_FULLSCREEN,
   4000                     equals = SYSTEM_UI_FLAG_FULLSCREEN,
   4001                     name = "FULLSCREEN"),
   4002             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_STABLE,
   4003                     equals = SYSTEM_UI_FLAG_LAYOUT_STABLE,
   4004                     name = "LAYOUT_STABLE"),
   4005             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
   4006                     equals = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
   4007                     name = "LAYOUT_HIDE_NAVIGATION"),
   4008             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
   4009                     equals = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
   4010                     name = "LAYOUT_FULLSCREEN"),
   4011             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE,
   4012                     equals = SYSTEM_UI_FLAG_IMMERSIVE,
   4013                     name = "IMMERSIVE"),
   4014             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
   4015                     equals = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
   4016                     name = "IMMERSIVE_STICKY"),
   4017             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
   4018                     equals = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
   4019                     name = "LIGHT_STATUS_BAR"),
   4020             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
   4021                     equals = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
   4022                     name = "LIGHT_NAVIGATION_BAR"),
   4023             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_EXPAND,
   4024                     equals = STATUS_BAR_DISABLE_EXPAND,
   4025                     name = "STATUS_BAR_DISABLE_EXPAND"),
   4026             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
   4027                     equals = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
   4028                     name = "STATUS_BAR_DISABLE_NOTIFICATION_ICONS"),
   4029             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
   4030                     equals = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
   4031                     name = "STATUS_BAR_DISABLE_NOTIFICATION_ALERTS"),
   4032             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
   4033                     equals = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
   4034                     name = "STATUS_BAR_DISABLE_NOTIFICATION_TICKER"),
   4035             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SYSTEM_INFO,
   4036                     equals = STATUS_BAR_DISABLE_SYSTEM_INFO,
   4037                     name = "STATUS_BAR_DISABLE_SYSTEM_INFO"),
   4038             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_HOME,
   4039                     equals = STATUS_BAR_DISABLE_HOME,
   4040                     name = "STATUS_BAR_DISABLE_HOME"),
   4041             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_BACK,
   4042                     equals = STATUS_BAR_DISABLE_BACK,
   4043                     name = "STATUS_BAR_DISABLE_BACK"),
   4044             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_CLOCK,
   4045                     equals = STATUS_BAR_DISABLE_CLOCK,
   4046                     name = "STATUS_BAR_DISABLE_CLOCK"),
   4047             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_RECENT,
   4048                     equals = STATUS_BAR_DISABLE_RECENT,
   4049                     name = "STATUS_BAR_DISABLE_RECENT"),
   4050             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SEARCH,
   4051                     equals = STATUS_BAR_DISABLE_SEARCH,
   4052                     name = "STATUS_BAR_DISABLE_SEARCH"),
   4053             @ViewDebug.FlagToString(mask = STATUS_BAR_TRANSIENT,
   4054                     equals = STATUS_BAR_TRANSIENT,
   4055                     name = "STATUS_BAR_TRANSIENT"),
   4056             @ViewDebug.FlagToString(mask = NAVIGATION_BAR_TRANSIENT,
   4057                     equals = NAVIGATION_BAR_TRANSIENT,
   4058                     name = "NAVIGATION_BAR_TRANSIENT"),
   4059             @ViewDebug.FlagToString(mask = STATUS_BAR_UNHIDE,
   4060                     equals = STATUS_BAR_UNHIDE,
   4061                     name = "STATUS_BAR_UNHIDE"),
   4062             @ViewDebug.FlagToString(mask = NAVIGATION_BAR_UNHIDE,
   4063                     equals = NAVIGATION_BAR_UNHIDE,
   4064                     name = "NAVIGATION_BAR_UNHIDE"),
   4065             @ViewDebug.FlagToString(mask = STATUS_BAR_TRANSLUCENT,
   4066                     equals = STATUS_BAR_TRANSLUCENT,
   4067                     name = "STATUS_BAR_TRANSLUCENT"),
   4068             @ViewDebug.FlagToString(mask = NAVIGATION_BAR_TRANSLUCENT,
   4069                     equals = NAVIGATION_BAR_TRANSLUCENT,
   4070                     name = "NAVIGATION_BAR_TRANSLUCENT"),
   4071             @ViewDebug.FlagToString(mask = NAVIGATION_BAR_TRANSPARENT,
   4072                     equals = NAVIGATION_BAR_TRANSPARENT,
   4073                     name = "NAVIGATION_BAR_TRANSPARENT"),
   4074             @ViewDebug.FlagToString(mask = STATUS_BAR_TRANSPARENT,
   4075                     equals = STATUS_BAR_TRANSPARENT,
   4076                     name = "STATUS_BAR_TRANSPARENT")
   4077     }, formatToHexString = true)
   4078     int mSystemUiVisibility;
   4079 
   4080     /**
   4081      * Reference count for transient state.
   4082      * @see #setHasTransientState(boolean)
   4083      */
   4084     int mTransientStateCount = 0;
   4085 
   4086     /**
   4087      * Count of how many windows this view has been attached to.
   4088      */
   4089     int mWindowAttachCount;
   4090 
   4091     /**
   4092      * The layout parameters associated with this view and used by the parent
   4093      * {@link android.view.ViewGroup} to determine how this view should be
   4094      * laid out.
   4095      *
   4096      * The field should not be used directly. Instead {@link #getLayoutParams()} and {@link
   4097      * #setLayoutParams(ViewGroup.LayoutParams)} should be used. The setter guarantees internal
   4098      * state correctness of the class.
   4099      * {@hide}
   4100      */
   4101     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
   4102     protected ViewGroup.LayoutParams mLayoutParams;
   4103 
   4104     /**
   4105      * The view flags hold various views states.
   4106      *
   4107      * Use {@link #setTransitionVisibility(int)} to change the visibility of this view without
   4108      * triggering updates.
   4109      * {@hide}
   4110      */
   4111     @ViewDebug.ExportedProperty(formatToHexString = true)
   4112     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
   4113     int mViewFlags;
   4114 
   4115     static class TransformationInfo {
   4116         /**
   4117          * The transform matrix for the View. This transform is calculated internally
   4118          * based on the translation, rotation, and scale properties.
   4119          *
   4120          * Do *not* use this variable directly; instead call getMatrix(), which will
   4121          * load the value from the View's RenderNode.
   4122          */
   4123         private final Matrix mMatrix = new Matrix();
   4124 
   4125         /**
   4126          * The inverse transform matrix for the View. This transform is calculated
   4127          * internally based on the translation, rotation, and scale properties.
   4128          *
   4129          * Do *not* use this variable directly; instead call getInverseMatrix(),
   4130          * which will load the value from the View's RenderNode.
   4131          */
   4132         private Matrix mInverseMatrix;
   4133 
   4134         /**
   4135          * The opacity of the View. This is a value from 0 to 1, where 0 means
   4136          * completely transparent and 1 means completely opaque.
   4137          */
   4138         @ViewDebug.ExportedProperty
   4139         private float mAlpha = 1f;
   4140 
   4141         /**
   4142          * The opacity of the view as manipulated by the Fade transition. This is a
   4143          * property only used by transitions, which is composited with the other alpha
   4144          * values to calculate the final visual alpha value.
   4145          */
   4146         float mTransitionAlpha = 1f;
   4147     }
   4148 
   4149     /** @hide */
   4150     @UnsupportedAppUsage
   4151     public TransformationInfo mTransformationInfo;
   4152 
   4153     /**
   4154      * Current clip bounds. to which all drawing of this view are constrained.
   4155      */
   4156     @ViewDebug.ExportedProperty(category = "drawing")
   4157     Rect mClipBounds = null;
   4158 
   4159     private boolean mLastIsOpaque;
   4160 
   4161     /**
   4162      * The distance in pixels from the left edge of this view's parent
   4163      * to the left edge of this view.
   4164      * {@hide}
   4165      */
   4166     @ViewDebug.ExportedProperty(category = "layout")
   4167     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
   4168     protected int mLeft;
   4169     /**
   4170      * The distance in pixels from the left edge of this view's parent
   4171      * to the right edge of this view.
   4172      * {@hide}
   4173      */
   4174     @ViewDebug.ExportedProperty(category = "layout")
   4175     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
   4176     protected int mRight;
   4177     /**
   4178      * The distance in pixels from the top edge of this view's parent
   4179      * to the top edge of this view.
   4180      * {@hide}
   4181      */
   4182     @ViewDebug.ExportedProperty(category = "layout")
   4183     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
   4184     protected int mTop;
   4185     /**
   4186      * The distance in pixels from the top edge of this view's parent
   4187      * to the bottom edge of this view.
   4188      * {@hide}
   4189      */
   4190     @ViewDebug.ExportedProperty(category = "layout")
   4191     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
   4192     protected int mBottom;
   4193 
   4194     /**
   4195      * The offset, in pixels, by which the content of this view is scrolled
   4196      * horizontally.
   4197      * Please use {@link View#getScrollX()} and {@link View#setScrollX(int)} instead of
   4198      * accessing these directly.
   4199      * {@hide}
   4200      */
   4201     @ViewDebug.ExportedProperty(category = "scrolling")
   4202     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
   4203     protected int mScrollX;
   4204     /**
   4205      * The offset, in pixels, by which the content of this view is scrolled
   4206      * vertically.
   4207      * Please use {@link View#getScrollY()} and {@link View#setScrollY(int)} instead of
   4208      * accessing these directly.
   4209      * {@hide}
   4210      */
   4211     @ViewDebug.ExportedProperty(category = "scrolling")
   4212     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
   4213     protected int mScrollY;
   4214 
   4215     /**
   4216      * The final computed left padding in pixels that is used for drawing. This is the distance in
   4217      * pixels between the left edge of this view and the left edge of its content.
   4218      * {@hide}
   4219      */
   4220     @ViewDebug.ExportedProperty(category = "padding")
   4221     @UnsupportedAppUsage
   4222     protected int mPaddingLeft = 0;
   4223     /**
   4224      * The final computed right padding in pixels that is used for drawing. This is the distance in
   4225      * pixels between the right edge of this view and the right edge of its content.
   4226      * {@hide}
   4227      */
   4228     @ViewDebug.ExportedProperty(category = "padding")
   4229     @UnsupportedAppUsage
   4230     protected int mPaddingRight = 0;
   4231     /**
   4232      * The final computed top padding in pixels that is used for drawing. This is the distance in
   4233      * pixels between the top edge of this view and the top edge of its content.
   4234      * {@hide}
   4235      */
   4236     @ViewDebug.ExportedProperty(category = "padding")
   4237     @UnsupportedAppUsage
   4238     protected int mPaddingTop;
   4239     /**
   4240      * The final computed bottom padding in pixels that is used for drawing. This is the distance in
   4241      * pixels between the bottom edge of this view and the bottom edge of its content.
   4242      * {@hide}
   4243      */
   4244     @ViewDebug.ExportedProperty(category = "padding")
   4245     @UnsupportedAppUsage
   4246     protected int mPaddingBottom;
   4247 
   4248     /**
   4249      * The layout insets in pixels, that is the distance in pixels between the
   4250      * visible edges of this view its bounds.
   4251      */
   4252     private Insets mLayoutInsets;
   4253 
   4254     /**
   4255      * Briefly describes the view and is primarily used for accessibility support.
   4256      */
   4257     private CharSequence mContentDescription;
   4258 
   4259     /**
   4260      * If this view represents a distinct part of the window, it can have a title that labels the
   4261      * area.
   4262      */
   4263     private CharSequence mAccessibilityPaneTitle;
   4264 
   4265     /**
   4266      * Specifies the id of a view for which this view serves as a label for
   4267      * accessibility purposes.
   4268      */
   4269     private int mLabelForId = View.NO_ID;
   4270 
   4271     /**
   4272      * Predicate for matching labeled view id with its label for
   4273      * accessibility purposes.
   4274      */
   4275     private MatchLabelForPredicate mMatchLabelForPredicate;
   4276 
   4277     /**
   4278      * Specifies a view before which this one is visited in accessibility traversal.
   4279      */
   4280     private int mAccessibilityTraversalBeforeId = NO_ID;
   4281 
   4282     /**
   4283      * Specifies a view after which this one is visited in accessibility traversal.
   4284      */
   4285     private int mAccessibilityTraversalAfterId = NO_ID;
   4286 
   4287     /**
   4288      * Predicate for matching a view by its id.
   4289      */
   4290     private MatchIdPredicate mMatchIdPredicate;
   4291 
   4292     /**
   4293      * The right padding after RTL resolution, but before taking account of scroll bars.
   4294      *
   4295      * @hide
   4296      */
   4297     @ViewDebug.ExportedProperty(category = "padding")
   4298     protected int mUserPaddingRight;
   4299 
   4300     /**
   4301      * The resolved bottom padding before taking account of scroll bars.
   4302      *
   4303      * @hide
   4304      */
   4305     @ViewDebug.ExportedProperty(category = "padding")
   4306     protected int mUserPaddingBottom;
   4307 
   4308     /**
   4309      * The left padding after RTL resolution, but before taking account of scroll bars.
   4310      *
   4311      * @hide
   4312      */
   4313     @ViewDebug.ExportedProperty(category = "padding")
   4314     protected int mUserPaddingLeft;
   4315 
   4316     /**
   4317      * Cache the paddingStart set by the user to append to the scrollbar's size.
   4318      *
   4319      */
   4320     @ViewDebug.ExportedProperty(category = "padding")
   4321     int mUserPaddingStart;
   4322 
   4323     /**
   4324      * Cache the paddingEnd set by the user to append to the scrollbar's size.
   4325      *
   4326      */
   4327     @ViewDebug.ExportedProperty(category = "padding")
   4328     int mUserPaddingEnd;
   4329 
   4330     /**
   4331      * The left padding as set by a setter method, a background's padding, or via XML property
   4332      * resolution. This value is the padding before LTR resolution or taking account of scrollbars.
   4333      *
   4334      * @hide
   4335      */
   4336     int mUserPaddingLeftInitial;
   4337 
   4338     /**
   4339      * The right padding as set by a setter method, a background's padding, or via XML property
   4340      * resolution. This value is the padding before LTR resolution or taking account of scrollbars.
   4341      *
   4342      * @hide
   4343      */
   4344     int mUserPaddingRightInitial;
   4345 
   4346     /**
   4347      * Default undefined padding
   4348      */
   4349     private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
   4350 
   4351     /**
   4352      * Cache if a left padding has been defined explicitly via padding, horizontal padding,
   4353      * or leftPadding in XML, or by setPadding(...) or setRelativePadding(...)
   4354      */
   4355     private boolean mLeftPaddingDefined = false;
   4356 
   4357     /**
   4358      * Cache if a right padding has been defined explicitly via padding, horizontal padding,
   4359      * or rightPadding in XML, or by setPadding(...) or setRelativePadding(...)
   4360      */
   4361     private boolean mRightPaddingDefined = false;
   4362 
   4363     /**
   4364      * @hide
   4365      */
   4366     int mOldWidthMeasureSpec = Integer.MIN_VALUE;
   4367     /**
   4368      * @hide
   4369      */
   4370     int mOldHeightMeasureSpec = Integer.MIN_VALUE;
   4371 
   4372     private LongSparseLongArray mMeasureCache;
   4373 
   4374     @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
   4375     @UnsupportedAppUsage
   4376     private Drawable mBackground;
   4377     private TintInfo mBackgroundTint;
   4378 
   4379     @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
   4380     private ForegroundInfo mForegroundInfo;
   4381 
   4382     private Drawable mScrollIndicatorDrawable;
   4383 
   4384     /**
   4385      * RenderNode used for backgrounds.
   4386      * <p>
   4387      * When non-null and valid, this is expected to contain an up-to-date copy
   4388      * of the background drawable. It is cleared on temporary detach, and reset
   4389      * on cleanup.
   4390      */
   4391     private RenderNode mBackgroundRenderNode;
   4392 
   4393     @UnsupportedAppUsage
   4394     private int mBackgroundResource;
   4395     private boolean mBackgroundSizeChanged;
   4396 
   4397     /** The default focus highlight.
   4398      * @see #mDefaultFocusHighlightEnabled
   4399      * @see Drawable#hasFocusStateSpecified()
   4400      */
   4401     private Drawable mDefaultFocusHighlight;
   4402     private Drawable mDefaultFocusHighlightCache;
   4403     private boolean mDefaultFocusHighlightSizeChanged;
   4404     /**
   4405      * True if the default focus highlight is needed on the target device.
   4406      */
   4407     private static boolean sUseDefaultFocusHighlight;
   4408 
   4409     /**
   4410      * True if zero-sized views can be focused.
   4411      */
   4412     private static boolean sCanFocusZeroSized;
   4413 
   4414     /**
   4415      * Always assign focus if a focusable View is available.
   4416      */
   4417     private static boolean sAlwaysAssignFocus;
   4418 
   4419     private String mTransitionName;
   4420 
   4421     static class TintInfo {
   4422         ColorStateList mTintList;
   4423         BlendMode mBlendMode;
   4424         boolean mHasTintMode;
   4425         boolean mHasTintList;
   4426     }
   4427 
   4428     private static class ForegroundInfo {
   4429         private Drawable mDrawable;
   4430         private TintInfo mTintInfo;
   4431         private int mGravity = Gravity.FILL;
   4432         private boolean mInsidePadding = true;
   4433         private boolean mBoundsChanged = true;
   4434         private final Rect mSelfBounds = new Rect();
   4435         private final Rect mOverlayBounds = new Rect();
   4436     }
   4437 
   4438     static class ListenerInfo {
   4439         /**
   4440          * Listener used to dispatch focus change events.
   4441          * This field should be made private, so it is hidden from the SDK.
   4442          * {@hide}
   4443          */
   4444         @UnsupportedAppUsage
   4445         protected OnFocusChangeListener mOnFocusChangeListener;
   4446 
   4447         /**
   4448          * Listeners for layout change events.
   4449          */
   4450         private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
   4451 
   4452         protected OnScrollChangeListener mOnScrollChangeListener;
   4453 
   4454         /**
   4455          * Listeners for attach events.
   4456          */
   4457         private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
   4458 
   4459         /**
   4460          * Listener used to dispatch click events.
   4461          * This field should be made private, so it is hidden from the SDK.
   4462          * {@hide}
   4463          */
   4464         @UnsupportedAppUsage
   4465         public OnClickListener mOnClickListener;
   4466 
   4467         /**
   4468          * Listener used to dispatch long click events.
   4469          * This field should be made private, so it is hidden from the SDK.
   4470          * {@hide}
   4471          */
   4472         @UnsupportedAppUsage
   4473         protected OnLongClickListener mOnLongClickListener;
   4474 
   4475         /**
   4476          * Listener used to dispatch context click events. This field should be made private, so it
   4477          * is hidden from the SDK.
   4478          * {@hide}
   4479          */
   4480         protected OnContextClickListener mOnContextClickListener;
   4481 
   4482         /**
   4483          * Listener used to build the context menu.
   4484          * This field should be made private, so it is hidden from the SDK.
   4485          * {@hide}
   4486          */
   4487         @UnsupportedAppUsage
   4488         protected OnCreateContextMenuListener mOnCreateContextMenuListener;
   4489 
   4490         @UnsupportedAppUsage
   4491         private OnKeyListener mOnKeyListener;
   4492 
   4493         @UnsupportedAppUsage
   4494         private OnTouchListener mOnTouchListener;
   4495 
   4496         @UnsupportedAppUsage
   4497         private OnHoverListener mOnHoverListener;
   4498 
   4499         @UnsupportedAppUsage
   4500         private OnGenericMotionListener mOnGenericMotionListener;
   4501 
   4502         @UnsupportedAppUsage
   4503         private OnDragListener mOnDragListener;
   4504 
   4505         private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
   4506 
   4507         OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
   4508 
   4509         OnCapturedPointerListener mOnCapturedPointerListener;
   4510 
   4511         private ArrayList<OnUnhandledKeyEventListener> mUnhandledKeyListeners;
   4512 
   4513         private WindowInsetsAnimationListener mWindowInsetsAnimationListener;
   4514 
   4515         /**
   4516          * This lives here since it's only valid for interactive views.
   4517          */
   4518         private List<Rect> mSystemGestureExclusionRects;
   4519 
   4520         /**
   4521          * Used to track {@link #mSystemGestureExclusionRects}
   4522          */
   4523         public RenderNode.PositionUpdateListener mPositionUpdateListener;
   4524     }
   4525 
   4526     @UnsupportedAppUsage
   4527     ListenerInfo mListenerInfo;
   4528 
   4529     private static class TooltipInfo {
   4530         /**
   4531          * Text to be displayed in a tooltip popup.
   4532          */
   4533         @Nullable
   4534         CharSequence mTooltipText;
   4535 
   4536         /**
   4537          * View-relative position of the tooltip anchor point.
   4538          */
   4539         int mAnchorX;
   4540         int mAnchorY;
   4541 
   4542         /**
   4543          * The tooltip popup.
   4544          */
   4545         @Nullable
   4546         TooltipPopup mTooltipPopup;
   4547 
   4548         /**
   4549          * Set to true if the tooltip was shown as a result of a long click.
   4550          */
   4551         boolean mTooltipFromLongClick;
   4552 
   4553         /**
   4554          * Keep these Runnables so that they can be used to reschedule.
   4555          */
   4556         Runnable mShowTooltipRunnable;
   4557         Runnable mHideTooltipRunnable;
   4558 
   4559         /**
   4560          * Hover move is ignored if it is within this distance in pixels from the previous one.
   4561          */
   4562         int mHoverSlop;
   4563 
   4564         /**
   4565          * Update the anchor position if it significantly (that is by at least mHoverSlop)
   4566          * different from the previously stored position. Ignoring insignificant changes
   4567          * filters out the jitter which is typical for such input sources as stylus.
   4568          *
   4569          * @return True if the position has been updated.
   4570          */
   4571         private boolean updateAnchorPos(MotionEvent event) {
   4572             final int newAnchorX = (int) event.getX();
   4573             final int newAnchorY = (int) event.getY();
   4574             if (Math.abs(newAnchorX - mAnchorX) <= mHoverSlop
   4575                     && Math.abs(newAnchorY - mAnchorY) <= mHoverSlop) {
   4576                 return false;
   4577             }
   4578             mAnchorX = newAnchorX;
   4579             mAnchorY = newAnchorY;
   4580             return true;
   4581         }
   4582 
   4583         /**
   4584          *  Clear the anchor position to ensure that the next change is considered significant.
   4585          */
   4586         private void clearAnchorPos() {
   4587             mAnchorX = Integer.MAX_VALUE;
   4588             mAnchorY = Integer.MAX_VALUE;
   4589         }
   4590     }
   4591 
   4592     TooltipInfo mTooltipInfo;
   4593 
   4594     // Temporary values used to hold (x,y) coordinates when delegating from the
   4595     // two-arg performLongClick() method to the legacy no-arg version.
   4596     private float mLongClickX = Float.NaN;
   4597     private float mLongClickY = Float.NaN;
   4598 
   4599     /**
   4600      * The application environment this view lives in.
   4601      * This field should be made private, so it is hidden from the SDK.
   4602      * {@hide}
   4603      */
   4604     @ViewDebug.ExportedProperty(deepExport = true)
   4605     @UnsupportedAppUsage
   4606     protected Context mContext;
   4607 
   4608     @UnsupportedAppUsage
   4609     private final Resources mResources;
   4610 
   4611     @UnsupportedAppUsage
   4612     private ScrollabilityCache mScrollCache;
   4613 
   4614     private int[] mDrawableState = null;
   4615 
   4616     ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
   4617 
   4618     /**
   4619      * Animator that automatically runs based on state changes.
   4620      */
   4621     private StateListAnimator mStateListAnimator;
   4622 
   4623     /**
   4624      * When this view has focus and the next focus is {@link #FOCUS_LEFT},
   4625      * the user may specify which view to go to next.
   4626      */
   4627     private int mNextFocusLeftId = View.NO_ID;
   4628 
   4629     /**
   4630      * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
   4631      * the user may specify which view to go to next.
   4632      */
   4633     private int mNextFocusRightId = View.NO_ID;
   4634 
   4635     /**
   4636      * When this view has focus and the next focus is {@link #FOCUS_UP},
   4637      * the user may specify which view to go to next.
   4638      */
   4639     private int mNextFocusUpId = View.NO_ID;
   4640 
   4641     /**
   4642      * When this view has focus and the next focus is {@link #FOCUS_DOWN},
   4643      * the user may specify which view to go to next.
   4644      */
   4645     private int mNextFocusDownId = View.NO_ID;
   4646 
   4647     /**
   4648      * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
   4649      * the user may specify which view to go to next.
   4650      */
   4651     int mNextFocusForwardId = View.NO_ID;
   4652 
   4653     /**
   4654      * User-specified next keyboard navigation cluster in the {@link #FOCUS_FORWARD} direction.
   4655      *
   4656      * @see #findUserSetNextKeyboardNavigationCluster(View, int)
   4657      */
   4658     int mNextClusterForwardId = View.NO_ID;
   4659 
   4660     /**
   4661      * Whether this View should use a default focus highlight when it gets focused but doesn't
   4662      * have {@link android.R.attr#state_focused} defined in its background.
   4663      */
   4664     boolean mDefaultFocusHighlightEnabled = true;
   4665 
   4666     private CheckForLongPress mPendingCheckForLongPress;
   4667     @UnsupportedAppUsage
   4668     private CheckForTap mPendingCheckForTap = null;
   4669     private PerformClick mPerformClick;
   4670     private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
   4671 
   4672     private UnsetPressedState mUnsetPressedState;
   4673 
   4674     /**
   4675      * Whether the long press's action has been invoked.  The tap's action is invoked on the
   4676      * up event while a long press is invoked as soon as the long press duration is reached, so
   4677      * a long press could be performed before the tap is checked, in which case the tap's action
   4678      * should not be invoked.
   4679      */
   4680     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
   4681     private boolean mHasPerformedLongPress;
   4682 
   4683     /**
   4684      * Whether a context click button is currently pressed down. This is true when the stylus is
   4685      * touching the screen and the primary button has been pressed, or if a mouse's right button is
   4686      * pressed. This is false once the button is released or if the stylus has been lifted.
   4687      */
   4688     private boolean mInContextButtonPress;
   4689 
   4690     /**
   4691      * Whether the next up event should be ignored for the purposes of gesture recognition. This is
   4692      * true after a stylus button press has occured, when the next up event should not be recognized
   4693      * as a tap.
   4694      */
   4695     private boolean mIgnoreNextUpEvent;
   4696 
   4697     /**
   4698      * The minimum height of the view. We'll try our best to have the height
   4699      * of this view to at least this amount.
   4700      */
   4701     @ViewDebug.ExportedProperty(category = "measurement")
   4702     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
   4703     private int mMinHeight;
   4704 
   4705     /**
   4706      * The minimum width of the view. We'll try our best to have the width
   4707      * of this view to at least this amount.
   4708      */
   4709     @ViewDebug.ExportedProperty(category = "measurement")
   4710     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
   4711     private int mMinWidth;
   4712 
   4713     /**
   4714      * The delegate to handle touch events that are physically in this view
   4715      * but should be handled by another view.
   4716      */
   4717     private TouchDelegate mTouchDelegate = null;
   4718 
   4719     /**
   4720      * While touch exploration is in use, set to true when hovering across boundaries and
   4721      * inside the touch area of the delegate at receiving {@link MotionEvent#ACTION_HOVER_ENTER}
   4722      * or {@link MotionEvent#ACTION_HOVER_MOVE}. False when leaving boundaries or receiving a
   4723      * {@link MotionEvent#ACTION_HOVER_EXIT}.
   4724      * Note that children of view group are excluded in the touch area.
   4725      * @see #dispatchTouchExplorationHoverEvent
   4726      */
   4727     private boolean mHoveringTouchDelegate = false;
   4728 
   4729     /**
   4730      * Solid color to use as a background when creating the drawing cache. Enables
   4731      * the cache to use 16 bit bitmaps instead of 32 bit.
   4732      */
   4733     private int mDrawingCacheBackgroundColor = 0;
   4734 
   4735     /**
   4736      * Special tree observer used when mAttachInfo is null.
   4737      */
   4738     private ViewTreeObserver mFloatingTreeObserver;
   4739 
   4740     /**
   4741      * Cache the touch slop from the context that created the view.
   4742      */
   4743     private int mTouchSlop;
   4744 
   4745     /**
   4746      * Object that handles automatic animation of view properties.
   4747      */
   4748     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
   4749     private ViewPropertyAnimator mAnimator = null;
   4750 
   4751     /**
   4752      * List of registered FrameMetricsObservers.
   4753      */
   4754     private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
   4755 
   4756     /**
   4757      * Flag indicating that a drag can cross window boundaries.  When
   4758      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
   4759      * with this flag set, all visible applications with targetSdkVersion >=
   4760      * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
   4761      * in the drag operation and receive the dragged content.
   4762      *
   4763      * <p>If this is the only flag set, then the drag recipient will only have access to text data
   4764      * and intents contained in the {@link ClipData} object. Access to URIs contained in the
   4765      * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p>
   4766      */
   4767     public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
   4768 
   4769     /**
   4770      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
   4771      * request read access to the content URI(s) contained in the {@link ClipData} object.
   4772      * @see android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION
   4773      */
   4774     public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
   4775 
   4776     /**
   4777      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
   4778      * request write access to the content URI(s) contained in the {@link ClipData} object.
   4779      * @see android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION
   4780      */
   4781     public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
   4782 
   4783     /**
   4784      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
   4785      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
   4786      * reboots until explicitly revoked with
   4787      * {@link android.content.Context#revokeUriPermission(Uri, int)} Context.revokeUriPermission}.
   4788      * @see android.content.Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION
   4789      */
   4790     public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
   4791             Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
   4792 
   4793     /**
   4794      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
   4795      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
   4796      * match against the original granted URI.
   4797      * @see android.content.Intent#FLAG_GRANT_PREFIX_URI_PERMISSION
   4798      */
   4799     public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
   4800             Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
   4801 
   4802     /**
   4803      * Flag indicating that the drag shadow will be opaque.  When
   4804      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
   4805      * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
   4806      */
   4807     public static final int DRAG_FLAG_OPAQUE = 1 << 9;
   4808 
   4809     /**
   4810      * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
   4811      */
   4812     private float mVerticalScrollFactor;
   4813 
   4814     /**
   4815      * Position of the vertical scroll bar.
   4816      */
   4817     @UnsupportedAppUsage
   4818     private int mVerticalScrollbarPosition;
   4819 
   4820     /**
   4821      * Position the scroll bar at the default position as determined by the system.
   4822      */
   4823     public static final int SCROLLBAR_POSITION_DEFAULT = 0;
   4824 
   4825     /**
   4826      * Position the scroll bar along the left edge.
   4827      */
   4828     public static final int SCROLLBAR_POSITION_LEFT = 1;
   4829 
   4830     /**
   4831      * Position the scroll bar along the right edge.
   4832      */
   4833     public static final int SCROLLBAR_POSITION_RIGHT = 2;
   4834 
   4835     /**
   4836      * Indicates that the view does not have a layer.
   4837      *
   4838      * @see #getLayerType()
   4839      * @see #setLayerType(int, android.graphics.Paint)
   4840      * @see #LAYER_TYPE_SOFTWARE
   4841      * @see #LAYER_TYPE_HARDWARE
   4842      */
   4843     public static final int LAYER_TYPE_NONE = 0;
   4844 
   4845     /**
   4846      * <p>Indicates that the view has a software layer. A software layer is backed
   4847      * by a bitmap and causes the view to be rendered using Android's software
   4848      * rendering pipeline, even if hardware acceleration is enabled.</p>
   4849      *
   4850      * <p>Software layers have various usages:</p>
   4851      * <p>When the application is not using hardware acceleration, a software layer
   4852      * is useful to apply a specific color filter and/or blending mode and/or
   4853      * translucency to a view and all its children.</p>
   4854      * <p>When the application is using hardware acceleration, a software layer
   4855      * is useful to render drawing primitives not supported by the hardware
   4856      * accelerated pipeline. It can also be used to cache a complex view tree
   4857      * into a texture and reduce the complexity of drawing operations. For instance,
   4858      * when animating a complex view tree with a translation, a software layer can
   4859      * be used to render the view tree only once.</p>
   4860      * <p>Software layers should be avoided when the affected view tree updates
   4861      * often. Every update will require to re-render the software layer, which can
   4862      * potentially be slow (particularly when hardware acceleration is turned on
   4863      * since the layer will have to be uploaded into a hardware texture after every
   4864      * update.)</p>
   4865      *
   4866      * @see #getLayerType()
   4867      * @see #setLayerType(int, android.graphics.Paint)
   4868      * @see #LAYER_TYPE_NONE
   4869      * @see #LAYER_TYPE_HARDWARE
   4870      */
   4871     public static final int LAYER_TYPE_SOFTWARE = 1;
   4872 
   4873     /**
   4874      * <p>Indicates that the view has a hardware layer. A hardware layer is backed
   4875      * by a hardware specific texture (generally Frame Buffer Objects or FBO on
   4876      * OpenGL hardware) and causes the view to be rendered using Android's hardware
   4877      * rendering pipeline, but only if hardware acceleration is turned on for the
   4878      * view hierarchy. When hardware acceleration is turned off, hardware layers
   4879      * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
   4880      *
   4881      * <p>A hardware layer is useful to apply a specific color filter and/or
   4882      * blending mode and/or translucency to a view and all its children.</p>
   4883      * <p>A hardware layer can be used to cache a complex view tree into a
   4884      * texture and reduce the complexity of drawing operations. For instance,
   4885      * when animating a complex view tree with a translation, a hardware layer can
   4886      * be used to render the view tree only once.</p>
   4887      * <p>A hardware layer can also be used to increase the rendering quality when
   4888      * rotation transformations are applied on a view. It can also be used to
   4889      * prevent potential clipping issues when applying 3D transforms on a view.</p>
   4890      *
   4891      * @see #getLayerType()
   4892      * @see #setLayerType(int, android.graphics.Paint)
   4893      * @see #LAYER_TYPE_NONE
   4894      * @see #LAYER_TYPE_SOFTWARE
   4895      */
   4896     public static final int LAYER_TYPE_HARDWARE = 2;
   4897 
   4898     /** @hide */
   4899     @IntDef(prefix = { "LAYER_TYPE_" }, value = {
   4900             LAYER_TYPE_NONE,
   4901             LAYER_TYPE_SOFTWARE,
   4902             LAYER_TYPE_HARDWARE
   4903     })
   4904     @Retention(RetentionPolicy.SOURCE)
   4905     public @interface LayerType {}
   4906 
   4907     @ViewDebug.ExportedProperty(category = "drawing", mapping = {
   4908             @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
   4909             @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
   4910             @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
   4911     })
   4912     int mLayerType = LAYER_TYPE_NONE;
   4913     Paint mLayerPaint;
   4914 
   4915     /**
   4916      * Set to true when drawing cache is enabled and cannot be created.
   4917      *
   4918      * @hide
   4919      */
   4920     @UnsupportedAppUsage
   4921     public boolean mCachingFailed;
   4922     @UnsupportedAppUsage
   4923     private Bitmap mDrawingCache;
   4924     @UnsupportedAppUsage
   4925     private Bitmap mUnscaledDrawingCache;
   4926 
   4927     /**
   4928      * RenderNode holding View properties, potentially holding a DisplayList of View content.
   4929      * <p>
   4930      * When non-null and valid, this is expected to contain an up-to-date copy
   4931      * of the View content. Its DisplayList content is cleared on temporary detach and reset on
   4932      * cleanup.
   4933      */
   4934     @UnsupportedAppUsage
   4935     final RenderNode mRenderNode;
   4936 
   4937     /**
   4938      * Set to true when the view is sending hover accessibility events because it
   4939      * is the innermost hovered view.
   4940      */
   4941     private boolean mSendingHoverAccessibilityEvents;
   4942 
   4943     /**
   4944      * Delegate for injecting accessibility functionality.
   4945      */
   4946     @UnsupportedAppUsage
   4947     AccessibilityDelegate mAccessibilityDelegate;
   4948 
   4949     /**
   4950      * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
   4951      * and add/remove objects to/from the overlay directly through the Overlay methods.
   4952      */
   4953     ViewOverlay mOverlay;
   4954 
   4955     /**
   4956      * The currently active parent view for receiving delegated nested scrolling events.
   4957      * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
   4958      * by {@link #stopNestedScroll()} at the same point where we clear
   4959      * requestDisallowInterceptTouchEvent.
   4960      */
   4961     private ViewParent mNestedScrollingParent;
   4962 
   4963     /**
   4964      * Consistency verifier for debugging purposes.
   4965      * @hide
   4966      */
   4967     protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
   4968             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
   4969                     new InputEventConsistencyVerifier(this, 0) : null;
   4970 
   4971     private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
   4972 
   4973     private int[] mTempNestedScrollConsumed;
   4974 
   4975     /**
   4976      * An overlay is going to draw this View instead of being drawn as part of this
   4977      * View's parent. mGhostView is the View in the Overlay that must be invalidated
   4978      * when this view is invalidated.
   4979      */
   4980     GhostView mGhostView;
   4981 
   4982     /**
   4983      * Holds pairs of adjacent attribute data: attribute name followed by its value.
   4984      * @hide
   4985      */
   4986     @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
   4987     public String[] mAttributes;
   4988 
   4989     /**
   4990      * Maps a Resource id to its name.
   4991      */
   4992     private static SparseArray<String> mAttributeMap;
   4993 
   4994     /**
   4995      * Queue of pending runnables. Used to postpone calls to post() until this
   4996      * view is attached and has a handler.
   4997      */
   4998     private HandlerActionQueue mRunQueue;
   4999 
   5000     /**
   5001      * The pointer icon when the mouse hovers on this view. The default is null.
   5002      */
   5003     private PointerIcon mPointerIcon;
   5004 
   5005     /**
   5006      * @hide
   5007      */
   5008     @UnsupportedAppUsage
   5009     String mStartActivityRequestWho;
   5010 
   5011     @Nullable
   5012     private RoundScrollbarRenderer mRoundScrollbarRenderer;
   5013 
   5014     /** Used to delay visibility updates sent to the autofill manager */
   5015     private Handler mVisibilityChangeForAutofillHandler;
   5016 
   5017     /**
   5018      * Used when app developers explicitly set the {@link ContentCaptureSession} associated with the
   5019      * view (through {@link #setContentCaptureSession(ContentCaptureSession)}.
   5020      */
   5021     @Nullable
   5022     private ContentCaptureSession mContentCaptureSession;
   5023 
   5024     @LayoutRes
   5025     private int mSourceLayoutId = ID_NULL;
   5026 
   5027     @Nullable
   5028     private SparseIntArray mAttributeSourceResId;
   5029 
   5030     @Nullable
   5031     private SparseArray<int[]> mAttributeResolutionStacks;
   5032 
   5033     @StyleRes
   5034     private int mExplicitStyle;
   5035 
   5036     /**
   5037      * Cached reference to the {@link ContentCaptureSession}, is reset on {@link #invalidate()}.
   5038      */
   5039     private ContentCaptureSession mCachedContentCaptureSession;
   5040 
   5041     /**
   5042      * Simple constructor to use when creating a view from code.
   5043      *
   5044      * @param context The Context the view is running in, through which it can
   5045      *        access the current theme, resources, etc.
   5046      */
   5047     public View(Context context) {
   5048         mContext = context;
   5049         mResources = context != null ? context.getResources() : null;
   5050         mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | FOCUSABLE_AUTO;
   5051         // Set some flags defaults
   5052         mPrivateFlags2 =
   5053                 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
   5054                 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
   5055                 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
   5056                 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
   5057                 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
   5058                 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
   5059         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
   5060         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
   5061         mUserPaddingStart = UNDEFINED_PADDING;
   5062         mUserPaddingEnd = UNDEFINED_PADDING;
   5063         mRenderNode = RenderNode.create(getClass().getName(), new ViewAnimationHostBridge(this));
   5064 
   5065         if (!sCompatibilityDone && context != null) {
   5066             final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
   5067 
   5068             // Older apps may need this compatibility hack for measurement.
   5069             sUseBrokenMakeMeasureSpec = targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1;
   5070 
   5071             // Older apps expect onMeasure() to always be called on a layout pass, regardless
   5072             // of whether a layout was requested on that View.
   5073             sIgnoreMeasureCache = targetSdkVersion < Build.VERSION_CODES.KITKAT;
   5074 
   5075             Canvas.sCompatibilityRestore = targetSdkVersion < Build.VERSION_CODES.M;
   5076             Canvas.sCompatibilitySetBitmap = targetSdkVersion < Build.VERSION_CODES.O;
   5077             Canvas.setCompatibilityVersion(targetSdkVersion);
   5078 
   5079             // In M and newer, our widgets can pass a "hint" value in the size
   5080             // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
   5081             // know what the expected parent size is going to be, so e.g. list items can size
   5082             // themselves at 1/3 the size of their container. It breaks older apps though,
   5083             // specifically apps that use some popular open source libraries.
   5084             sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < Build.VERSION_CODES.M;
   5085 
   5086             // Old versions of the platform would give different results from
   5087             // LinearLayout measurement passes using EXACTLY and non-EXACTLY
   5088             // modes, so we always need to run an additional EXACTLY pass.
   5089             sAlwaysRemeasureExactly = targetSdkVersion <= Build.VERSION_CODES.M;
   5090 
   5091             // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
   5092             // On N+, we throw, but that breaks compatibility with apps that use these methods.
   5093             sTextureViewIgnoresDrawableSetters = targetSdkVersion <= Build.VERSION_CODES.M;
   5094 
   5095             // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
   5096             // in apps so we target check it to avoid breaking existing apps.
   5097             sPreserveMarginParamsInLayoutParamConversion =
   5098                     targetSdkVersion >= Build.VERSION_CODES.N;
   5099 
   5100             sCascadedDragDrop = targetSdkVersion < Build.VERSION_CODES.N;
   5101 
   5102             sHasFocusableExcludeAutoFocusable = targetSdkVersion < Build.VERSION_CODES.O;
   5103 
   5104             sAutoFocusableOffUIThreadWontNotifyParents = targetSdkVersion < Build.VERSION_CODES.O;
   5105 
   5106             sUseDefaultFocusHighlight = context.getResources().getBoolean(
   5107                     com.android.internal.R.bool.config_useDefaultFocusHighlight);
   5108 
   5109             sThrowOnInvalidFloatProperties = targetSdkVersion >= Build.VERSION_CODES.P;
   5110 
   5111             sCanFocusZeroSized = targetSdkVersion < Build.VERSION_CODES.P;
   5112 
   5113             sAlwaysAssignFocus = targetSdkVersion < Build.VERSION_CODES.P;
   5114 
   5115             sAcceptZeroSizeDragShadow = targetSdkVersion < Build.VERSION_CODES.P;
   5116 
   5117             sBrokenInsetsDispatch = ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_FULL
   5118                     || targetSdkVersion < Build.VERSION_CODES.Q;
   5119 
   5120             sBrokenWindowBackground = targetSdkVersion < Build.VERSION_CODES.Q;
   5121 
   5122             sCompatibilityDone = true;
   5123         }
   5124     }
   5125 
   5126     /**
   5127      * Constructor that is called when inflating a view from XML. This is called
   5128      * when a view is being constructed from an XML file, supplying attributes
   5129      * that were specified in the XML file. This version uses a default style of
   5130      * 0, so the only attribute values applied are those in the Context's Theme
   5131      * and the given AttributeSet.
   5132      *
   5133      * <p>
   5134      * The method onFinishInflate() will be called after all children have been
   5135      * added.
   5136      *
   5137      * @param context The Context the view is running in, through which it can
   5138      *        access the current theme, resources, etc.
   5139      * @param attrs The attributes of the XML tag that is inflating the view.
   5140      * @see #View(Context, AttributeSet, int)
   5141      */
   5142     public View(Context context, @Nullable AttributeSet attrs) {
   5143         this(context, attrs, 0);
   5144     }
   5145 
   5146     /**
   5147      * Perform inflation from XML and apply a class-specific base style from a
   5148      * theme attribute. This constructor of View allows subclasses to use their
   5149      * own base style when they are inflating. For example, a Button class's
   5150      * constructor would call this version of the super class constructor and
   5151      * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
   5152      * allows the theme's button style to modify all of the base view attributes
   5153      * (in particular its background) as well as the Button class's attributes.
   5154      *
   5155      * @param context The Context the view is running in, through which it can
   5156      *        access the current theme, resources, etc.
   5157      * @param attrs The attributes of the XML tag that is inflating the view.
   5158      * @param defStyleAttr An attribute in the current theme that contains a
   5159      *        reference to a style resource that supplies default values for
   5160      *        the view. Can be 0 to not look for defaults.
   5161      * @see #View(Context, AttributeSet)
   5162      */
   5163     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
   5164         this(context, attrs, defStyleAttr, 0);
   5165     }
   5166 
   5167     /**
   5168      * Perform inflation from XML and apply a class-specific base style from a
   5169      * theme attribute or style resource. This constructor of View allows
   5170      * subclasses to use their own base style when they are inflating.
   5171      * <p>
   5172      * When determining the final value of a particular attribute, there are
   5173      * four inputs that come into play:
   5174      * <ol>
   5175      * <li>Any attribute values in the given AttributeSet.
   5176      * <li>The style resource specified in the AttributeSet (named "style").
   5177      * <li>The default style specified by <var>defStyleAttr</var>.
   5178      * <li>The default style specified by <var>defStyleRes</var>.
   5179      * <li>The base values in this theme.
   5180      * </ol>
   5181      * <p>
   5182      * Each of these inputs is considered in-order, with the first listed taking
   5183      * precedence over the following ones. In other words, if in the
   5184      * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
   5185      * , then the button's text will <em>always</em> be black, regardless of
   5186      * what is specified in any of the styles.
   5187      *
   5188      * @param context The Context the view is running in, through which it can
   5189      *        access the current theme, resources, etc.
   5190      * @param attrs The attributes of the XML tag that is inflating the view.
   5191      * @param defStyleAttr An attribute in the current theme that contains a
   5192      *        reference to a style resource that supplies default values for
   5193      *        the view. Can be 0 to not look for defaults.
   5194      * @param defStyleRes A resource identifier of a style resource that
   5195      *        supplies default values for the view, used only if
   5196      *        defStyleAttr is 0 or can not be found in the theme. Can be 0
   5197      *        to not look for defaults.
   5198      * @see #View(Context, AttributeSet, int)
   5199      */
   5200     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
   5201         this(context);
   5202 
   5203         mSourceLayoutId = Resources.getAttributeSetSourceResId(attrs);
   5204 
   5205         final TypedArray a = context.obtainStyledAttributes(
   5206                 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
   5207 
   5208         retrieveExplicitStyle(context.getTheme(), attrs);
   5209         saveAttributeDataForStyleable(context, com.android.internal.R.styleable.View, attrs, a,
   5210                 defStyleAttr, defStyleRes);
   5211 
   5212         if (sDebugViewAttributes) {
   5213             saveAttributeData(attrs, a);
   5214         }
   5215 
   5216         Drawable background = null;
   5217 
   5218         int leftPadding = -1;
   5219         int topPadding = -1;
   5220         int rightPadding = -1;
   5221         int bottomPadding = -1;
   5222         int startPadding = UNDEFINED_PADDING;
   5223         int endPadding = UNDEFINED_PADDING;
   5224 
   5225         int padding = -1;
   5226         int paddingHorizontal = -1;
   5227         int paddingVertical = -1;
   5228 
   5229         int viewFlagValues = 0;
   5230         int viewFlagMasks = 0;
   5231 
   5232         boolean setScrollContainer = false;
   5233 
   5234         int x = 0;
   5235         int y = 0;
   5236 
   5237         float tx = 0;
   5238         float ty = 0;
   5239         float tz = 0;
   5240         float elevation = 0;
   5241         float rotation = 0;
   5242         float rotationX = 0;
   5243         float rotationY = 0;
   5244         float sx = 1f;
   5245         float sy = 1f;
   5246         boolean transformSet = false;
   5247 
   5248         int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
   5249         int overScrollMode = mOverScrollMode;
   5250         boolean initializeScrollbars = false;
   5251         boolean initializeScrollIndicators = false;
   5252 
   5253         boolean startPaddingDefined = false;
   5254         boolean endPaddingDefined = false;
   5255         boolean leftPaddingDefined = false;
   5256         boolean rightPaddingDefined = false;
   5257 
   5258         final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
   5259 
   5260         // Set default values.
   5261         viewFlagValues |= FOCUSABLE_AUTO;
   5262         viewFlagMasks |= FOCUSABLE_AUTO;
   5263 
   5264         final int N = a.getIndexCount();
   5265         for (int i = 0; i < N; i++) {
   5266             int attr = a.getIndex(i);
   5267             switch (attr) {
   5268                 case com.android.internal.R.styleable.View_background:
   5269                     background = a.getDrawable(attr);
   5270                     break;
   5271                 case com.android.internal.R.styleable.View_padding:
   5272                     padding = a.getDimensionPixelSize(attr, -1);
   5273                     mUserPaddingLeftInitial = padding;
   5274                     mUserPaddingRightInitial = padding;
   5275                     leftPaddingDefined = true;
   5276                     rightPaddingDefined = true;
   5277                     break;
   5278                 case com.android.internal.R.styleable.View_paddingHorizontal:
   5279                     paddingHorizontal = a.getDimensionPixelSize(attr, -1);
   5280                     mUserPaddingLeftInitial = paddingHorizontal;
   5281                     mUserPaddingRightInitial = paddingHorizontal;
   5282                     leftPaddingDefined = true;
   5283                     rightPaddingDefined = true;
   5284                     break;
   5285                 case com.android.internal.R.styleable.View_paddingVertical:
   5286                     paddingVertical = a.getDimensionPixelSize(attr, -1);
   5287                     break;
   5288                 case com.android.internal.R.styleable.View_paddingLeft:
   5289                     leftPadding = a.getDimensionPixelSize(attr, -1);
   5290                     mUserPaddingLeftInitial = leftPadding;
   5291                     leftPaddingDefined = true;
   5292                     break;
   5293                 case com.android.internal.R.styleable.View_paddingTop:
   5294                     topPadding = a.getDimensionPixelSize(attr, -1);
   5295                     break;
   5296                 case com.android.internal.R.styleable.View_paddingRight:
   5297                     rightPadding = a.getDimensionPixelSize(attr, -1);
   5298                     mUserPaddingRightInitial = rightPadding;
   5299                     rightPaddingDefined = true;
   5300                     break;
   5301                 case com.android.internal.R.styleable.View_paddingBottom:
   5302                     bottomPadding = a.getDimensionPixelSize(attr, -1);
   5303                     break;
   5304                 case com.android.internal.R.styleable.View_paddingStart:
   5305                     startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
   5306                     startPaddingDefined = (startPadding != UNDEFINED_PADDING);
   5307                     break;
   5308                 case com.android.internal.R.styleable.View_paddingEnd:
   5309                     endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
   5310                     endPaddingDefined = (endPadding != UNDEFINED_PADDING);
   5311                     break;
   5312                 case com.android.internal.R.styleable.View_scrollX:
   5313                     x = a.getDimensionPixelOffset(attr, 0);
   5314                     break;
   5315                 case com.android.internal.R.styleable.View_scrollY:
   5316                     y = a.getDimensionPixelOffset(attr, 0);
   5317                     break;
   5318                 case com.android.internal.R.styleable.View_alpha:
   5319                     setAlpha(a.getFloat(attr, 1f));
   5320                     break;
   5321                 case com.android.internal.R.styleable.View_transformPivotX:
   5322                     setPivotX(a.getDimension(attr, 0));
   5323                     break;
   5324                 case com.android.internal.R.styleable.View_transformPivotY:
   5325                     setPivotY(a.getDimension(attr, 0));
   5326                     break;
   5327                 case com.android.internal.R.styleable.View_translationX:
   5328                     tx = a.getDimension(attr, 0);
   5329                     transformSet = true;
   5330                     break;
   5331                 case com.android.internal.R.styleable.View_translationY:
   5332                     ty = a.getDimension(attr, 0);
   5333                     transformSet = true;
   5334                     break;
   5335                 case com.android.internal.R.styleable.View_translationZ:
   5336                     tz = a.getDimension(attr, 0);
   5337                     transformSet = true;
   5338                     break;
   5339                 case com.android.internal.R.styleable.View_elevation:
   5340                     elevation = a.getDimension(attr, 0);
   5341                     transformSet = true;
   5342                     break;
   5343                 case com.android.internal.R.styleable.View_rotation:
   5344                     rotation = a.getFloat(attr, 0);
   5345                     transformSet = true;
   5346                     break;
   5347                 case com.android.internal.R.styleable.View_rotationX:
   5348                     rotationX = a.getFloat(attr, 0);
   5349                     transformSet = true;
   5350                     break;
   5351                 case com.android.internal.R.styleable.View_rotationY:
   5352                     rotationY = a.getFloat(attr, 0);
   5353                     transformSet = true;
   5354                     break;
   5355                 case com.android.internal.R.styleable.View_scaleX:
   5356                     sx = a.getFloat(attr, 1f);
   5357                     transformSet = true;
   5358                     break;
   5359                 case com.android.internal.R.styleable.View_scaleY:
   5360                     sy = a.getFloat(attr, 1f);
   5361                     transformSet = true;
   5362                     break;
   5363                 case com.android.internal.R.styleable.View_id:
   5364                     mID = a.getResourceId(attr, NO_ID);
   5365                     break;
   5366                 case com.android.internal.R.styleable.View_tag:
   5367                     mTag = a.getText(attr);
   5368                     break;
   5369                 case com.android.internal.R.styleable.View_fitsSystemWindows:
   5370                     if (a.getBoolean(attr, false)) {
   5371                         viewFlagValues |= FITS_SYSTEM_WINDOWS;
   5372                         viewFlagMasks |= FITS_SYSTEM_WINDOWS;
   5373                     }
   5374                     break;
   5375                 case com.android.internal.R.styleable.View_focusable:
   5376                     viewFlagValues = (viewFlagValues & ~FOCUSABLE_MASK) | getFocusableAttribute(a);
   5377                     if ((viewFlagValues & FOCUSABLE_AUTO) == 0) {
   5378                         viewFlagMasks |= FOCUSABLE_MASK;
   5379                     }
   5380                     break;
   5381                 case com.android.internal.R.styleable.View_focusableInTouchMode:
   5382                     if (a.getBoolean(attr, false)) {
   5383                         // unset auto focus since focusableInTouchMode implies explicit focusable
   5384                         viewFlagValues &= ~FOCUSABLE_AUTO;
   5385                         viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
   5386                         viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
   5387                     }
   5388                     break;
   5389                 case com.android.internal.R.styleable.View_clickable:
   5390                     if (a.getBoolean(attr, false)) {
   5391                         viewFlagValues |= CLICKABLE;
   5392                         viewFlagMasks |= CLICKABLE;
   5393                     }
   5394                     break;
   5395                 case com.android.internal.R.styleable.View_longClickable:
   5396                     if (a.getBoolean(attr, false)) {
   5397                         viewFlagValues |= LONG_CLICKABLE;
   5398                         viewFlagMasks |= LONG_CLICKABLE;
   5399                     }
   5400                     break;
   5401                 case com.android.internal.R.styleable.View_contextClickable:
   5402                     if (a.getBoolean(attr, false)) {
   5403                         viewFlagValues |= CONTEXT_CLICKABLE;
   5404                         viewFlagMasks |= CONTEXT_CLICKABLE;
   5405                     }
   5406                     break;
   5407                 case com.android.internal.R.styleable.View_saveEnabled:
   5408                     if (!a.getBoolean(attr, true)) {
   5409                         viewFlagValues |= SAVE_DISABLED;
   5410                         viewFlagMasks |= SAVE_DISABLED_MASK;
   5411                     }
   5412                     break;
   5413                 case com.android.internal.R.styleable.View_duplicateParentState:
   5414                     if (a.getBoolean(attr, false)) {
   5415                         viewFlagValues |= DUPLICATE_PARENT_STATE;
   5416                         viewFlagMasks |= DUPLICATE_PARENT_STATE;
   5417                     }
   5418                     break;
   5419                 case com.android.internal.R.styleable.View_visibility:
   5420                     final int visibility = a.getInt(attr, 0);
   5421                     if (visibility != 0) {
   5422                         viewFlagValues |= VISIBILITY_FLAGS[visibility];
   5423                         viewFlagMasks |= VISIBILITY_MASK;
   5424                     }
   5425                     break;
   5426                 case com.android.internal.R.styleable.View_layoutDirection:
   5427                     // Clear any layout direction flags (included resolved bits) already set
   5428                     mPrivateFlags2 &=
   5429                             ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
   5430                     // Set the layout direction flags depending on the value of the attribute
   5431                     final int layoutDirection = a.getInt(attr, -1);
   5432                     final int value = (layoutDirection != -1) ?
   5433                             LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
   5434                     mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
   5435                     break;
   5436                 case com.android.internal.R.styleable.View_drawingCacheQuality:
   5437                     final int cacheQuality = a.getInt(attr, 0);
   5438                     if (cacheQuality != 0) {
   5439                         viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
   5440                         viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
   5441                     }
   5442                     break;
   5443                 case com.android.internal.R.styleable.View_contentDescription:
   5444                     setContentDescription(a.getString(attr));
   5445                     break;
   5446                 case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
   5447                     setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
   5448                     break;
   5449                 case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
   5450                     setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
   5451                     break;
   5452                 case com.android.internal.R.styleable.View_labelFor:
   5453                     setLabelFor(a.getResourceId(attr, NO_ID));
   5454                     break;
   5455                 case com.android.internal.R.styleable.View_soundEffectsEnabled:
   5456                     if (!a.getBoolean(attr, true)) {
   5457                         viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
   5458                         viewFlagMasks |= SOUND_EFFECTS_ENABLED;
   5459                     }
   5460                     break;
   5461                 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
   5462                     if (!a.getBoolean(attr, true)) {
   5463                         viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
   5464                         viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
   5465                     }
   5466                     break;
   5467                 case R.styleable.View_scrollbars:
   5468                     final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
   5469                     if (scrollbars != SCROLLBARS_NONE) {
   5470                         viewFlagValues |= scrollbars;
   5471                         viewFlagMasks |= SCROLLBARS_MASK;
   5472                         initializeScrollbars = true;
   5473                     }
   5474                     break;
   5475                 //noinspection deprecation
   5476                 case R.styleable.View_fadingEdge:
   5477                     if (targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
   5478                         // Ignore the attribute starting with ICS
   5479                         break;
   5480                     }
   5481                     // With builds < ICS, fall through and apply fading edges
   5482                 case R.styleable.View_requiresFadingEdge:
   5483                     final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
   5484                     if (fadingEdge != FADING_EDGE_NONE) {
   5485                         viewFlagValues |= fadingEdge;
   5486                         viewFlagMasks |= FADING_EDGE_MASK;
   5487                         initializeFadingEdgeInternal(a);
   5488                     }
   5489                     break;
   5490                 case R.styleable.View_scrollbarStyle:
   5491                     scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
   5492                     if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
   5493                         viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
   5494                         viewFlagMasks |= SCROLLBARS_STYLE_MASK;
   5495                     }
   5496                     break;
   5497                 case R.styleable.View_isScrollContainer:
   5498                     setScrollContainer = true;
   5499                     if (a.getBoolean(attr, false)) {
   5500                         setScrollContainer(true);
   5501                     }
   5502                     break;
   5503                 case com.android.internal.R.styleable.View_keepScreenOn:
   5504                     if (a.getBoolean(attr, false)) {
   5505                         viewFlagValues |= KEEP_SCREEN_ON;
   5506                         viewFlagMasks |= KEEP_SCREEN_ON;
   5507                     }
   5508                     break;
   5509                 case R.styleable.View_filterTouchesWhenObscured:
   5510                     if (a.getBoolean(attr, false)) {
   5511                         viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
   5512                         viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
   5513                     }
   5514                     break;
   5515                 case R.styleable.View_nextFocusLeft:
   5516                     mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
   5517                     break;
   5518                 case R.styleable.View_nextFocusRight:
   5519                     mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
   5520                     break;
   5521                 case R.styleable.View_nextFocusUp:
   5522                     mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
   5523                     break;
   5524                 case R.styleable.View_nextFocusDown:
   5525                     mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
   5526                     break;
   5527                 case R.styleable.View_nextFocusForward:
   5528                     mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
   5529                     break;
   5530                 case R.styleable.View_nextClusterForward:
   5531                     mNextClusterForwardId = a.getResourceId(attr, View.NO_ID);
   5532                     break;
   5533                 case R.styleable.View_minWidth:
   5534                     mMinWidth = a.getDimensionPixelSize(attr, 0);
   5535                     break;
   5536                 case R.styleable.View_minHeight:
   5537                     mMinHeight = a.getDimensionPixelSize(attr, 0);
   5538                     break;
   5539                 case R.styleable.View_onClick:
   5540                     if (context.isRestricted()) {
   5541                         throw new IllegalStateException("The android:onClick attribute cannot "
   5542                                 + "be used within a restricted context");
   5543                     }
   5544 
   5545                     final String handlerName = a.getString(attr);
   5546                     if (handlerName != null) {
   5547                         setOnClickListener(new DeclaredOnClickListener(this, handlerName));
   5548                     }
   5549                     break;
   5550                 case R.styleable.View_overScrollMode:
   5551                     overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
   5552                     break;
   5553                 case R.styleable.View_verticalScrollbarPosition:
   5554                     mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
   5555                     break;
   5556                 case R.styleable.View_layerType:
   5557                     setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
   5558                     break;
   5559                 case R.styleable.View_textDirection:
   5560                     // Clear any text direction flag already set
   5561                     mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
   5562                     // Set the text direction flags depending on the value of the attribute
   5563                     final int textDirection = a.getInt(attr, -1);
   5564                     if (textDirection != -1) {
   5565                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
   5566                     }
   5567                     break;
   5568                 case R.styleable.View_textAlignment:
   5569                     // Clear any text alignment flag already set
   5570                     mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
   5571                     // Set the text alignment flag depending on the value of the attribute
   5572                     final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
   5573                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
   5574                     break;
   5575                 case R.styleable.View_importantForAccessibility:
   5576                     setImportantForAccessibility(a.getInt(attr,
   5577                             IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
   5578                     break;
   5579                 case R.styleable.View_accessibilityLiveRegion:
   5580                     setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
   5581                     break;
   5582                 case R.styleable.View_transitionName:
   5583                     setTransitionName(a.getString(attr));
   5584                     break;
   5585                 case R.styleable.View_nestedScrollingEnabled:
   5586                     setNestedScrollingEnabled(a.getBoolean(attr, false));
   5587                     break;
   5588                 case R.styleable.View_stateListAnimator:
   5589                     setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
   5590                             a.getResourceId(attr, 0)));
   5591                     break;
   5592                 case R.styleable.View_backgroundTint:
   5593                     // This will get applied later during setBackground().
   5594                     if (mBackgroundTint == null) {
   5595                         mBackgroundTint = new TintInfo();
   5596                     }
   5597                     mBackgroundTint.mTintList = a.getColorStateList(
   5598                             R.styleable.View_backgroundTint);
   5599                     mBackgroundTint.mHasTintList = true;
   5600                     break;
   5601                 case R.styleable.View_backgroundTintMode:
   5602                     // This will get applied later during setBackground().
   5603                     if (mBackgroundTint == null) {
   5604                         mBackgroundTint = new TintInfo();
   5605                     }
   5606                     mBackgroundTint.mBlendMode = Drawable.parseBlendMode(a.getInt(
   5607                             R.styleable.View_backgroundTintMode, -1), null);
   5608                     mBackgroundTint.mHasTintMode = true;
   5609                     break;
   5610                 case R.styleable.View_outlineProvider:
   5611                     setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
   5612                             PROVIDER_BACKGROUND));
   5613                     break;
   5614                 case R.styleable.View_foreground:
   5615                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
   5616                         setForeground(a.getDrawable(attr));
   5617                     }
   5618                     break;
   5619                 case R.styleable.View_foregroundGravity:
   5620                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
   5621                         setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
   5622                     }
   5623                     break;
   5624                 case R.styleable.View_foregroundTintMode:
   5625                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
   5626                         setForegroundTintBlendMode(
   5627                                 Drawable.parseBlendMode(a.getInt(attr, -1),
   5628                                         null));
   5629                     }
   5630                     break;
   5631                 case R.styleable.View_foregroundTint:
   5632                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
   5633                         setForegroundTintList(a.getColorStateList(attr));
   5634                     }
   5635                     break;
   5636                 case R.styleable.View_foregroundInsidePadding:
   5637                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
   5638                         if (mForegroundInfo == null) {
   5639                             mForegroundInfo = new ForegroundInfo();
   5640                         }
   5641                         mForegroundInfo.mInsidePadding = a.getBoolean(attr,
   5642                                 mForegroundInfo.mInsidePadding);
   5643                     }
   5644                     break;
   5645                 case R.styleable.View_scrollIndicators:
   5646                     final int scrollIndicators =
   5647                             (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
   5648                                     & SCROLL_INDICATORS_PFLAG3_MASK;
   5649                     if (scrollIndicators != 0) {
   5650                         mPrivateFlags3 |= scrollIndicators;
   5651                         initializeScrollIndicators = true;
   5652                     }
   5653                     break;
   5654                 case R.styleable.View_pointerIcon:
   5655                     final int resourceId = a.getResourceId(attr, 0);
   5656                     if (resourceId != 0) {
   5657                         setPointerIcon(PointerIcon.load(
   5658                                 context.getResources(), resourceId));
   5659                     } else {
   5660                         final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
   5661                         if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
   5662                             setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
   5663                         }
   5664                     }
   5665                     break;
   5666                 case R.styleable.View_forceHasOverlappingRendering:
   5667                     if (a.peekValue(attr) != null) {
   5668                         forceHasOverlappingRendering(a.getBoolean(attr, true));
   5669                     }
   5670                     break;
   5671                 case R.styleable.View_tooltipText:
   5672                     setTooltipText(a.getText(attr));
   5673                     break;
   5674                 case R.styleable.View_keyboardNavigationCluster:
   5675                     if (a.peekValue(attr) != null) {
   5676                         setKeyboardNavigationCluster(a.getBoolean(attr, true));
   5677                     }
   5678                     break;
   5679                 case R.styleable.View_focusedByDefault:
   5680                     if (a.peekValue(attr) != null) {
   5681                         setFocusedByDefault(a.getBoolean(attr, true));
   5682                     }
   5683                     break;
   5684                 case R.styleable.View_autofillHints:
   5685                     if (a.peekValue(attr) != null) {
   5686                         CharSequence[] rawHints = null;
   5687                         String rawString = null;
   5688 
   5689                         if (a.getType(attr) == TypedValue.TYPE_REFERENCE) {
   5690                             int resId = a.getResourceId(attr, 0);
   5691 
   5692                             try {
   5693                                 rawHints = a.getTextArray(attr);
   5694                             } catch (Resources.NotFoundException e) {
   5695                                 rawString = getResources().getString(resId);
   5696                             }
   5697                         } else {
   5698                             rawString = a.getString(attr);
   5699                         }
   5700 
   5701                         if (rawHints == null) {
   5702                             if (rawString == null) {
   5703                                 throw new IllegalArgumentException(
   5704                                         "Could not resolve autofillHints");
   5705                             } else {
   5706                                 rawHints = rawString.split(",");
   5707                             }
   5708                         }
   5709 
   5710                         String[] hints = new String[rawHints.length];
   5711 
   5712                         int numHints = rawHints.length;
   5713                         for (int rawHintNum = 0; rawHintNum < numHints; rawHintNum++) {
   5714                             hints[rawHintNum] = rawHints[rawHintNum].toString().trim();
   5715                         }
   5716                         setAutofillHints(hints);
   5717                     }
   5718                     break;
   5719                 case R.styleable.View_importantForAutofill:
   5720                     if (a.peekValue(attr) != null) {
   5721                         setImportantForAutofill(a.getInt(attr, IMPORTANT_FOR_AUTOFILL_AUTO));
   5722                     }
   5723                     break;
   5724                 case R.styleable.View_defaultFocusHighlightEnabled:
   5725                     if (a.peekValue(attr) != null) {
   5726                         setDefaultFocusHighlightEnabled(a.getBoolean(attr, true));
   5727                     }
   5728                     break;
   5729                 case R.styleable.View_screenReaderFocusable:
   5730                     if (a.peekValue(attr) != null) {
   5731                         setScreenReaderFocusable(a.getBoolean(attr, false));
   5732                     }
   5733                     break;
   5734                 case R.styleable.View_accessibilityPaneTitle:
   5735                     if (a.peekValue(attr) != null) {
   5736                         setAccessibilityPaneTitle(a.getString(attr));
   5737                     }
   5738                     break;
   5739                 case R.styleable.View_outlineSpotShadowColor:
   5740                     setOutlineSpotShadowColor(a.getColor(attr, Color.BLACK));
   5741                     break;
   5742                 case R.styleable.View_outlineAmbientShadowColor:
   5743                     setOutlineAmbientShadowColor(a.getColor(attr, Color.BLACK));
   5744                     break;
   5745                 case com.android.internal.R.styleable.View_accessibilityHeading:
   5746                     setAccessibilityHeading(a.getBoolean(attr, false));
   5747                     break;
   5748                 case R.styleable.View_forceDarkAllowed:
   5749                     mRenderNode.setForceDarkAllowed(a.getBoolean(attr, true));
   5750                     break;
   5751             }
   5752         }
   5753 
   5754         setOverScrollMode(overScrollMode);
   5755 
   5756         // Cache start/end user padding as we cannot fully resolve padding here (we don't have yet
   5757         // the resolved layout direction). Those cached values will be used later during padding
   5758         // resolution.
   5759         mUserPaddingStart = startPadding;
   5760         mUserPaddingEnd = endPadding;
   5761 
   5762         if (background != null) {
   5763             setBackground(background);
   5764         }
   5765 
   5766         // setBackground above will record that padding is currently provided by the background.
   5767         // If we have padding specified via xml, record that here instead and use it.
   5768         mLeftPaddingDefined = leftPaddingDefined;
   5769         mRightPaddingDefined = rightPaddingDefined;
   5770 
   5771         // Valid paddingHorizontal/paddingVertical beats leftPadding, rightPadding, topPadding,
   5772         // bottomPadding, and padding set by background.  Valid padding beats everything.
   5773         if (padding >= 0) {
   5774             leftPadding = padding;
   5775             topPadding = padding;
   5776             rightPadding = padding;
   5777             bottomPadding = padding;
   5778             mUserPaddingLeftInitial = padding;
   5779             mUserPaddingRightInitial = padding;
   5780         } else {
   5781             if (paddingHorizontal >= 0) {
   5782                 leftPadding = paddingHorizontal;
   5783                 rightPadding = paddingHorizontal;
   5784                 mUserPaddingLeftInitial = paddingHorizontal;
   5785                 mUserPaddingRightInitial = paddingHorizontal;
   5786             }
   5787             if (paddingVertical >= 0) {
   5788                 topPadding = paddingVertical;
   5789                 bottomPadding = paddingVertical;
   5790             }
   5791         }
   5792 
   5793         if (isRtlCompatibilityMode()) {
   5794             // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
   5795             // left / right padding are used if defined (meaning here nothing to do). If they are not
   5796             // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
   5797             // start / end and resolve them as left / right (layout direction is not taken into account).
   5798             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
   5799             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
   5800             // defined.
   5801             if (!mLeftPaddingDefined && startPaddingDefined) {
   5802                 leftPadding = startPadding;
   5803             }
   5804             mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
   5805             if (!mRightPaddingDefined && endPaddingDefined) {
   5806                 rightPadding = endPadding;
   5807             }
   5808             mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
   5809         } else {
   5810             // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
   5811             // values defined. Otherwise, left /right values are used.
   5812             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
   5813             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
   5814             // defined.
   5815             final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
   5816 
   5817             if (mLeftPaddingDefined && !hasRelativePadding) {
   5818                 mUserPaddingLeftInitial = leftPadding;
   5819             }
   5820             if (mRightPaddingDefined && !hasRelativePadding) {
   5821                 mUserPaddingRightInitial = rightPadding;
   5822             }
   5823         }
   5824 
   5825         // mPaddingTop and mPaddingBottom may have been set by setBackground(Drawable) so must pass
   5826         // them on if topPadding or bottomPadding are not valid.
   5827         internalSetPadding(
   5828                 mUserPaddingLeftInitial,
   5829                 topPadding >= 0 ? topPadding : mPaddingTop,
   5830                 mUserPaddingRightInitial,
   5831                 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
   5832 
   5833         if (viewFlagMasks != 0) {
   5834             setFlags(viewFlagValues, viewFlagMasks);
   5835         }
   5836 
   5837         if (initializeScrollbars) {
   5838             initializeScrollbarsInternal(a);
   5839         }
   5840 
   5841         if (initializeScrollIndicators) {
   5842             initializeScrollIndicatorsInternal();
   5843         }
   5844 
   5845         a.recycle();
   5846 
   5847         // Needs to be called after mViewFlags is set
   5848         if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
   5849             recomputePadding();
   5850         }
   5851 
   5852         if (x != 0 || y != 0) {
   5853             scrollTo(x, y);
   5854         }
   5855 
   5856         if (transformSet) {
   5857             setTranslationX(tx);
   5858             setTranslationY(ty);
   5859             setTranslationZ(tz);
   5860             setElevation(elevation);
   5861             setRotation(rotation);
   5862             setRotationX(rotationX);
   5863             setRotationY(rotationY);
   5864             setScaleX(sx);
   5865             setScaleY(sy);
   5866         }
   5867 
   5868         if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
   5869             setScrollContainer(true);
   5870         }
   5871 
   5872         computeOpaqueFlags();
   5873     }
   5874 
   5875     /**
   5876      * Returns the ordered list of resource ID that are considered when resolving attribute values
   5877      * for this {@link View}. The list will include layout resource ID if the View is inflated from
   5878      * XML. It will also include a set of explicit styles if specified in XML using
   5879      * {@code style="..."}. Finally, it will include the default styles resolved from the theme.
   5880      *
   5881      * <p>
   5882      * <b>Note:</b> this method will only return actual values if the view attribute debugging
   5883      * is enabled in Android developer options.
   5884      *
   5885      * @param attribute Attribute resource ID for which the resolution stack should be returned.
   5886      * @return ordered list of resource ID that are considered when resolving attribute values for
   5887      * this {@link View}.
   5888      */
   5889     @NonNull
   5890     public int[] getAttributeResolutionStack(@AttrRes int attribute) {
   5891         if (!sDebugViewAttributes
   5892                 || mAttributeResolutionStacks == null
   5893                 || mAttributeResolutionStacks.get(attribute) == null) {
   5894             return new int[0];
   5895         }
   5896         int[] attributeResolutionStack = mAttributeResolutionStacks.get(attribute);
   5897         int stackSize = attributeResolutionStack.length;
   5898         if (mSourceLayoutId != ID_NULL) {
   5899             stackSize++;
   5900         }
   5901 
   5902         int currentIndex = 0;
   5903         int[] stack = new int[stackSize];
   5904 
   5905         if (mSourceLayoutId != ID_NULL) {
   5906             stack[currentIndex] = mSourceLayoutId;
   5907             currentIndex++;
   5908         }
   5909         for (int i = 0; i < attributeResolutionStack.length; i++) {
   5910             stack[currentIndex] = attributeResolutionStack[i];
   5911             currentIndex++;
   5912         }
   5913         return stack;
   5914     }
   5915 
   5916     /**
   5917      * Returns the mapping of attribute resource ID to source resource ID where the attribute value
   5918      * was set. Source resource ID can either be a layout resource ID, if the value was set in XML
   5919      * within the View tag, or a style resource ID, if the attribute was set in a style. The source
   5920      * resource value will be one of the resource IDs from {@link #getAttributeSourceResourceMap()}.
   5921      *
   5922      * <p>
   5923      * <b>Note:</b> this method will only return actual values if the view attribute debugging
   5924      * is enabled in Android developer options.
   5925      *
   5926      * @return mapping of attribute resource ID to source resource ID where the attribute value
   5927      * was set.
   5928      */
   5929     @NonNull
   5930     public Map<Integer, Integer> getAttributeSourceResourceMap() {
   5931         HashMap<Integer, Integer> map = new HashMap<>();
   5932         if (!sDebugViewAttributes || mAttributeSourceResId == null) {
   5933             return map;
   5934         }
   5935         for (int i = 0; i < mAttributeSourceResId.size(); i++) {
   5936             map.put(mAttributeSourceResId.keyAt(i), mAttributeSourceResId.valueAt(i));
   5937         }
   5938         return map;
   5939     }
   5940 
   5941     /**
   5942      * Returns the resource ID for the style specified using {@code style="..."} in the
   5943      * {@link AttributeSet}'s backing XML element or {@link Resources#ID_NULL} otherwise if not
   5944      * specified or otherwise not applicable.
   5945      * <p>
   5946      * Each {@link View} can have an explicit style specified in the layout file.
   5947      * This style is used first during the {@link View} attribute resolution, then if an attribute
   5948      * is not defined there the resource system looks at default style and theme as fallbacks.
   5949      *
   5950      * <p>
   5951      * <b>Note:</b> this method will only return actual values if the view attribute debugging
   5952      * is enabled in Android developer options.
   5953      *
   5954      * @return The resource ID for the style specified using {@code style="..."} in the
   5955      *      {@link AttributeSet}'s backing XML element or {@link Resources#ID_NULL} otherwise
   5956      *      if not specified or otherwise not applicable.
   5957      */
   5958     @StyleRes
   5959     public int getExplicitStyle() {
   5960         if (!sDebugViewAttributes) {
   5961             return ID_NULL;
   5962         }
   5963         return mExplicitStyle;
   5964     }
   5965 
   5966     /**
   5967      * An implementation of OnClickListener that attempts to lazily load a
   5968      * named click handling method from a parent or ancestor context.
   5969      */
   5970     private static class DeclaredOnClickListener implements OnClickListener {
   5971         private final View mHostView;
   5972         private final String mMethodName;
   5973 
   5974         private Method mResolvedMethod;
   5975         private Context mResolvedContext;
   5976 
   5977         public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
   5978             mHostView = hostView;
   5979             mMethodName = methodName;
   5980         }
   5981 
   5982         @Override
   5983         public void onClick(@NonNull View v) {
   5984             if (mResolvedMethod == null) {
   5985                 resolveMethod(mHostView.getContext(), mMethodName);
   5986             }
   5987 
   5988             try {
   5989                 mResolvedMethod.invoke(mResolvedContext, v);
   5990             } catch (IllegalAccessException e) {
   5991                 throw new IllegalStateException(
   5992                         "Could not execute non-public method for android:onClick", e);
   5993             } catch (InvocationTargetException e) {
   5994                 throw new IllegalStateException(
   5995                         "Could not execute method for android:onClick", e);
   5996             }
   5997         }
   5998 
   5999         @NonNull
   6000         private void resolveMethod(@Nullable Context context, @NonNull String name) {
   6001             while (context != null) {
   6002                 try {
   6003                     if (!context.isRestricted()) {
   6004                         final Method method = context.getClass().getMethod(mMethodName, View.class);
   6005                         if (method != null) {
   6006                             mResolvedMethod = method;
   6007                             mResolvedContext = context;
   6008                             return;
   6009                         }
   6010                     }
   6011                 } catch (NoSuchMethodException e) {
   6012                     // Failed to find method, keep searching up the hierarchy.
   6013                 }
   6014 
   6015                 if (context instanceof ContextWrapper) {
   6016                     context = ((ContextWrapper) context).getBaseContext();
   6017                 } else {
   6018                     // Can't search up the hierarchy, null out and fail.
   6019                     context = null;
   6020                 }
   6021             }
   6022 
   6023             final int id = mHostView.getId();
   6024             final String idText = id == NO_ID ? "" : " with id '"
   6025                     + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
   6026             throw new IllegalStateException("Could not find method " + mMethodName
   6027                     + "(View) in a parent or ancestor Context for android:onClick "
   6028                     + "attribute defined on view " + mHostView.getClass() + idText);
   6029         }
   6030     }
   6031 
   6032     /**
   6033      * Non-public constructor for use in testing
   6034      */
   6035     @UnsupportedAppUsage
   6036     View() {
   6037         mResources = null;
   6038         mRenderNode = RenderNode.create(getClass().getName(), new ViewAnimationHostBridge(this));
   6039     }
   6040 
   6041     final boolean debugDraw() {
   6042         return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
   6043     }
   6044 
   6045     private static SparseArray<String> getAttributeMap() {
   6046         if (mAttributeMap == null) {
   6047             mAttributeMap = new SparseArray<>();
   6048         }
   6049         return mAttributeMap;
   6050     }
   6051 
   6052     private void retrieveExplicitStyle(@NonNull Resources.Theme theme,
   6053             @Nullable AttributeSet attrs) {
   6054         if (!sDebugViewAttributes) {
   6055             return;
   6056         }
   6057         mExplicitStyle = theme.getExplicitStyle(attrs);
   6058     }
   6059 
   6060     /**
   6061      * Stores debugging information about attributes. This should be called in a constructor by
   6062      * every custom {@link View} that uses a custom styleable. If the custom view does not call it,
   6063      * then the custom attributes used by this view will not be visible in layout inspection tools.
   6064      *
   6065      *  @param context Context under which this view is created.
   6066      * @param styleable A reference to styleable array R.styleable.Foo
   6067      * @param attrs AttributeSet used to construct this view.
   6068      * @param t Resolved {@link TypedArray} returned by a call to
   6069      *        {@link Resources#obtainAttributes(AttributeSet, int[])}.
   6070      * @param defStyleAttr Default style attribute passed into the view constructor.
   6071      * @param defStyleRes Default style resource passed into the view constructor.
   6072      */
   6073     public final void saveAttributeDataForStyleable(@NonNull Context context,
   6074             @NonNull int[] styleable, @Nullable AttributeSet attrs, @NonNull TypedArray t,
   6075             int defStyleAttr, int defStyleRes) {
   6076         if (!sDebugViewAttributes) {
   6077             return;
   6078         }
   6079 
   6080         int[] attributeResolutionStack = context.getTheme().getAttributeResolutionStack(
   6081                 defStyleAttr, defStyleRes, mExplicitStyle);
   6082 
   6083         if (mAttributeResolutionStacks == null) {
   6084             mAttributeResolutionStacks = new SparseArray<>();
   6085         }
   6086 
   6087         if (mAttributeSourceResId == null) {
   6088             mAttributeSourceResId = new SparseIntArray();
   6089         }
   6090 
   6091         final int indexCount = t.getIndexCount();
   6092         for (int j = 0; j < indexCount; ++j) {
   6093             final int index = t.getIndex(j);
   6094             mAttributeSourceResId.append(styleable[index], t.getSourceResourceId(index, 0));
   6095             mAttributeResolutionStacks.append(styleable[index], attributeResolutionStack);
   6096         }
   6097     }
   6098 
   6099     private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
   6100         final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
   6101         final int indexCount = t.getIndexCount();
   6102         final String[] attributes = new String[(attrsCount + indexCount) * 2];
   6103 
   6104         int i = 0;
   6105 
   6106         // Store raw XML attributes.
   6107         for (int j = 0; j < attrsCount; ++j) {
   6108             attributes[i] = attrs.getAttributeName(j);
   6109             attributes[i + 1] = attrs.getAttributeValue(j);
   6110             i += 2;
   6111         }
   6112 
   6113         // Store resolved styleable attributes.
   6114         final Resources res = t.getResources();
   6115         final SparseArray<String> attributeMap = getAttributeMap();
   6116         for (int j = 0; j < indexCount; ++j) {
   6117             final int index = t.getIndex(j);
   6118             if (!t.hasValueOrEmpty(index)) {
   6119                 // Value is undefined. Skip it.
   6120                 continue;
   6121             }
   6122 
   6123             final int resourceId = t.getResourceId(index, 0);
   6124             if (resourceId == 0) {
   6125                 // Value is not a reference. Skip it.
   6126                 continue;
   6127             }
   6128 
   6129             String resourceName = attributeMap.get(resourceId);
   6130             if (resourceName == null) {
   6131                 try {
   6132                     resourceName = res.getResourceName(resourceId);
   6133                 } catch (Resources.NotFoundException e) {
   6134                     resourceName = "0x" + Integer.toHexString(resourceId);
   6135                 }
   6136                 attributeMap.put(resourceId, resourceName);
   6137             }
   6138 
   6139             attributes[i] = resourceName;
   6140             attributes[i + 1] = t.getString(index);
   6141             i += 2;
   6142         }
   6143 
   6144         // Trim to fit contents.
   6145         final String[] trimmed = new String[i];
   6146         System.arraycopy(attributes, 0, trimmed, 0, i);
   6147         mAttributes = trimmed;
   6148     }
   6149 
   6150     @Override
   6151     public String toString() {
   6152         StringBuilder out = new StringBuilder(128);
   6153         out.append(getClass().getName());
   6154         out.append('{');
   6155         out.append(Integer.toHexString(System.identityHashCode(this)));
   6156         out.append(' ');
   6157         switch (mViewFlags&VISIBILITY_MASK) {
   6158             case VISIBLE: out.append('V'); break;
   6159             case INVISIBLE: out.append('I'); break;
   6160             case GONE: out.append('G'); break;
   6161             default: out.append('.'); break;
   6162         }
   6163         out.append((mViewFlags & FOCUSABLE) == FOCUSABLE ? 'F' : '.');
   6164         out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
   6165         out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
   6166         out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
   6167         out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
   6168         out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
   6169         out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
   6170         out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
   6171         out.append(' ');
   6172         out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
   6173         out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
   6174         out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
   6175         if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
   6176             out.append('p');
   6177         } else {
   6178             out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
   6179         }
   6180         out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
   6181         out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
   6182         out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
   6183         out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
   6184         out.append(' ');
   6185         out.append(mLeft);
   6186         out.append(',');
   6187         out.append(mTop);
   6188         out.append('-');
   6189         out.append(mRight);
   6190         out.append(',');
   6191         out.append(mBottom);
   6192         final int id = getId();
   6193         if (id != NO_ID) {
   6194             out.append(" #");
   6195             out.append(Integer.toHexString(id));
   6196             final Resources r = mResources;
   6197             if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
   6198                 try {
   6199                     String pkgname;
   6200                     switch (id&0xff000000) {
   6201                         case 0x7f000000:
   6202                             pkgname="app";
   6203                             break;
   6204                         case 0x01000000:
   6205                             pkgname="android";
   6206                             break;
   6207                         default:
   6208                             pkgname = r.getResourcePackageName(id);
   6209                             break;
   6210                     }
   6211                     String typename = r.getResourceTypeName(id);
   6212                     String entryname = r.getResourceEntryName(id);
   6213                     out.append(" ");
   6214                     out.append(pkgname);
   6215                     out.append(":");
   6216                     out.append(typename);
   6217                     out.append("/");
   6218                     out.append(entryname);
   6219                 } catch (Resources.NotFoundException e) {
   6220                 }
   6221             }
   6222         }
   6223         if (mAutofillId != null) {
   6224             out.append(" aid="); out.append(mAutofillId);
   6225         }
   6226         out.append("}");
   6227         return out.toString();
   6228     }
   6229 
   6230     /**
   6231      * <p>
   6232      * Initializes the fading edges from a given set of styled attributes. This
   6233      * method should be called by subclasses that need fading edges and when an
   6234      * instance of these subclasses is created programmatically rather than
   6235      * being inflated from XML. This method is automatically called when the XML
   6236      * is inflated.
   6237      * </p>
   6238      *
   6239      * @param a the styled attributes set to initialize the fading edges from
   6240      *
   6241      * @removed
   6242      */
   6243     protected void initializeFadingEdge(TypedArray a) {
   6244         // This method probably shouldn't have been included in the SDK to begin with.
   6245         // It relies on 'a' having been initialized using an attribute filter array that is
   6246         // not publicly available to the SDK. The old method has been renamed
   6247         // to initializeFadingEdgeInternal and hidden for framework use only;
   6248         // this one initializes using defaults to make it safe to call for apps.
   6249 
   6250         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
   6251 
   6252         initializeFadingEdgeInternal(arr);
   6253 
   6254         arr.recycle();
   6255     }
   6256 
   6257     /**
   6258      * <p>
   6259      * Initializes the fading edges from a given set of styled attributes. This
   6260      * method should be called by subclasses that need fading edges and when an
   6261      * instance of these subclasses is created programmatically rather than
   6262      * being inflated from XML. This method is automatically called when the XML
   6263      * is inflated.
   6264      * </p>
   6265      *
   6266      * @param a the styled attributes set to initialize the fading edges from
   6267      * @hide This is the real method; the public one is shimmed to be safe to call from apps.
   6268      */
   6269     protected void initializeFadingEdgeInternal(TypedArray a) {
   6270         initScrollCache();
   6271 
   6272         mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
   6273                 R.styleable.View_fadingEdgeLength,
   6274                 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
   6275     }
   6276 
   6277     /**
   6278      * Returns the size of the vertical faded edges used to indicate that more
   6279      * content in this view is visible.
   6280      *
   6281      * @return The size in pixels of the vertical faded edge or 0 if vertical
   6282      *         faded edges are not enabled for this view.
   6283      * @attr ref android.R.styleable#View_fadingEdgeLength
   6284      */
   6285     public int getVerticalFadingEdgeLength() {
   6286         if (isVerticalFadingEdgeEnabled()) {
   6287             ScrollabilityCache cache = mScrollCache;
   6288             if (cache != null) {
   6289                 return cache.fadingEdgeLength;
   6290             }
   6291         }
   6292         return 0;
   6293     }
   6294 
   6295     /**
   6296      * Set the size of the faded edge used to indicate that more content in this
   6297      * view is available.  Will not change whether the fading edge is enabled; use
   6298      * {@link #setVerticalFadingEdgeEnabled(boolean)} or
   6299      * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
   6300      * for the vertical or horizontal fading edges.
   6301      *
   6302      * @param length The size in pixels of the faded edge used to indicate that more
   6303      *        content in this view is visible.
   6304      */
   6305     public void setFadingEdgeLength(int length) {
   6306         initScrollCache();
   6307         mScrollCache.fadingEdgeLength = length;
   6308     }
   6309 
   6310     /**
   6311      * Returns the size of the horizontal faded edges used to indicate that more
   6312      * content in this view is visible.
   6313      *
   6314      * @return The size in pixels of the horizontal faded edge or 0 if horizontal
   6315      *         faded edges are not enabled for this view.
   6316      * @attr ref android.R.styleable#View_fadingEdgeLength
   6317      */
   6318     public int getHorizontalFadingEdgeLength() {
   6319         if (isHorizontalFadingEdgeEnabled()) {
   6320             ScrollabilityCache cache = mScrollCache;
   6321             if (cache != null) {
   6322                 return cache.fadingEdgeLength;
   6323             }
   6324         }
   6325         return 0;
   6326     }
   6327 
   6328     /**
   6329      * Returns the width of the vertical scrollbar.
   6330      *
   6331      * @return The width in pixels of the vertical scrollbar or 0 if there
   6332      *         is no vertical scrollbar.
   6333      */
   6334     public int getVerticalScrollbarWidth() {
   6335         ScrollabilityCache cache = mScrollCache;
   6336         if (cache != null) {
   6337             ScrollBarDrawable scrollBar = cache.scrollBar;
   6338             if (scrollBar != null) {
   6339                 int size = scrollBar.getSize(true);
   6340                 if (size <= 0) {
   6341                     size = cache.scrollBarSize;
   6342                 }
   6343                 return size;
   6344             }
   6345             return 0;
   6346         }
   6347         return 0;
   6348     }
   6349 
   6350     /**
   6351      * Returns the height of the horizontal scrollbar.
   6352      *
   6353      * @return The height in pixels of the horizontal scrollbar or 0 if
   6354      *         there is no horizontal scrollbar.
   6355      */
   6356     protected int getHorizontalScrollbarHeight() {
   6357         ScrollabilityCache cache = mScrollCache;
   6358         if (cache != null) {
   6359             ScrollBarDrawable scrollBar = cache.scrollBar;
   6360             if (scrollBar != null) {
   6361                 int size = scrollBar.getSize(false);
   6362                 if (size <= 0) {
   6363                     size = cache.scrollBarSize;
   6364                 }
   6365                 return size;
   6366             }
   6367             return 0;
   6368         }
   6369         return 0;
   6370     }
   6371 
   6372     /**
   6373      * <p>
   6374      * Initializes the scrollbars from a given set of styled attributes. This
   6375      * method should be called by subclasses that need scrollbars and when an
   6376      * instance of these subclasses is created programmatically rather than
   6377      * being inflated from XML. This method is automatically called when the XML
   6378      * is inflated.
   6379      * </p>
   6380      *
   6381      * @param a the styled attributes set to initialize the scrollbars from
   6382      *
   6383      * @removed
   6384      */
   6385     protected void initializeScrollbars(TypedArray a) {
   6386         // It's not safe to use this method from apps. The parameter 'a' must have been obtained
   6387         // using the View filter array which is not available to the SDK. As such, internal
   6388         // framework usage now uses initializeScrollbarsInternal and we grab a default
   6389         // TypedArray with the right filter instead here.
   6390         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
   6391 
   6392         initializeScrollbarsInternal(arr);
   6393 
   6394         // We ignored the method parameter. Recycle the one we actually did use.
   6395         arr.recycle();
   6396     }
   6397 
   6398     private void initializeScrollBarDrawable() {
   6399         initScrollCache();
   6400 
   6401         if (mScrollCache.scrollBar == null) {
   6402             mScrollCache.scrollBar = new ScrollBarDrawable();
   6403             mScrollCache.scrollBar.setState(getDrawableState());
   6404             mScrollCache.scrollBar.setCallback(this);
   6405         }
   6406     }
   6407 
   6408     /**
   6409      * <p>
   6410      * Initializes the scrollbars from a given set of styled attributes. This
   6411      * method should be called by subclasses that need scrollbars and when an
   6412      * instance of these subclasses is created programmatically rather than
   6413      * being inflated from XML. This method is automatically called when the XML
   6414      * is inflated.
   6415      * </p>
   6416      *
   6417      * @param a the styled attributes set to initialize the scrollbars from
   6418      * @hide
   6419      */
   6420     @UnsupportedAppUsage
   6421     protected void initializeScrollbarsInternal(TypedArray a) {
   6422         initScrollCache();
   6423 
   6424         final ScrollabilityCache scrollabilityCache = mScrollCache;
   6425 
   6426         if (scrollabilityCache.scrollBar == null) {
   6427             scrollabilityCache.scrollBar = new ScrollBarDrawable();
   6428             scrollabilityCache.scrollBar.setState(getDrawableState());
   6429             scrollabilityCache.scrollBar.setCallback(this);
   6430         }
   6431 
   6432         final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
   6433 
   6434         if (!fadeScrollbars) {
   6435             scrollabilityCache.state = ScrollabilityCache.ON;
   6436         }
   6437         scrollabilityCache.fadeScrollBars = fadeScrollbars;
   6438 
   6439 
   6440         scrollabilityCache.scrollBarFadeDuration = a.getInt(
   6441                 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
   6442                         .getScrollBarFadeDuration());
   6443         scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
   6444                 R.styleable.View_scrollbarDefaultDelayBeforeFade,
   6445                 ViewConfiguration.getScrollDefaultDelay());
   6446 
   6447 
   6448         scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
   6449                 com.android.internal.R.styleable.View_scrollbarSize,
   6450                 ViewConfiguration.get(mContext).getScaledScrollBarSize());
   6451 
   6452         Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
   6453         scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
   6454 
   6455         Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
   6456         if (thumb != null) {
   6457             scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
   6458         }
   6459 
   6460         boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
   6461                 false);
   6462         if (alwaysDraw) {
   6463             scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
   6464         }
   6465 
   6466         track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
   6467         scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
   6468 
   6469         thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
   6470         if (thumb != null) {
   6471             scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
   6472         }
   6473 
   6474         alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
   6475                 false);
   6476         if (alwaysDraw) {
   6477             scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
   6478         }
   6479 
   6480         // Apply layout direction to the new Drawables if needed
   6481         final int layoutDirection = getLayoutDirection();
   6482         if (track != null) {
   6483             track.setLayoutDirection(layoutDirection);
   6484         }
   6485         if (thumb != null) {
   6486             thumb.setLayoutDirection(layoutDirection);
   6487         }
   6488 
   6489         // Re-apply user/background padding so that scrollbar(s) get added
   6490         resolvePadding();
   6491     }
   6492 
   6493     /**
   6494      * Defines the vertical scrollbar thumb drawable
   6495      * @attr ref android.R.styleable#View_scrollbarThumbVertical
   6496      *
   6497      * @see #awakenScrollBars(int)
   6498      * @see #isVerticalScrollBarEnabled()
   6499      * @see #setVerticalScrollBarEnabled(boolean)
   6500      */
   6501     public void setVerticalScrollbarThumbDrawable(@Nullable Drawable drawable) {
   6502         initializeScrollBarDrawable();
   6503         mScrollCache.scrollBar.setVerticalThumbDrawable(drawable);
   6504     }
   6505 
   6506     /**
   6507      * Defines the vertical scrollbar track drawable
   6508      * @attr ref android.R.styleable#View_scrollbarTrackVertical
   6509      *
   6510      * @see #awakenScrollBars(int)
   6511      * @see #isVerticalScrollBarEnabled()
   6512      * @see #setVerticalScrollBarEnabled(boolean)
   6513      */
   6514     public void setVerticalScrollbarTrackDrawable(@Nullable Drawable drawable) {
   6515         initializeScrollBarDrawable();
   6516         mScrollCache.scrollBar.setVerticalTrackDrawable(drawable);
   6517     }
   6518 
   6519     /**
   6520      * Defines the horizontal thumb drawable
   6521      * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
   6522      *
   6523      * @see #awakenScrollBars(int)
   6524      * @see #isHorizontalScrollBarEnabled()
   6525      * @see #setHorizontalScrollBarEnabled(boolean)
   6526      */
   6527     public void setHorizontalScrollbarThumbDrawable(@Nullable Drawable drawable) {
   6528         initializeScrollBarDrawable();
   6529         mScrollCache.scrollBar.setHorizontalThumbDrawable(drawable);
   6530     }
   6531 
   6532     /**
   6533      * Defines the horizontal track drawable
   6534      * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
   6535      *
   6536      * @see #awakenScrollBars(int)
   6537      * @see #isHorizontalScrollBarEnabled()
   6538      * @see #setHorizontalScrollBarEnabled(boolean)
   6539      */
   6540     public void setHorizontalScrollbarTrackDrawable(@Nullable Drawable drawable) {
   6541         initializeScrollBarDrawable();
   6542         mScrollCache.scrollBar.setHorizontalTrackDrawable(drawable);
   6543     }
   6544 
   6545     /**
   6546      * Returns the currently configured Drawable for the thumb of the vertical scroll bar if it
   6547      * exists, null otherwise.
   6548      *
   6549      * @see #awakenScrollBars(int)
   6550      * @see #isVerticalScrollBarEnabled()
   6551      * @see #setVerticalScrollBarEnabled(boolean)
   6552      */
   6553     public @Nullable Drawable getVerticalScrollbarThumbDrawable() {
   6554         return mScrollCache != null ? mScrollCache.scrollBar.getVerticalThumbDrawable() : null;
   6555     }
   6556 
   6557     /**
   6558      * Returns the currently configured Drawable for the track of the vertical scroll bar if it
   6559      * exists, null otherwise.
   6560      *
   6561      * @see #awakenScrollBars(int)
   6562      * @see #isVerticalScrollBarEnabled()
   6563      * @see #setVerticalScrollBarEnabled(boolean)
   6564      */
   6565     public @Nullable Drawable getVerticalScrollbarTrackDrawable() {
   6566         return mScrollCache != null ? mScrollCache.scrollBar.getVerticalTrackDrawable() : null;
   6567     }
   6568 
   6569     /**
   6570      * Returns the currently configured Drawable for the thumb of the horizontal scroll bar if it
   6571      * exists, null otherwise.
   6572      *
   6573      * @see #awakenScrollBars(int)
   6574      * @see #isHorizontalScrollBarEnabled()
   6575      * @see #setHorizontalScrollBarEnabled(boolean)
   6576      */
   6577     public @Nullable Drawable getHorizontalScrollbarThumbDrawable() {
   6578         return mScrollCache != null ? mScrollCache.scrollBar.getHorizontalThumbDrawable() : null;
   6579     }
   6580 
   6581     /**
   6582      * Returns the currently configured Drawable for the track of the horizontal scroll bar if it
   6583      * exists, null otherwise.
   6584      *
   6585      * @see #awakenScrollBars(int)
   6586      * @see #isHorizontalScrollBarEnabled()
   6587      * @see #setHorizontalScrollBarEnabled(boolean)
   6588      */
   6589     public @Nullable Drawable getHorizontalScrollbarTrackDrawable() {
   6590         return mScrollCache != null ? mScrollCache.scrollBar.getHorizontalTrackDrawable() : null;
   6591     }
   6592 
   6593     private void initializeScrollIndicatorsInternal() {
   6594         // Some day maybe we'll break this into top/left/start/etc. and let the
   6595         // client control it. Until then, you can have any scroll indicator you
   6596         // want as long as it's a 1dp foreground-colored rectangle.
   6597         if (mScrollIndicatorDrawable == null) {
   6598             mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
   6599         }
   6600     }
   6601 
   6602     /**
   6603      * <p>
   6604      * Initalizes the scrollability cache if necessary.
   6605      * </p>
   6606      */
   6607     private void initScrollCache() {
   6608         if (mScrollCache == null) {
   6609             mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
   6610         }
   6611     }
   6612 
   6613     @UnsupportedAppUsage
   6614     private ScrollabilityCache getScrollCache() {
   6615         initScrollCache();
   6616         return mScrollCache;
   6617     }
   6618 
   6619     /**
   6620      * Set the position of the vertical scroll bar. Should be one of
   6621      * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
   6622      * {@link #SCROLLBAR_POSITION_RIGHT}.
   6623      *
   6624      * @param position Where the vertical scroll bar should be positioned.
   6625      */
   6626     public void setVerticalScrollbarPosition(int position) {
   6627         if (mVerticalScrollbarPosition != position) {
   6628             mVerticalScrollbarPosition = position;
   6629             computeOpaqueFlags();
   6630             resolvePadding();
   6631         }
   6632     }
   6633 
   6634     /**
   6635      * @return The position where the vertical scroll bar will show, if applicable.
   6636      * @see #setVerticalScrollbarPosition(int)
   6637      */
   6638     public int getVerticalScrollbarPosition() {
   6639         return mVerticalScrollbarPosition;
   6640     }
   6641 
   6642     boolean isOnScrollbar(float x, float y) {
   6643         if (mScrollCache == null) {
   6644             return false;
   6645         }
   6646         x += getScrollX();
   6647         y += getScrollY();
   6648         final boolean canScrollVertically =
   6649                 computeVerticalScrollRange() > computeVerticalScrollExtent();
   6650         if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden() && canScrollVertically) {
   6651             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
   6652             getVerticalScrollBarBounds(null, touchBounds);
   6653             if (touchBounds.contains((int) x, (int) y)) {
   6654                 return true;
   6655             }
   6656         }
   6657         final boolean canScrollHorizontally =
   6658                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
   6659         if (isHorizontalScrollBarEnabled() && canScrollHorizontally) {
   6660             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
   6661             getHorizontalScrollBarBounds(null, touchBounds);
   6662             if (touchBounds.contains((int) x, (int) y)) {
   6663                 return true;
   6664             }
   6665         }
   6666         return false;
   6667     }
   6668 
   6669     @UnsupportedAppUsage
   6670     boolean isOnScrollbarThumb(float x, float y) {
   6671         return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
   6672     }
   6673 
   6674     private boolean isOnVerticalScrollbarThumb(float x, float y) {
   6675         if (mScrollCache == null || !isVerticalScrollBarEnabled() || isVerticalScrollBarHidden()) {
   6676             return false;
   6677         }
   6678         final int range = computeVerticalScrollRange();
   6679         final int extent = computeVerticalScrollExtent();
   6680         if (range > extent) {
   6681             x += getScrollX();
   6682             y += getScrollY();
   6683             final Rect bounds = mScrollCache.mScrollBarBounds;
   6684             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
   6685             getVerticalScrollBarBounds(bounds, touchBounds);
   6686             final int offset = computeVerticalScrollOffset();
   6687             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
   6688                     extent, range);
   6689             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
   6690                     extent, range, offset);
   6691             final int thumbTop = bounds.top + thumbOffset;
   6692             final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
   6693             if (x >= touchBounds.left && x <= touchBounds.right
   6694                     && y >= thumbTop - adjust && y <= thumbTop + thumbLength + adjust) {
   6695                 return true;
   6696             }
   6697         }
   6698         return false;
   6699     }
   6700 
   6701     private boolean isOnHorizontalScrollbarThumb(float x, float y) {
   6702         if (mScrollCache == null || !isHorizontalScrollBarEnabled()) {
   6703             return false;
   6704         }
   6705         final int range = computeHorizontalScrollRange();
   6706         final int extent = computeHorizontalScrollExtent();
   6707         if (range > extent) {
   6708             x += getScrollX();
   6709             y += getScrollY();
   6710             final Rect bounds = mScrollCache.mScrollBarBounds;
   6711             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
   6712             getHorizontalScrollBarBounds(bounds, touchBounds);
   6713             final int offset = computeHorizontalScrollOffset();
   6714 
   6715             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
   6716                     extent, range);
   6717             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
   6718                     extent, range, offset);
   6719             final int thumbLeft = bounds.left + thumbOffset;
   6720             final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
   6721             if (x >= thumbLeft - adjust && x <= thumbLeft + thumbLength + adjust
   6722                     && y >= touchBounds.top && y <= touchBounds.bottom) {
   6723                 return true;
   6724             }
   6725         }
   6726         return false;
   6727     }
   6728 
   6729     @UnsupportedAppUsage
   6730     boolean isDraggingScrollBar() {
   6731         return mScrollCache != null
   6732                 && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
   6733     }
   6734 
   6735     /**
   6736      * Sets the state of all scroll indicators.
   6737      * <p>
   6738      * See {@link #setScrollIndicators(int, int)} for usage information.
   6739      *
   6740      * @param indicators a bitmask of indicators that should be enabled, or
   6741      *                   {@code 0} to disable all indicators
   6742      * @see #setScrollIndicators(int, int)
   6743      * @see #getScrollIndicators()
   6744      * @attr ref android.R.styleable#View_scrollIndicators
   6745      */
   6746     public void setScrollIndicators(@ScrollIndicators int indicators) {
   6747         setScrollIndicators(indicators,
   6748                 SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
   6749     }
   6750 
   6751     /**
   6752      * Sets the state of the scroll indicators specified by the mask. To change
   6753      * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
   6754      * <p>
   6755      * When a scroll indicator is enabled, it will be displayed if the view
   6756      * can scroll in the direction of the indicator.
   6757      * <p>
   6758      * Multiple indicator types may be enabled or disabled by passing the
   6759      * logical OR of the desired types. If multiple types are specified, they
   6760      * will all be set to the same enabled state.
   6761      * <p>
   6762      * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
   6763      *
   6764      * @param indicators the indicator direction, or the logical OR of multiple
   6765      *             indicator directions. One or more of:
   6766      *             <ul>
   6767      *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
   6768      *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
   6769      *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
   6770      *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
   6771      *               <li>{@link #SCROLL_INDICATOR_START}</li>
   6772      *               <li>{@link #SCROLL_INDICATOR_END}</li>
   6773      *             </ul>
   6774      * @see #setScrollIndicators(int)
   6775      * @see #getScrollIndicators()
   6776      * @attr ref android.R.styleable#View_scrollIndicators
   6777      */
   6778     public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
   6779         // Shift and sanitize mask.
   6780         mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   6781         mask &= SCROLL_INDICATORS_PFLAG3_MASK;
   6782 
   6783         // Shift and mask indicators.
   6784         indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   6785         indicators &= mask;
   6786 
   6787         // Merge with non-masked flags.
   6788         final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
   6789 
   6790         if (mPrivateFlags3 != updatedFlags) {
   6791             mPrivateFlags3 = updatedFlags;
   6792 
   6793             if (indicators != 0) {
   6794                 initializeScrollIndicatorsInternal();
   6795             }
   6796             invalidate();
   6797         }
   6798     }
   6799 
   6800     /**
   6801      * Returns a bitmask representing the enabled scroll indicators.
   6802      * <p>
   6803      * For example, if the top and left scroll indicators are enabled and all
   6804      * other indicators are disabled, the return value will be
   6805      * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
   6806      * <p>
   6807      * To check whether the bottom scroll indicator is enabled, use the value
   6808      * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
   6809      *
   6810      * @return a bitmask representing the enabled scroll indicators
   6811      */
   6812     @InspectableProperty(flagMapping = {
   6813             @FlagEntry(target = SCROLL_INDICATORS_NONE, mask = 0xffff_ffff, name = "none"),
   6814             @FlagEntry(target = SCROLL_INDICATOR_TOP, name = "top"),
   6815             @FlagEntry(target = SCROLL_INDICATOR_BOTTOM, name = "bottom"),
   6816             @FlagEntry(target = SCROLL_INDICATOR_LEFT, name = "left"),
   6817             @FlagEntry(target = SCROLL_INDICATOR_RIGHT, name = "right"),
   6818             @FlagEntry(target = SCROLL_INDICATOR_START, name = "start"),
   6819             @FlagEntry(target = SCROLL_INDICATOR_END, name = "end")
   6820     })
   6821     @ScrollIndicators
   6822     public int getScrollIndicators() {
   6823         return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
   6824                 >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   6825     }
   6826 
   6827     @UnsupportedAppUsage
   6828     ListenerInfo getListenerInfo() {
   6829         if (mListenerInfo != null) {
   6830             return mListenerInfo;
   6831         }
   6832         mListenerInfo = new ListenerInfo();
   6833         return mListenerInfo;
   6834     }
   6835 
   6836     /**
   6837      * Register a callback to be invoked when the scroll X or Y positions of
   6838      * this view change.
   6839      * <p>
   6840      * <b>Note:</b> Some views handle scrolling independently from View and may
   6841      * have their own separate listeners for scroll-type events. For example,
   6842      * {@link android.widget.ListView ListView} allows clients to register an
   6843      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
   6844      * to listen for changes in list scroll position.
   6845      *
   6846      * @param l The listener to notify when the scroll X or Y position changes.
   6847      * @see android.view.View#getScrollX()
   6848      * @see android.view.View#getScrollY()
   6849      */
   6850     public void setOnScrollChangeListener(OnScrollChangeListener l) {
   6851         getListenerInfo().mOnScrollChangeListener = l;
   6852     }
   6853 
   6854     /**
   6855      * Register a callback to be invoked when focus of this view changed.
   6856      *
   6857      * @param l The callback that will run.
   6858      */
   6859     public void setOnFocusChangeListener(OnFocusChangeListener l) {
   6860         getListenerInfo().mOnFocusChangeListener = l;
   6861     }
   6862 
   6863     /**
   6864      * Add a listener that will be called when the bounds of the view change due to
   6865      * layout processing.
   6866      *
   6867      * @param listener The listener that will be called when layout bounds change.
   6868      */
   6869     public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
   6870         ListenerInfo li = getListenerInfo();
   6871         if (li.mOnLayoutChangeListeners == null) {
   6872             li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
   6873         }
   6874         if (!li.mOnLayoutChangeListeners.contains(listener)) {
   6875             li.mOnLayoutChangeListeners.add(listener);
   6876         }
   6877     }
   6878 
   6879     /**
   6880      * Remove a listener for layout changes.
   6881      *
   6882      * @param listener The listener for layout bounds change.
   6883      */
   6884     public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
   6885         ListenerInfo li = mListenerInfo;
   6886         if (li == null || li.mOnLayoutChangeListeners == null) {
   6887             return;
   6888         }
   6889         li.mOnLayoutChangeListeners.remove(listener);
   6890     }
   6891 
   6892     /**
   6893      * Add a listener for attach state changes.
   6894      *
   6895      * This listener will be called whenever this view is attached or detached
   6896      * from a window. Remove the listener using
   6897      * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
   6898      *
   6899      * @param listener Listener to attach
   6900      * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
   6901      */
   6902     public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
   6903         ListenerInfo li = getListenerInfo();
   6904         if (li.mOnAttachStateChangeListeners == null) {
   6905             li.mOnAttachStateChangeListeners
   6906                     = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
   6907         }
   6908         li.mOnAttachStateChangeListeners.add(listener);
   6909     }
   6910 
   6911     /**
   6912      * Remove a listener for attach state changes. The listener will receive no further
   6913      * notification of window attach/detach events.
   6914      *
   6915      * @param listener Listener to remove
   6916      * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
   6917      */
   6918     public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
   6919         ListenerInfo li = mListenerInfo;
   6920         if (li == null || li.mOnAttachStateChangeListeners == null) {
   6921             return;
   6922         }
   6923         li.mOnAttachStateChangeListeners.remove(listener);
   6924     }
   6925 
   6926     /**
   6927      * Returns the focus-change callback registered for this view.
   6928      *
   6929      * @return The callback, or null if one is not registered.
   6930      */
   6931     public OnFocusChangeListener getOnFocusChangeListener() {
   6932         ListenerInfo li = mListenerInfo;
   6933         return li != null ? li.mOnFocusChangeListener : null;
   6934     }
   6935 
   6936     /**
   6937      * Register a callback to be invoked when this view is clicked. If this view is not
   6938      * clickable, it becomes clickable.
   6939      *
   6940      * @param l The callback that will run
   6941      *
   6942      * @see #setClickable(boolean)
   6943      */
   6944     public void setOnClickListener(@Nullable OnClickListener l) {
   6945         if (!isClickable()) {
   6946             setClickable(true);
   6947         }
   6948         getListenerInfo().mOnClickListener = l;
   6949     }
   6950 
   6951     /**
   6952      * Return whether this view has an attached OnClickListener.  Returns
   6953      * true if there is a listener, false if there is none.
   6954      */
   6955     public boolean hasOnClickListeners() {
   6956         ListenerInfo li = mListenerInfo;
   6957         return (li != null && li.mOnClickListener != null);
   6958     }
   6959 
   6960     /**
   6961      * Register a callback to be invoked when this view is clicked and held. If this view is not
   6962      * long clickable, it becomes long clickable.
   6963      *
   6964      * @param l The callback that will run
   6965      *
   6966      * @see #setLongClickable(boolean)
   6967      */
   6968     public void setOnLongClickListener(@Nullable OnLongClickListener l) {
   6969         if (!isLongClickable()) {
   6970             setLongClickable(true);
   6971         }
   6972         getListenerInfo().mOnLongClickListener = l;
   6973     }
   6974 
   6975     /**
   6976      * Register a callback to be invoked when this view is context clicked. If the view is not
   6977      * context clickable, it becomes context clickable.
   6978      *
   6979      * @param l The callback that will run
   6980      * @see #setContextClickable(boolean)
   6981      */
   6982     public void setOnContextClickListener(@Nullable OnContextClickListener l) {
   6983         if (!isContextClickable()) {
   6984             setContextClickable(true);
   6985         }
   6986         getListenerInfo().mOnContextClickListener = l;
   6987     }
   6988 
   6989     /**
   6990      * Register a callback to be invoked when the context menu for this view is
   6991      * being built. If this view is not long clickable, it becomes long clickable.
   6992      *
   6993      * @param l The callback that will run
   6994      *
   6995      */
   6996     public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
   6997         if (!isLongClickable()) {
   6998             setLongClickable(true);
   6999         }
   7000         getListenerInfo().mOnCreateContextMenuListener = l;
   7001     }
   7002 
   7003     /**
   7004      * Set an observer to collect stats for each frame rendered for this view.
   7005      *
   7006      * @hide
   7007      */
   7008     public void addFrameMetricsListener(Window window,
   7009             Window.OnFrameMetricsAvailableListener listener,
   7010             Handler handler) {
   7011         if (mAttachInfo != null) {
   7012             if (mAttachInfo.mThreadedRenderer != null) {
   7013                 if (mFrameMetricsObservers == null) {
   7014                     mFrameMetricsObservers = new ArrayList<>();
   7015                 }
   7016 
   7017                 FrameMetricsObserver fmo = new FrameMetricsObserver(window,
   7018                         handler.getLooper(), listener);
   7019                 mFrameMetricsObservers.add(fmo);
   7020                 mAttachInfo.mThreadedRenderer.addFrameMetricsObserver(fmo);
   7021             } else {
   7022                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
   7023             }
   7024         } else {
   7025             if (mFrameMetricsObservers == null) {
   7026                 mFrameMetricsObservers = new ArrayList<>();
   7027             }
   7028 
   7029             FrameMetricsObserver fmo = new FrameMetricsObserver(window,
   7030                     handler.getLooper(), listener);
   7031             mFrameMetricsObservers.add(fmo);
   7032         }
   7033     }
   7034 
   7035     /**
   7036      * Remove observer configured to collect frame stats for this view.
   7037      *
   7038      * @hide
   7039      */
   7040     public void removeFrameMetricsListener(
   7041             Window.OnFrameMetricsAvailableListener listener) {
   7042         ThreadedRenderer renderer = getThreadedRenderer();
   7043         FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
   7044         if (fmo == null) {
   7045             throw new IllegalArgumentException(
   7046                     "attempt to remove OnFrameMetricsAvailableListener that was never added");
   7047         }
   7048 
   7049         if (mFrameMetricsObservers != null) {
   7050             mFrameMetricsObservers.remove(fmo);
   7051             if (renderer != null) {
   7052                 renderer.removeFrameMetricsObserver(fmo);
   7053             }
   7054         }
   7055     }
   7056 
   7057     private void registerPendingFrameMetricsObservers() {
   7058         if (mFrameMetricsObservers != null) {
   7059             ThreadedRenderer renderer = getThreadedRenderer();
   7060             if (renderer != null) {
   7061                 for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
   7062                     renderer.addFrameMetricsObserver(fmo);
   7063                 }
   7064             } else {
   7065                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
   7066             }
   7067         }
   7068     }
   7069 
   7070     private FrameMetricsObserver findFrameMetricsObserver(
   7071             Window.OnFrameMetricsAvailableListener listener) {
   7072         if (mFrameMetricsObservers != null) {
   7073             for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
   7074                 FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
   7075                 if (observer.mListener == listener) {
   7076                     return observer;
   7077                 }
   7078             }
   7079         }
   7080 
   7081         return null;
   7082     }
   7083 
   7084     /** @hide */
   7085     public void setNotifyAutofillManagerOnClick(boolean notify) {
   7086         if (notify) {
   7087             mPrivateFlags |= PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
   7088         } else {
   7089             mPrivateFlags &= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
   7090         }
   7091     }
   7092 
   7093     private void notifyAutofillManagerOnClick() {
   7094         if ((mPrivateFlags & PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK) != 0) {
   7095             try {
   7096                 getAutofillManager().notifyViewClicked(this);
   7097             } finally {
   7098                 // Set it to already called so it's not called twice when called by
   7099                 // performClickInternal()
   7100                 mPrivateFlags &= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
   7101             }
   7102         }
   7103     }
   7104 
   7105     /**
   7106      * Entry point for {@link #performClick()} - other methods on View should call it instead of
   7107      * {@code performClick()} directly to make sure the autofill manager is notified when
   7108      * necessary (as subclasses could extend {@code performClick()} without calling the parent's
   7109      * method).
   7110      */
   7111     private boolean performClickInternal() {
   7112         // Must notify autofill manager before performing the click actions to avoid scenarios where
   7113         // the app has a click listener that changes the state of views the autofill service might
   7114         // be interested on.
   7115         notifyAutofillManagerOnClick();
   7116 
   7117         return performClick();
   7118     }
   7119 
   7120     /**
   7121      * Call this view's OnClickListener, if it is defined.  Performs all normal
   7122      * actions associated with clicking: reporting accessibility event, playing
   7123      * a sound, etc.
   7124      *
   7125      * @return True there was an assigned OnClickListener that was called, false
   7126      *         otherwise is returned.
   7127      */
   7128     // NOTE: other methods on View should not call this method directly, but performClickInternal()
   7129     // instead, to guarantee that the autofill manager is notified when necessary (as subclasses
   7130     // could extend this method without calling super.performClick()).
   7131     public boolean performClick() {
   7132         // We still need to call this method to handle the cases where performClick() was called
   7133         // externally, instead of through performClickInternal()
   7134         notifyAutofillManagerOnClick();
   7135 
   7136         final boolean result;
   7137         final ListenerInfo li = mListenerInfo;
   7138         if (li != null && li.mOnClickListener != null) {
   7139             playSoundEffect(SoundEffectConstants.CLICK);
   7140             li.mOnClickListener.onClick(this);
   7141             result = true;
   7142         } else {
   7143             result = false;
   7144         }
   7145 
   7146         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
   7147 
   7148         notifyEnterOrExitForAutoFillIfNeeded(true);
   7149 
   7150         return result;
   7151     }
   7152 
   7153     /**
   7154      * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
   7155      * this only calls the listener, and does not do any associated clicking
   7156      * actions like reporting an accessibility event.
   7157      *
   7158      * @return True there was an assigned OnClickListener that was called, false
   7159      *         otherwise is returned.
   7160      */
   7161     public boolean callOnClick() {
   7162         ListenerInfo li = mListenerInfo;
   7163         if (li != null && li.mOnClickListener != null) {
   7164             li.mOnClickListener.onClick(this);
   7165             return true;
   7166         }
   7167         return false;
   7168     }
   7169 
   7170     /**
   7171      * Calls this view's OnLongClickListener, if it is defined. Invokes the
   7172      * context menu if the OnLongClickListener did not consume the event.
   7173      *
   7174      * @return {@code true} if one of the above receivers consumed the event,
   7175      *         {@code false} otherwise
   7176      */
   7177     public boolean performLongClick() {
   7178         return performLongClickInternal(mLongClickX, mLongClickY);
   7179     }
   7180 
   7181     /**
   7182      * Calls this view's OnLongClickListener, if it is defined. Invokes the
   7183      * context menu if the OnLongClickListener did not consume the event,
   7184      * anchoring it to an (x,y) coordinate.
   7185      *
   7186      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
   7187      *          to disable anchoring
   7188      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
   7189      *          to disable anchoring
   7190      * @return {@code true} if one of the above receivers consumed the event,
   7191      *         {@code false} otherwise
   7192      */
   7193     public boolean performLongClick(float x, float y) {
   7194         mLongClickX = x;
   7195         mLongClickY = y;
   7196         final boolean handled = performLongClick();
   7197         mLongClickX = Float.NaN;
   7198         mLongClickY = Float.NaN;
   7199         return handled;
   7200     }
   7201 
   7202     /**
   7203      * Calls this view's OnLongClickListener, if it is defined. Invokes the
   7204      * context menu if the OnLongClickListener did not consume the event,
   7205      * optionally anchoring it to an (x,y) coordinate.
   7206      *
   7207      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
   7208      *          to disable anchoring
   7209      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
   7210      *          to disable anchoring
   7211      * @return {@code true} if one of the above receivers consumed the event,
   7212      *         {@code false} otherwise
   7213      */
   7214     private boolean performLongClickInternal(float x, float y) {
   7215         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
   7216 
   7217         boolean handled = false;
   7218         final ListenerInfo li = mListenerInfo;
   7219         if (li != null && li.mOnLongClickListener != null) {
   7220             handled = li.mOnLongClickListener.onLongClick(View.this);
   7221         }
   7222         if (!handled) {
   7223             final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
   7224             handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
   7225         }
   7226         if ((mViewFlags & TOOLTIP) == TOOLTIP) {
   7227             if (!handled) {
   7228                 handled = showLongClickTooltip((int) x, (int) y);
   7229             }
   7230         }
   7231         if (handled) {
   7232             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
   7233         }
   7234         return handled;
   7235     }
   7236 
   7237     /**
   7238      * Call this view's OnContextClickListener, if it is defined.
   7239      *
   7240      * @param x the x coordinate of the context click
   7241      * @param y the y coordinate of the context click
   7242      * @return True if there was an assigned OnContextClickListener that consumed the event, false
   7243      *         otherwise.
   7244      */
   7245     public boolean performContextClick(float x, float y) {
   7246         return performContextClick();
   7247     }
   7248 
   7249     /**
   7250      * Call this view's OnContextClickListener, if it is defined.
   7251      *
   7252      * @return True if there was an assigned OnContextClickListener that consumed the event, false
   7253      *         otherwise.
   7254      */
   7255     public boolean performContextClick() {
   7256         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
   7257 
   7258         boolean handled = false;
   7259         ListenerInfo li = mListenerInfo;
   7260         if (li != null && li.mOnContextClickListener != null) {
   7261             handled = li.mOnContextClickListener.onContextClick(View.this);
   7262         }
   7263         if (handled) {
   7264             performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
   7265         }
   7266         return handled;
   7267     }
   7268 
   7269     /**
   7270      * Performs button-related actions during a touch down event.
   7271      *
   7272      * @param event The event.
   7273      * @return True if the down was consumed.
   7274      *
   7275      * @hide
   7276      */
   7277     protected boolean performButtonActionOnTouchDown(MotionEvent event) {
   7278         if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
   7279             (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
   7280             showContextMenu(event.getX(), event.getY());
   7281             mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
   7282             return true;
   7283         }
   7284         return false;
   7285     }
   7286 
   7287     /**
   7288      * Shows the context menu for this view.
   7289      *
   7290      * @return {@code true} if the context menu was shown, {@code false}
   7291      *         otherwise
   7292      * @see #showContextMenu(float, float)
   7293      */
   7294     public boolean showContextMenu() {
   7295         return getParent().showContextMenuForChild(this);
   7296     }
   7297 
   7298     /**
   7299      * Shows the context menu for this view anchored to the specified
   7300      * view-relative coordinate.
   7301      *
   7302      * @param x the X coordinate in pixels relative to the view to which the
   7303      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
   7304      * @param y the Y coordinate in pixels relative to the view to which the
   7305      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
   7306      * @return {@code true} if the context menu was shown, {@code false}
   7307      *         otherwise
   7308      */
   7309     public boolean showContextMenu(float x, float y) {
   7310         return getParent().showContextMenuForChild(this, x, y);
   7311     }
   7312 
   7313     /**
   7314      * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
   7315      *
   7316      * @param callback Callback that will control the lifecycle of the action mode
   7317      * @return The new action mode if it is started, null otherwise
   7318      *
   7319      * @see ActionMode
   7320      * @see #startActionMode(android.view.ActionMode.Callback, int)
   7321      */
   7322     public ActionMode startActionMode(ActionMode.Callback callback) {
   7323         return startActionMode(callback, ActionMode.TYPE_PRIMARY);
   7324     }
   7325 
   7326     /**
   7327      * Start an action mode with the given type.
   7328      *
   7329      * @param callback Callback that will control the lifecycle of the action mode
   7330      * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
   7331      * @return The new action mode if it is started, null otherwise
   7332      *
   7333      * @see ActionMode
   7334      */
   7335     public ActionMode startActionMode(ActionMode.Callback callback, int type) {
   7336         ViewParent parent = getParent();
   7337         if (parent == null) return null;
   7338         try {
   7339             return parent.startActionModeForChild(this, callback, type);
   7340         } catch (AbstractMethodError ame) {
   7341             // Older implementations of custom views might not implement this.
   7342             return parent.startActionModeForChild(this, callback);
   7343         }
   7344     }
   7345 
   7346     /**
   7347      * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
   7348      * Context, creating a unique View identifier to retrieve the result.
   7349      *
   7350      * @param intent The Intent to be started.
   7351      * @param requestCode The request code to use.
   7352      * @hide
   7353      */
   7354     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
   7355     public void startActivityForResult(Intent intent, int requestCode) {
   7356         mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
   7357         getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
   7358     }
   7359 
   7360     /**
   7361      * If this View corresponds to the calling who, dispatches the activity result.
   7362      * @param who The identifier for the targeted View to receive the result.
   7363      * @param requestCode The integer request code originally supplied to
   7364      *                    startActivityForResult(), allowing you to identify who this
   7365      *                    result came from.
   7366      * @param resultCode The integer result code returned by the child activity
   7367      *                   through its setResult().
   7368      * @param data An Intent, which can return result data to the caller
   7369      *               (various data can be attached to Intent "extras").
   7370      * @return {@code true} if the activity result was dispatched.
   7371      * @hide
   7372      */
   7373     public boolean dispatchActivityResult(
   7374             String who, int requestCode, int resultCode, Intent data) {
   7375         if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
   7376             onActivityResult(requestCode, resultCode, data);
   7377             mStartActivityRequestWho = null;
   7378             return true;
   7379         }
   7380         return false;
   7381     }
   7382 
   7383     /**
   7384      * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
   7385      *
   7386      * @param requestCode The integer request code originally supplied to
   7387      *                    startActivityForResult(), allowing you to identify who this
   7388      *                    result came from.
   7389      * @param resultCode The integer result code returned by the child activity
   7390      *                   through its setResult().
   7391      * @param data An Intent, which can return result data to the caller
   7392      *               (various data can be attached to Intent "extras").
   7393      * @hide
   7394      */
   7395     public void onActivityResult(int requestCode, int resultCode, Intent data) {
   7396         // Do nothing.
   7397     }
   7398 
   7399     /**
   7400      * Register a callback to be invoked when a hardware key is pressed in this view.
   7401      * Key presses in software input methods will generally not trigger the methods of
   7402      * this listener.
   7403      * @param l the key listener to attach to this view
   7404      */
   7405     public void setOnKeyListener(OnKeyListener l) {
   7406         getListenerInfo().mOnKeyListener = l;
   7407     }
   7408 
   7409     /**
   7410      * Register a callback to be invoked when a touch event is sent to this view.
   7411      * @param l the touch listener to attach to this view
   7412      */
   7413     public void setOnTouchListener(OnTouchListener l) {
   7414         getListenerInfo().mOnTouchListener = l;
   7415     }
   7416 
   7417     /**
   7418      * Register a callback to be invoked when a generic motion event is sent to this view.
   7419      * @param l the generic motion listener to attach to this view
   7420      */
   7421     public void setOnGenericMotionListener(OnGenericMotionListener l) {
   7422         getListenerInfo().mOnGenericMotionListener = l;
   7423     }
   7424 
   7425     /**
   7426      * Register a callback to be invoked when a hover event is sent to this view.
   7427      * @param l the hover listener to attach to this view
   7428      */
   7429     public void setOnHoverListener(OnHoverListener l) {
   7430         getListenerInfo().mOnHoverListener = l;
   7431     }
   7432 
   7433     /**
   7434      * Register a drag event listener callback object for this View. The parameter is
   7435      * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
   7436      * View, the system calls the
   7437      * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
   7438      * @param l An implementation of {@link android.view.View.OnDragListener}.
   7439      */
   7440     public void setOnDragListener(OnDragListener l) {
   7441         getListenerInfo().mOnDragListener = l;
   7442     }
   7443 
   7444     /**
   7445      * Give this view focus. This will cause
   7446      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
   7447      *
   7448      * Note: this does not check whether this {@link View} should get focus, it just
   7449      * gives it focus no matter what.  It should only be called internally by framework
   7450      * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
   7451      *
   7452      * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
   7453      *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
   7454      *        focus moved when requestFocus() is called. It may not always
   7455      *        apply, in which case use the default View.FOCUS_DOWN.
   7456      * @param previouslyFocusedRect The rectangle of the view that had focus
   7457      *        prior in this View's coordinate system.
   7458      */
   7459     void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
   7460         if (DBG) {
   7461             System.out.println(this + " requestFocus()");
   7462         }
   7463 
   7464         if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
   7465             mPrivateFlags |= PFLAG_FOCUSED;
   7466 
   7467             View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
   7468 
   7469             if (mParent != null) {
   7470                 mParent.requestChildFocus(this, this);
   7471                 updateFocusedInCluster(oldFocus, direction);
   7472             }
   7473 
   7474             if (mAttachInfo != null) {
   7475                 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
   7476             }
   7477 
   7478             onFocusChanged(true, direction, previouslyFocusedRect);
   7479             refreshDrawableState();
   7480         }
   7481     }
   7482 
   7483     /**
   7484      * Sets this view's preference for reveal behavior when it gains focus.
   7485      *
   7486      * <p>When set to true, this is a signal to ancestor views in the hierarchy that
   7487      * this view would prefer to be brought fully into view when it gains focus.
   7488      * For example, a text field that a user is meant to type into. Other views such
   7489      * as scrolling containers may prefer to opt-out of this behavior.</p>
   7490      *
   7491      * <p>The default value for views is true, though subclasses may change this
   7492      * based on their preferred behavior.</p>
   7493      *
   7494      * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
   7495      *
   7496      * @see #getRevealOnFocusHint()
   7497      */
   7498     public final void setRevealOnFocusHint(boolean revealOnFocus) {
   7499         if (revealOnFocus) {
   7500             mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
   7501         } else {
   7502             mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
   7503         }
   7504     }
   7505 
   7506     /**
   7507      * Returns this view's preference for reveal behavior when it gains focus.
   7508      *
   7509      * <p>When this method returns true for a child view requesting focus, ancestor
   7510      * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
   7511      * should make a best effort to make the newly focused child fully visible to the user.
   7512      * When it returns false, ancestor views should preferably not disrupt scroll positioning or
   7513      * other properties affecting visibility to the user as part of the focus change.</p>
   7514      *
   7515      * @return true if this view would prefer to become fully visible when it gains focus,
   7516      *         false if it would prefer not to disrupt scroll positioning
   7517      *
   7518      * @see #setRevealOnFocusHint(boolean)
   7519      */
   7520     public final boolean getRevealOnFocusHint() {
   7521         return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
   7522     }
   7523 
   7524     /**
   7525      * Populates <code>outRect</code> with the hotspot bounds. By default,
   7526      * the hotspot bounds are identical to the screen bounds.
   7527      *
   7528      * @param outRect rect to populate with hotspot bounds
   7529      * @hide Only for internal use by views and widgets.
   7530      */
   7531     public void getHotspotBounds(Rect outRect) {
   7532         final Drawable background = getBackground();
   7533         if (background != null) {
   7534             background.getHotspotBounds(outRect);
   7535         } else {
   7536             getBoundsOnScreen(outRect);
   7537         }
   7538     }
   7539 
   7540     /**
   7541      * Request that a rectangle of this view be visible on the screen,
   7542      * scrolling if necessary just enough.
   7543      *
   7544      * <p>A View should call this if it maintains some notion of which part
   7545      * of its content is interesting.  For example, a text editing view
   7546      * should call this when its cursor moves.
   7547      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
   7548      * It should not be affected by which part of the View is currently visible or its scroll
   7549      * position.
   7550      *
   7551      * @param rectangle The rectangle in the View's content coordinate space
   7552      * @return Whether any parent scrolled.
   7553      */
   7554     public boolean requestRectangleOnScreen(Rect rectangle) {
   7555         return requestRectangleOnScreen(rectangle, false);
   7556     }
   7557 
   7558     /**
   7559      * Request that a rectangle of this view be visible on the screen,
   7560      * scrolling if necessary just enough.
   7561      *
   7562      * <p>A View should call this if it maintains some notion of which part
   7563      * of its content is interesting.  For example, a text editing view
   7564      * should call this when its cursor moves.
   7565      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
   7566      * It should not be affected by which part of the View is currently visible or its scroll
   7567      * position.
   7568      * <p>When <code>immediate</code> is set to true, scrolling will not be
   7569      * animated.
   7570      *
   7571      * @param rectangle The rectangle in the View's content coordinate space
   7572      * @param immediate True to forbid animated scrolling, false otherwise
   7573      * @return Whether any parent scrolled.
   7574      */
   7575     public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
   7576         if (mParent == null) {
   7577             return false;
   7578         }
   7579 
   7580         View child = this;
   7581 
   7582         RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
   7583         position.set(rectangle);
   7584 
   7585         ViewParent parent = mParent;
   7586         boolean scrolled = false;
   7587         while (parent != null) {
   7588             rectangle.set((int) position.left, (int) position.top,
   7589                     (int) position.right, (int) position.bottom);
   7590 
   7591             scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
   7592 
   7593             if (!(parent instanceof View)) {
   7594                 break;
   7595             }
   7596 
   7597             // move it from child's content coordinate space to parent's content coordinate space
   7598             position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
   7599 
   7600             child = (View) parent;
   7601             parent = child.getParent();
   7602         }
   7603 
   7604         return scrolled;
   7605     }
   7606 
   7607     /**
   7608      * Called when this view wants to give up focus. If focus is cleared
   7609      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
   7610      * <p>
   7611      * <strong>Note:</strong> When not in touch-mode, the framework will try to give focus
   7612      * to the first focusable View from the top after focus is cleared. Hence, if this
   7613      * View is the first from the top that can take focus, then all callbacks
   7614      * related to clearing focus will be invoked after which the framework will
   7615      * give focus to this view.
   7616      * </p>
   7617      */
   7618     public void clearFocus() {
   7619         if (DBG) {
   7620             System.out.println(this + " clearFocus()");
   7621         }
   7622 
   7623         final boolean refocus = sAlwaysAssignFocus || !isInTouchMode();
   7624         clearFocusInternal(null, true, refocus);
   7625     }
   7626 
   7627     /**
   7628      * Clears focus from the view, optionally propagating the change up through
   7629      * the parent hierarchy and requesting that the root view place new focus.
   7630      *
   7631      * @param propagate whether to propagate the change up through the parent
   7632      *            hierarchy
   7633      * @param refocus when propagate is true, specifies whether to request the
   7634      *            root view place new focus
   7635      */
   7636     void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
   7637         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
   7638             mPrivateFlags &= ~PFLAG_FOCUSED;
   7639             clearParentsWantFocus();
   7640 
   7641             if (propagate && mParent != null) {
   7642                 mParent.clearChildFocus(this);
   7643             }
   7644 
   7645             onFocusChanged(false, 0, null);
   7646             refreshDrawableState();
   7647 
   7648             if (propagate && (!refocus || !rootViewRequestFocus())) {
   7649                 notifyGlobalFocusCleared(this);
   7650             }
   7651         }
   7652     }
   7653 
   7654     void notifyGlobalFocusCleared(View oldFocus) {
   7655         if (oldFocus != null && mAttachInfo != null) {
   7656             mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
   7657         }
   7658     }
   7659 
   7660     boolean rootViewRequestFocus() {
   7661         final View root = getRootView();
   7662         return root != null && root.requestFocus();
   7663     }
   7664 
   7665     /**
   7666      * Called internally by the view system when a new view is getting focus.
   7667      * This is what clears the old focus.
   7668      * <p>
   7669      * <b>NOTE:</b> The parent view's focused child must be updated manually
   7670      * after calling this method. Otherwise, the view hierarchy may be left in
   7671      * an inconstent state.
   7672      */
   7673     void unFocus(View focused) {
   7674         if (DBG) {
   7675             System.out.println(this + " unFocus()");
   7676         }
   7677 
   7678         clearFocusInternal(focused, false, false);
   7679     }
   7680 
   7681     /**
   7682      * Returns true if this view has focus itself, or is the ancestor of the
   7683      * view that has focus.
   7684      *
   7685      * @return True if this view has or contains focus, false otherwise.
   7686      */
   7687     @ViewDebug.ExportedProperty(category = "focus")
   7688     public boolean hasFocus() {
   7689         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
   7690     }
   7691 
   7692     /**
   7693      * Returns true if this view is focusable or if it contains a reachable View
   7694      * for which {@link #hasFocusable()} returns {@code true}. A "reachable hasFocusable()"
   7695      * is a view whose parents do not block descendants focus.
   7696      * Only {@link #VISIBLE} views are considered focusable.
   7697      *
   7698      * <p>As of {@link Build.VERSION_CODES#O} views that are determined to be focusable
   7699      * through {@link #FOCUSABLE_AUTO} will also cause this method to return {@code true}.
   7700      * Apps that declare a {@link android.content.pm.ApplicationInfo#targetSdkVersion} of
   7701      * earlier than {@link Build.VERSION_CODES#O} will continue to see this method return
   7702      * {@code false} for views not explicitly marked as focusable.
   7703      * Use {@link #hasExplicitFocusable()} if you require the pre-{@link Build.VERSION_CODES#O}
   7704      * behavior.</p>
   7705      *
   7706      * @return {@code true} if the view is focusable or if the view contains a focusable
   7707      *         view, {@code false} otherwise
   7708      *
   7709      * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
   7710      * @see ViewGroup#getTouchscreenBlocksFocus()
   7711      * @see #hasExplicitFocusable()
   7712      */
   7713     public boolean hasFocusable() {
   7714         return hasFocusable(!sHasFocusableExcludeAutoFocusable, false);
   7715     }
   7716 
   7717     /**
   7718      * Returns true if this view is focusable or if it contains a reachable View
   7719      * for which {@link #hasExplicitFocusable()} returns {@code true}.
   7720      * A "reachable hasExplicitFocusable()" is a view whose parents do not block descendants focus.
   7721      * Only {@link #VISIBLE} views for which {@link #getFocusable()} would return
   7722      * {@link #FOCUSABLE} are considered focusable.
   7723      *
   7724      * <p>This method preserves the pre-{@link Build.VERSION_CODES#O} behavior of
   7725      * {@link #hasFocusable()} in that only views explicitly set focusable will cause
   7726      * this method to return true. A view set to {@link #FOCUSABLE_AUTO} that resolves
   7727      * to focusable will not.</p>
   7728      *
   7729      * @return {@code true} if the view is focusable or if the view contains a focusable
   7730      *         view, {@code false} otherwise
   7731      *
   7732      * @see #hasFocusable()
   7733      */
   7734     public boolean hasExplicitFocusable() {
   7735         return hasFocusable(false, true);
   7736     }
   7737 
   7738     boolean hasFocusable(boolean allowAutoFocus, boolean dispatchExplicit) {
   7739         if (!isFocusableInTouchMode()) {
   7740             for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
   7741                 final ViewGroup g = (ViewGroup) p;
   7742                 if (g.shouldBlockFocusForTouchscreen()) {
   7743                     return false;
   7744                 }
   7745             }
   7746         }
   7747 
   7748         // Invisible, gone, or disabled views are never focusable.
   7749         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE
   7750                 || (mViewFlags & ENABLED_MASK) != ENABLED) {
   7751             return false;
   7752         }
   7753 
   7754         // Only use effective focusable value when allowed.
   7755         if ((allowAutoFocus || getFocusable() != FOCUSABLE_AUTO) && isFocusable()) {
   7756             return true;
   7757         }
   7758 
   7759         return false;
   7760     }
   7761 
   7762     /**
   7763      * Called by the view system when the focus state of this view changes.
   7764      * When the focus change event is caused by directional navigation, direction
   7765      * and previouslyFocusedRect provide insight into where the focus is coming from.
   7766      * When overriding, be sure to call up through to the super class so that
   7767      * the standard focus handling will occur.
   7768      *
   7769      * @param gainFocus True if the View has focus; false otherwise.
   7770      * @param direction The direction focus has moved when requestFocus()
   7771      *                  is called to give this view focus. Values are
   7772      *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
   7773      *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
   7774      *                  It may not always apply, in which case use the default.
   7775      * @param previouslyFocusedRect The rectangle, in this view's coordinate
   7776      *        system, of the previously focused view.  If applicable, this will be
   7777      *        passed in as finer grained information about where the focus is coming
   7778      *        from (in addition to direction).  Will be <code>null</code> otherwise.
   7779      */
   7780     @CallSuper
   7781     protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
   7782             @Nullable Rect previouslyFocusedRect) {
   7783         if (gainFocus) {
   7784             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
   7785         } else {
   7786             notifyViewAccessibilityStateChangedIfNeeded(
   7787                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   7788         }
   7789 
   7790         // Here we check whether we still need the default focus highlight, and switch it on/off.
   7791         switchDefaultFocusHighlight();
   7792 
   7793         if (!gainFocus) {
   7794             if (isPressed()) {
   7795                 setPressed(false);
   7796             }
   7797             if (mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
   7798                 notifyFocusChangeToInputMethodManager(false /* hasFocus */);
   7799             }
   7800             onFocusLost();
   7801         } else if (mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
   7802             notifyFocusChangeToInputMethodManager(true /* hasFocus */);
   7803         }
   7804 
   7805         invalidate(true);
   7806         ListenerInfo li = mListenerInfo;
   7807         if (li != null && li.mOnFocusChangeListener != null) {
   7808             li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
   7809         }
   7810 
   7811         if (mAttachInfo != null) {
   7812             mAttachInfo.mKeyDispatchState.reset(this);
   7813         }
   7814 
   7815         notifyEnterOrExitForAutoFillIfNeeded(gainFocus);
   7816     }
   7817 
   7818     /**
   7819      * Notify {@link InputMethodManager} about the focus change of the {@link View}.
   7820      *
   7821      * <p>Does nothing when {@link InputMethodManager} is not available.</p>
   7822      *
   7823      * @param hasFocus {@code true} when the {@link View} is being focused.
   7824      */
   7825     private void notifyFocusChangeToInputMethodManager(boolean hasFocus) {
   7826         final InputMethodManager imm =
   7827                 getContext().getSystemService(InputMethodManager.class);
   7828         if (imm == null) {
   7829             return;
   7830         }
   7831         if (hasFocus) {
   7832             imm.focusIn(this);
   7833         } else {
   7834             imm.focusOut(this);
   7835         }
   7836     }
   7837 
   7838     /** @hide */
   7839     public void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {
   7840         if (canNotifyAutofillEnterExitEvent()) {
   7841             AutofillManager afm = getAutofillManager();
   7842             if (afm != null) {
   7843                 if (enter && isFocused()) {
   7844                     // We have not been laid out yet, hence cannot evaluate
   7845                     // whether this view is visible to the user, we will do
   7846                     // the evaluation once layout is complete.
   7847                     if (!isLaidOut()) {
   7848                         mPrivateFlags3 |= PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
   7849                     } else if (isVisibleToUser()) {
   7850                         // TODO This is a potential problem that View gets focus before it's visible
   7851                         // to User. Ideally View should handle the event when isVisibleToUser()
   7852                         // becomes true where it should issue notifyViewEntered().
   7853                         afm.notifyViewEntered(this);
   7854                     }
   7855                 } else if (!enter && !isFocused()) {
   7856                     afm.notifyViewExited(this);
   7857                 }
   7858             }
   7859         }
   7860     }
   7861 
   7862     /**
   7863      * Visually distinct portion of a window with window-like semantics are considered panes for
   7864      * accessibility purposes. One example is the content view of a fragment that is replaced.
   7865      * In order for accessibility services to understand a pane's window-like behavior, panes
   7866      * should have descriptive titles. Views with pane titles produce {@link AccessibilityEvent}s
   7867      * when they appear, disappear, or change title.
   7868      *
   7869      * @param accessibilityPaneTitle The pane's title. Setting to {@code null} indicates that this
   7870      *                               View is not a pane.
   7871      *
   7872      * {@see AccessibilityNodeInfo#setPaneTitle(CharSequence)}
   7873      *
   7874      * @attr ref android.R.styleable#View_accessibilityPaneTitle
   7875      */
   7876     public void setAccessibilityPaneTitle(@Nullable CharSequence accessibilityPaneTitle) {
   7877         if (!TextUtils.equals(accessibilityPaneTitle, mAccessibilityPaneTitle)) {
   7878             mAccessibilityPaneTitle = accessibilityPaneTitle;
   7879             notifyViewAccessibilityStateChangedIfNeeded(
   7880                     AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_TITLE);
   7881         }
   7882     }
   7883 
   7884     /**
   7885      * Get the title of the pane for purposes of accessibility.
   7886      *
   7887      * @return The current pane title.
   7888      *
   7889      * {@see #setAccessibilityPaneTitle}.
   7890      *
   7891      * @attr ref android.R.styleable#View_accessibilityPaneTitle
   7892      */
   7893     @InspectableProperty
   7894     @Nullable
   7895     public CharSequence getAccessibilityPaneTitle() {
   7896         return mAccessibilityPaneTitle;
   7897     }
   7898 
   7899     private boolean isAccessibilityPane() {
   7900         return mAccessibilityPaneTitle != null;
   7901     }
   7902 
   7903     /**
   7904      * Sends an accessibility event of the given type. If accessibility is
   7905      * not enabled this method has no effect. The default implementation calls
   7906      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
   7907      * to populate information about the event source (this View), then calls
   7908      * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
   7909      * populate the text content of the event source including its descendants,
   7910      * and last calls
   7911      * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
   7912      * on its parent to request sending of the event to interested parties.
   7913      * <p>
   7914      * If an {@link AccessibilityDelegate} has been specified via calling
   7915      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   7916      * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
   7917      * responsible for handling this call.
   7918      * </p>
   7919      *
   7920      * @param eventType The type of the event to send, as defined by several types from
   7921      * {@link android.view.accessibility.AccessibilityEvent}, such as
   7922      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
   7923      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
   7924      *
   7925      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
   7926      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   7927      * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
   7928      * @see AccessibilityDelegate
   7929      */
   7930     public void sendAccessibilityEvent(int eventType) {
   7931         if (mAccessibilityDelegate != null) {
   7932             mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
   7933         } else {
   7934             sendAccessibilityEventInternal(eventType);
   7935         }
   7936     }
   7937 
   7938     /**
   7939      * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
   7940      * {@link AccessibilityEvent} to suggest that an accessibility service announce the
   7941      * specified text to its users.
   7942      * <p>
   7943      * Note: The event generated with this API carries no semantic meaning, and is appropriate only
   7944      * in exceptional situations. Apps can generally achieve correct behavior for accessibility by
   7945      * accurately supplying the semantics of their UI.
   7946      * They should not need to specify what exactly is announced to users.
   7947      *
   7948      * @param text The announcement text.
   7949      */
   7950     public void announceForAccessibility(CharSequence text) {
   7951         if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
   7952             AccessibilityEvent event = AccessibilityEvent.obtain(
   7953                     AccessibilityEvent.TYPE_ANNOUNCEMENT);
   7954             onInitializeAccessibilityEvent(event);
   7955             event.getText().add(text);
   7956             event.setContentDescription(null);
   7957             mParent.requestSendAccessibilityEvent(this, event);
   7958         }
   7959     }
   7960 
   7961     /**
   7962      * @see #sendAccessibilityEvent(int)
   7963      *
   7964      * Note: Called from the default {@link AccessibilityDelegate}.
   7965      *
   7966      * @hide
   7967      */
   7968     public void sendAccessibilityEventInternal(int eventType) {
   7969         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
   7970             sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
   7971         }
   7972     }
   7973 
   7974     /**
   7975      * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
   7976      * takes as an argument an empty {@link AccessibilityEvent} and does not
   7977      * perform a check whether accessibility is enabled.
   7978      * <p>
   7979      * If an {@link AccessibilityDelegate} has been specified via calling
   7980      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   7981      * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
   7982      * is responsible for handling this call.
   7983      * </p>
   7984      *
   7985      * @param event The event to send.
   7986      *
   7987      * @see #sendAccessibilityEvent(int)
   7988      */
   7989     public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
   7990         if (mAccessibilityDelegate != null) {
   7991             mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
   7992         } else {
   7993             sendAccessibilityEventUncheckedInternal(event);
   7994         }
   7995     }
   7996 
   7997     /**
   7998      * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
   7999      *
   8000      * Note: Called from the default {@link AccessibilityDelegate}.
   8001      *
   8002      * @hide
   8003      */
   8004     public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
   8005         // Panes disappearing are relevant even if though the view is no longer visible.
   8006         boolean isWindowStateChanged =
   8007                 (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
   8008         boolean isWindowDisappearedEvent = isWindowStateChanged && ((event.getContentChangeTypes()
   8009                 & AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED) != 0);
   8010         if (!isShown() && !isWindowDisappearedEvent) {
   8011             return;
   8012         }
   8013         onInitializeAccessibilityEvent(event);
   8014         // Only a subset of accessibility events populates text content.
   8015         if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
   8016             dispatchPopulateAccessibilityEvent(event);
   8017         }
   8018         // In the beginning we called #isShown(), so we know that getParent() is not null.
   8019         ViewParent parent = getParent();
   8020         if (parent != null) {
   8021             getParent().requestSendAccessibilityEvent(this, event);
   8022         }
   8023     }
   8024 
   8025     /**
   8026      * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
   8027      * to its children for adding their text content to the event. Note that the
   8028      * event text is populated in a separate dispatch path since we add to the
   8029      * event not only the text of the source but also the text of all its descendants.
   8030      * A typical implementation will call
   8031      * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
   8032      * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
   8033      * on each child. Override this method if custom population of the event text
   8034      * content is required.
   8035      * <p>
   8036      * If an {@link AccessibilityDelegate} has been specified via calling
   8037      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   8038      * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
   8039      * is responsible for handling this call.
   8040      * </p>
   8041      * <p>
   8042      * <em>Note:</em> Accessibility events of certain types are not dispatched for
   8043      * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
   8044      * </p>
   8045      *
   8046      * @param event The event.
   8047      *
   8048      * @return True if the event population was completed.
   8049      */
   8050     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
   8051         if (mAccessibilityDelegate != null) {
   8052             return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
   8053         } else {
   8054             return dispatchPopulateAccessibilityEventInternal(event);
   8055         }
   8056     }
   8057 
   8058     /**
   8059      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   8060      *
   8061      * Note: Called from the default {@link AccessibilityDelegate}.
   8062      *
   8063      * @hide
   8064      */
   8065     public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
   8066         onPopulateAccessibilityEvent(event);
   8067         return false;
   8068     }
   8069 
   8070     /**
   8071      * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
   8072      * giving a chance to this View to populate the accessibility event with its
   8073      * text content. While this method is free to modify event
   8074      * attributes other than text content, doing so should normally be performed in
   8075      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
   8076      * <p>
   8077      * Example: Adding formatted date string to an accessibility event in addition
   8078      *          to the text added by the super implementation:
   8079      * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
   8080      *     super.onPopulateAccessibilityEvent(event);
   8081      *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
   8082      *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
   8083      *         mCurrentDate.getTimeInMillis(), flags);
   8084      *     event.getText().add(selectedDateUtterance);
   8085      * }</pre>
   8086      * <p>
   8087      * If an {@link AccessibilityDelegate} has been specified via calling
   8088      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   8089      * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
   8090      * is responsible for handling this call.
   8091      * </p>
   8092      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
   8093      * information to the event, in case the default implementation has basic information to add.
   8094      * </p>
   8095      *
   8096      * @param event The accessibility event which to populate.
   8097      *
   8098      * @see #sendAccessibilityEvent(int)
   8099      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   8100      */
   8101     @CallSuper
   8102     public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
   8103         if (mAccessibilityDelegate != null) {
   8104             mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
   8105         } else {
   8106             onPopulateAccessibilityEventInternal(event);
   8107         }
   8108     }
   8109 
   8110     /**
   8111      * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
   8112      *
   8113      * Note: Called from the default {@link AccessibilityDelegate}.
   8114      *
   8115      * @hide
   8116      */
   8117     public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
   8118         if ((event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED)
   8119                 && isAccessibilityPane()) {
   8120             event.getText().add(getAccessibilityPaneTitle());
   8121         }
   8122     }
   8123 
   8124     /**
   8125      * Initializes an {@link AccessibilityEvent} with information about
   8126      * this View which is the event source. In other words, the source of
   8127      * an accessibility event is the view whose state change triggered firing
   8128      * the event.
   8129      * <p>
   8130      * Example: Setting the password property of an event in addition
   8131      *          to properties set by the super implementation:
   8132      * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
   8133      *     super.onInitializeAccessibilityEvent(event);
   8134      *     event.setPassword(true);
   8135      * }</pre>
   8136      * <p>
   8137      * If an {@link AccessibilityDelegate} has been specified via calling
   8138      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   8139      * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
   8140      * is responsible for handling this call.
   8141      * </p>
   8142      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
   8143      * information to the event, in case the default implementation has basic information to add.
   8144      * </p>
   8145      * @param event The event to initialize.
   8146      *
   8147      * @see #sendAccessibilityEvent(int)
   8148      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   8149      */
   8150     @CallSuper
   8151     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
   8152         if (mAccessibilityDelegate != null) {
   8153             mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
   8154         } else {
   8155             onInitializeAccessibilityEventInternal(event);
   8156         }
   8157     }
   8158 
   8159     /**
   8160      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
   8161      *
   8162      * Note: Called from the default {@link AccessibilityDelegate}.
   8163      *
   8164      * @hide
   8165      */
   8166     @UnsupportedAppUsage
   8167     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
   8168         event.setSource(this);
   8169         event.setClassName(getAccessibilityClassName());
   8170         event.setPackageName(getContext().getPackageName());
   8171         event.setEnabled(isEnabled());
   8172         event.setContentDescription(mContentDescription);
   8173 
   8174         switch (event.getEventType()) {
   8175             case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
   8176                 ArrayList<View> focusablesTempList = (mAttachInfo != null)
   8177                         ? mAttachInfo.mTempArrayList : new ArrayList<View>();
   8178                 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
   8179                 event.setItemCount(focusablesTempList.size());
   8180                 event.setCurrentItemIndex(focusablesTempList.indexOf(this));
   8181                 if (mAttachInfo != null) {
   8182                     focusablesTempList.clear();
   8183                 }
   8184             } break;
   8185             case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
   8186                 CharSequence text = getIterableTextForAccessibility();
   8187                 if (text != null && text.length() > 0) {
   8188                     event.setFromIndex(getAccessibilitySelectionStart());
   8189                     event.setToIndex(getAccessibilitySelectionEnd());
   8190                     event.setItemCount(text.length());
   8191                 }
   8192             } break;
   8193         }
   8194     }
   8195 
   8196     /**
   8197      * Returns an {@link AccessibilityNodeInfo} representing this view from the
   8198      * point of view of an {@link android.accessibilityservice.AccessibilityService}.
   8199      * This method is responsible for obtaining an accessibility node info from a
   8200      * pool of reusable instances and calling
   8201      * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
   8202      * initialize the former.
   8203      * <p>
   8204      * Note: The client is responsible for recycling the obtained instance by calling
   8205      *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
   8206      * </p>
   8207      *
   8208      * @return A populated {@link AccessibilityNodeInfo}.
   8209      *
   8210      * @see AccessibilityNodeInfo
   8211      */
   8212     public AccessibilityNodeInfo createAccessibilityNodeInfo() {
   8213         if (mAccessibilityDelegate != null) {
   8214             return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
   8215         } else {
   8216             return createAccessibilityNodeInfoInternal();
   8217         }
   8218     }
   8219 
   8220     /**
   8221      * @see #createAccessibilityNodeInfo()
   8222      *
   8223      * @hide
   8224      */
   8225     public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
   8226         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
   8227         if (provider != null) {
   8228             return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
   8229         } else {
   8230             AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
   8231             onInitializeAccessibilityNodeInfo(info);
   8232             return info;
   8233         }
   8234     }
   8235 
   8236     /**
   8237      * Initializes an {@link AccessibilityNodeInfo} with information about this view.
   8238      * The base implementation sets:
   8239      * <ul>
   8240      *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
   8241      *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
   8242      *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
   8243      *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
   8244      *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
   8245      *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
   8246      *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
   8247      *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
   8248      *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
   8249      *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
   8250      *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
   8251      *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
   8252      *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
   8253      * </ul>
   8254      * <p>
   8255      * Subclasses should override this method, call the super implementation,
   8256      * and set additional attributes.
   8257      * </p>
   8258      * <p>
   8259      * If an {@link AccessibilityDelegate} has been specified via calling
   8260      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   8261      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
   8262      * is responsible for handling this call.
   8263      * </p>
   8264      *
   8265      * @param info The instance to initialize.
   8266      */
   8267     @CallSuper
   8268     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
   8269         if (mAccessibilityDelegate != null) {
   8270             mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
   8271         } else {
   8272             onInitializeAccessibilityNodeInfoInternal(info);
   8273         }
   8274     }
   8275 
   8276     /**
   8277      * Gets the location of this view in screen coordinates.
   8278      *
   8279      * @param outRect The output location
   8280      * @hide
   8281      */
   8282     @UnsupportedAppUsage
   8283     public void getBoundsOnScreen(Rect outRect) {
   8284         getBoundsOnScreen(outRect, false);
   8285     }
   8286 
   8287     /**
   8288      * Gets the location of this view in screen coordinates.
   8289      *
   8290      * @param outRect The output location
   8291      * @param clipToParent Whether to clip child bounds to the parent ones.
   8292      * @hide
   8293      */
   8294     @UnsupportedAppUsage
   8295     public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
   8296         if (mAttachInfo == null) {
   8297             return;
   8298         }
   8299 
   8300         RectF position = mAttachInfo.mTmpTransformRect;
   8301         position.set(0, 0, mRight - mLeft, mBottom - mTop);
   8302         mapRectFromViewToScreenCoords(position, clipToParent);
   8303         outRect.set(Math.round(position.left), Math.round(position.top),
   8304                 Math.round(position.right), Math.round(position.bottom));
   8305     }
   8306 
   8307     /**
   8308      * Map a rectangle from view-relative coordinates to screen-relative coordinates
   8309      *
   8310      * @param rect The rectangle to be mapped
   8311      * @param clipToParent Whether to clip child bounds to the parent ones.
   8312      * @hide
   8313      */
   8314     public void mapRectFromViewToScreenCoords(RectF rect, boolean clipToParent) {
   8315         if (!hasIdentityMatrix()) {
   8316             getMatrix().mapRect(rect);
   8317         }
   8318 
   8319         rect.offset(mLeft, mTop);
   8320 
   8321         ViewParent parent = mParent;
   8322         while (parent instanceof View) {
   8323             View parentView = (View) parent;
   8324 
   8325             rect.offset(-parentView.mScrollX, -parentView.mScrollY);
   8326 
   8327             if (clipToParent) {
   8328                 rect.left = Math.max(rect.left, 0);
   8329                 rect.top = Math.max(rect.top, 0);
   8330                 rect.right = Math.min(rect.right, parentView.getWidth());
   8331                 rect.bottom = Math.min(rect.bottom, parentView.getHeight());
   8332             }
   8333 
   8334             if (!parentView.hasIdentityMatrix()) {
   8335                 parentView.getMatrix().mapRect(rect);
   8336             }
   8337 
   8338             rect.offset(parentView.mLeft, parentView.mTop);
   8339 
   8340             parent = parentView.mParent;
   8341         }
   8342 
   8343         if (parent instanceof ViewRootImpl) {
   8344             ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
   8345             rect.offset(0, -viewRootImpl.mCurScrollY);
   8346         }
   8347 
   8348         rect.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
   8349     }
   8350 
   8351     /**
   8352      * Return the class name of this object to be used for accessibility purposes.
   8353      * Subclasses should only override this if they are implementing something that
   8354      * should be seen as a completely new class of view when used by accessibility,
   8355      * unrelated to the class it is deriving from.  This is used to fill in
   8356      * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
   8357      */
   8358     public CharSequence getAccessibilityClassName() {
   8359         return View.class.getName();
   8360     }
   8361 
   8362     /**
   8363      * Called when assist structure is being retrieved from a view as part of
   8364      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
   8365      * @param structure Fill in with structured view data.  The default implementation
   8366      * fills in all data that can be inferred from the view itself.
   8367      */
   8368     public void onProvideStructure(ViewStructure structure) {
   8369         onProvideStructure(structure, VIEW_STRUCTURE_FOR_ASSIST, /* flags= */ 0);
   8370     }
   8371 
   8372     /**
   8373      * Populates a {@link ViewStructure} to fullfil an autofill request.
   8374      *
   8375      * <p>The structure should contain at least the following properties:
   8376      * <ul>
   8377      *   <li>Autofill id ({@link ViewStructure#setAutofillId(AutofillId, int)}).
   8378      *   <li>Autofill type ({@link ViewStructure#setAutofillType(int)}).
   8379      *   <li>Autofill value ({@link ViewStructure#setAutofillValue(AutofillValue)}).
   8380      *   <li>Whether the data is sensitive ({@link ViewStructure#setDataIsSensitive(boolean)}).
   8381      * </ul>
   8382      *
   8383      * <p>It's also recommended to set the following properties - the more properties the structure
   8384      * has, the higher the changes of an {@link android.service.autofill.AutofillService} properly
   8385      * using the structure:
   8386      *
   8387      * <ul>
   8388      *   <li>Autofill hints ({@link ViewStructure#setAutofillHints(String[])}).
   8389      *   <li>Autofill options ({@link ViewStructure#setAutofillOptions(CharSequence[])}) when the
   8390      *       view can only be filled with predefined values (typically used when the autofill type
   8391      *       is {@link #AUTOFILL_TYPE_LIST}).
   8392      *   <li>Resource id ({@link ViewStructure#setId(int, String, String, String)}).
   8393      *   <li>Class name ({@link ViewStructure#setClassName(String)}).
   8394      *   <li>Content description ({@link ViewStructure#setContentDescription(CharSequence)}).
   8395      *   <li>Visual properties such as visibility ({@link ViewStructure#setVisibility(int)}),
   8396      *       dimensions ({@link ViewStructure#setDimens(int, int, int, int, int, int)}), and
   8397      *       opacity ({@link ViewStructure#setOpaque(boolean)}).
   8398      *   <li>For views representing text fields, text properties such as the text itself
   8399      *       ({@link ViewStructure#setText(CharSequence)}), text hints
   8400      *       ({@link ViewStructure#setHint(CharSequence)}, input type
   8401      *       ({@link ViewStructure#setInputType(int)}),
   8402      *   <li>For views representing HTML nodes, its web domain
   8403      *       ({@link ViewStructure#setWebDomain(String)}) and HTML properties
   8404      *       (({@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}).
   8405      * </ul>
   8406      *
   8407      * <p>The default implementation of this method already sets most of these properties based on
   8408      * related {@link View} methods (for example, the autofill id is set using
   8409      * {@link #getAutofillId()}, the autofill type set using {@link #getAutofillType()}, etc.),
   8410      * and views in the standard Android widgets library also override it to set their
   8411      * relevant properties (for example, {@link android.widget.TextView} already sets the text
   8412      * properties), so it's recommended to only override this method
   8413      * (and call {@code super.onProvideAutofillStructure()}) when:
   8414      *
   8415      * <ul>
   8416      *   <li>The view contents does not include PII (Personally Identifiable Information), so it
   8417      *       can call {@link ViewStructure#setDataIsSensitive(boolean)} passing {@code false}.
   8418      *   <li>The view can only be autofilled with predefined options, so it can call
   8419      *       {@link ViewStructure#setAutofillOptions(CharSequence[])}.
   8420      * </ul>
   8421      *
   8422      * <p><b>Note:</b> The {@code left} and {@code top} values set in
   8423      * {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the next
   8424      * {@link ViewGroup#isImportantForAutofill()} predecessor view included in the structure.
   8425      *
   8426      * <p>Views support the Autofill Framework mainly by:
   8427      * <ul>
   8428      *   <li>Providing the metadata defining what the view means and how it can be autofilled.
   8429      *   <li>Notifying the Android System when the view value changed by calling
   8430      *       {@link AutofillManager#notifyValueChanged(View)}.
   8431      *   <li>Implementing the methods that autofill the view.
   8432      * </ul>
   8433      * <p>This method is responsible for the former; {@link #autofill(AutofillValue)} is responsible
   8434      * for the latter.
   8435      *
   8436      * @param structure fill in with structured view data for autofill purposes.
   8437      * @param flags optional flags.
   8438      *
   8439      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
   8440      */
   8441     public void onProvideAutofillStructure(ViewStructure structure, @AutofillFlags int flags) {
   8442         onProvideStructure(structure, VIEW_STRUCTURE_FOR_AUTOFILL, flags);
   8443     }
   8444 
   8445     /** @hide */
   8446     protected void onProvideStructure(@NonNull ViewStructure structure,
   8447             @ViewStructureType int viewFor, int flags) {
   8448         final int id = mID;
   8449         if (id != NO_ID && !isViewIdGenerated(id)) {
   8450             String pkg, type, entry;
   8451             try {
   8452                 final Resources res = getResources();
   8453                 entry = res.getResourceEntryName(id);
   8454                 type = res.getResourceTypeName(id);
   8455                 pkg = res.getResourcePackageName(id);
   8456             } catch (Resources.NotFoundException e) {
   8457                 entry = type = pkg = null;
   8458             }
   8459             structure.setId(id, pkg, type, entry);
   8460         } else {
   8461             structure.setId(id, null, null, null);
   8462         }
   8463 
   8464         if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
   8465                 || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
   8466             final @AutofillType int autofillType = getAutofillType();
   8467             // Don't need to fill autofill info if view does not support it.
   8468             // For example, only TextViews that are editable support autofill
   8469             if (autofillType != AUTOFILL_TYPE_NONE) {
   8470                 structure.setAutofillType(autofillType);
   8471                 structure.setAutofillHints(getAutofillHints());
   8472                 structure.setAutofillValue(getAutofillValue());
   8473             }
   8474             structure.setImportantForAutofill(getImportantForAutofill());
   8475         }
   8476 
   8477         int ignoredParentLeft = 0;
   8478         int ignoredParentTop = 0;
   8479         if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
   8480                 && (flags & AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) {
   8481             View parentGroup = null;
   8482 
   8483             ViewParent viewParent = getParent();
   8484             if (viewParent instanceof View) {
   8485                 parentGroup = (View) viewParent;
   8486             }
   8487 
   8488             while (parentGroup != null && !parentGroup.isImportantForAutofill()) {
   8489                 ignoredParentLeft += parentGroup.mLeft;
   8490                 ignoredParentTop += parentGroup.mTop;
   8491 
   8492                 viewParent = parentGroup.getParent();
   8493                 if (viewParent instanceof View) {
   8494                     parentGroup = (View) viewParent;
   8495                 } else {
   8496                     break;
   8497                 }
   8498             }
   8499         }
   8500 
   8501         structure.setDimens(ignoredParentLeft + mLeft, ignoredParentTop + mTop, mScrollX, mScrollY,
   8502                 mRight - mLeft, mBottom - mTop);
   8503         if (viewFor == VIEW_STRUCTURE_FOR_ASSIST) {
   8504             if (!hasIdentityMatrix()) {
   8505                 structure.setTransformation(getMatrix());
   8506             }
   8507             structure.setElevation(getZ());
   8508         }
   8509         structure.setVisibility(getVisibility());
   8510         structure.setEnabled(isEnabled());
   8511         if (isClickable()) {
   8512             structure.setClickable(true);
   8513         }
   8514         if (isFocusable()) {
   8515             structure.setFocusable(true);
   8516         }
   8517         if (isFocused()) {
   8518             structure.setFocused(true);
   8519         }
   8520         if (isAccessibilityFocused()) {
   8521             structure.setAccessibilityFocused(true);
   8522         }
   8523         if (isSelected()) {
   8524             structure.setSelected(true);
   8525         }
   8526         if (isActivated()) {
   8527             structure.setActivated(true);
   8528         }
   8529         if (isLongClickable()) {
   8530             structure.setLongClickable(true);
   8531         }
   8532         if (this instanceof Checkable) {
   8533             structure.setCheckable(true);
   8534             if (((Checkable)this).isChecked()) {
   8535                 structure.setChecked(true);
   8536             }
   8537         }
   8538         if (isOpaque()) {
   8539             structure.setOpaque(true);
   8540         }
   8541         if (isContextClickable()) {
   8542             structure.setContextClickable(true);
   8543         }
   8544         structure.setClassName(getAccessibilityClassName().toString());
   8545         structure.setContentDescription(getContentDescription());
   8546     }
   8547 
   8548     /**
   8549      * Called when assist structure is being retrieved from a view as part of
   8550      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
   8551      * generate additional virtual structure under this view.  The defaullt implementation
   8552      * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
   8553      * view's virtual accessibility nodes, if any.  You can override this for a more
   8554      * optimal implementation providing this data.
   8555      */
   8556     public void onProvideVirtualStructure(ViewStructure structure) {
   8557         onProvideVirtualStructureCompat(structure, false);
   8558     }
   8559 
   8560     /**
   8561      * Fallback implementation to populate a ViewStructure from accessibility state.
   8562      *
   8563      * @param structure The structure to populate.
   8564      * @param forAutofill Whether the structure is needed for autofill.
   8565      */
   8566     private void onProvideVirtualStructureCompat(ViewStructure structure, boolean forAutofill) {
   8567         final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
   8568         if (provider != null) {
   8569             if (forAutofill && Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
   8570                 Log.v(AUTOFILL_LOG_TAG, "onProvideVirtualStructureCompat() for " + this);
   8571             }
   8572             final AccessibilityNodeInfo info = createAccessibilityNodeInfo();
   8573             structure.setChildCount(1);
   8574             final ViewStructure root = structure.newChild(0);
   8575             populateVirtualStructure(root, provider, info, forAutofill);
   8576             info.recycle();
   8577         }
   8578     }
   8579 
   8580     /**
   8581      * Populates a {@link ViewStructure} containing virtual children to fullfil an autofill
   8582      * request.
   8583      *
   8584      * <p>This method should be used when the view manages a virtual structure under this view. For
   8585      * example, a view that draws input fields using {@link #draw(Canvas)}.
   8586      *
   8587      * <p>When implementing this method, subclasses must follow the rules below:
   8588      *
   8589      * <ul>
   8590      *   <li>Add virtual children by calling the {@link ViewStructure#newChild(int)} or
   8591      *       {@link ViewStructure#asyncNewChild(int)} methods, where the {@code id} is an unique id
   8592      *       identifying the children in the virtual structure.
   8593      *   <li>The children hierarchy can have multiple levels if necessary, but ideally it should
   8594      *       exclude intermediate levels that are irrelevant for autofill; that would improve the
   8595      *       autofill performance.
   8596      *   <li>Also implement {@link #autofill(SparseArray)} to autofill the virtual
   8597      *       children.
   8598      *   <li>Set the autofill properties of the child structure as defined by
   8599      *       {@link #onProvideAutofillStructure(ViewStructure, int)}, using
   8600      *       {@link ViewStructure#setAutofillId(AutofillId, int)} to set its autofill id.
   8601      *   <li>Call {@link android.view.autofill.AutofillManager#notifyViewEntered(View, int, Rect)}
   8602      *       and/or {@link android.view.autofill.AutofillManager#notifyViewExited(View, int)}
   8603      *       when the focused virtual child changed.
   8604      *   <li>Override {@link #isVisibleToUserForAutofill(int)} to allow the platform to query
   8605      *       whether a given virtual view is visible to the user in order to support triggering
   8606      *       save when all views of interest go away.
   8607      *   <li>Call
   8608      *    {@link android.view.autofill.AutofillManager#notifyValueChanged(View, int, AutofillValue)}
   8609      *       when the value of a virtual child changed.
   8610      *   <li>Call {@link
   8611      *    android.view.autofill.AutofillManager#notifyViewVisibilityChanged(View, int, boolean)}
   8612      *       when the visibility of a virtual child changed.
   8613      *   <li>Call
   8614      *    {@link android.view.autofill.AutofillManager#notifyViewClicked(View, int)} when a virtual
   8615      *       child is clicked.
   8616      *   <li>Call {@link AutofillManager#commit()} when the autofill context of the view structure
   8617      *       changed and the current context should be committed (for example, when the user tapped
   8618      *       a {@code SUBMIT} button in an HTML page).
   8619      *   <li>Call {@link AutofillManager#cancel()} when the autofill context of the view structure
   8620      *       changed and the current context should be canceled (for example, when the user tapped
   8621      *       a {@code CANCEL} button in an HTML page).
   8622      *   <li>Provide ways for users to manually request autofill by calling
   8623      *       {@link AutofillManager#requestAutofill(View, int, Rect)}.
   8624      *   <li>The {@code left} and {@code top} values set in
   8625      *       {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the
   8626      *       next {@link ViewGroup#isImportantForAutofill()} predecessor view included in the
   8627      *       structure.
   8628      * </ul>
   8629      *
   8630      * <p>Views with virtual children support the Autofill Framework mainly by:
   8631      * <ul>
   8632      *   <li>Providing the metadata defining what the virtual children mean and how they can be
   8633      *       autofilled.
   8634      *   <li>Implementing the methods that autofill the virtual children.
   8635      * </ul>
   8636      * <p>This method is responsible for the former; {@link #autofill(SparseArray)} is responsible
   8637      * for the latter.
   8638      *
   8639      * @param structure fill in with virtual children data for autofill purposes.
   8640      * @param flags optional flags.
   8641      *
   8642      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
   8643      */
   8644     public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
   8645         if (mContext.isAutofillCompatibilityEnabled()) {
   8646             onProvideVirtualStructureCompat(structure, true);
   8647         }
   8648     }
   8649 
   8650     /**
   8651      * Automatically fills the content of this view with the {@code value}.
   8652      *
   8653      * <p>Views support the Autofill Framework mainly by:
   8654      * <ul>
   8655      *   <li>Providing the metadata defining what the view means and how it can be autofilled.
   8656      *   <li>Implementing the methods that autofill the view.
   8657      * </ul>
   8658      * <p>{@link #onProvideAutofillStructure(ViewStructure, int)} is responsible for the former,
   8659      * this method is responsible for latter.
   8660      *
   8661      * <p>This method does nothing by default, but when overridden it typically:
   8662      * <ol>
   8663      *   <li>Checks if the provided value matches the expected type (which is defined by
   8664      *       {@link #getAutofillType()}).
   8665      *   <li>Checks if the view is editable - if it isn't, it should return right away.
   8666      *   <li>Call the proper getter method on {@link AutofillValue} to fetch the actual value.
   8667      *   <li>Pass the actual value to the equivalent setter in the view.
   8668      * </ol>
   8669      *
   8670      * <p>For example, a text-field view could implement the method this way:
   8671      *
   8672      * <pre class="prettyprint">
   8673      * &#64;Override
   8674      * public void autofill(AutofillValue value) {
   8675      *   if (!value.isText() || !this.isEditable()) {
   8676      *      return;
   8677      *   }
   8678      *   CharSequence text = value.getTextValue();
   8679      *   if (text != null) {
   8680      *     this.setText(text);
   8681      *   }
   8682      * }
   8683      * </pre>
   8684      *
   8685      * <p>If the value is updated asynchronously, the next call to
   8686      * {@link AutofillManager#notifyValueChanged(View)} must happen <b>after</b> the value was
   8687      * changed to the autofilled value. If not, the view will not be considered autofilled.
   8688      *
   8689      * <p><b>Note:</b> After this method is called, the value returned by
   8690      * {@link #getAutofillValue()} must be equal to the {@code value} passed to it, otherwise the
   8691      * view will not be highlighted as autofilled.
   8692      *
   8693      * @param value value to be autofilled.
   8694      */
   8695     public void autofill(@SuppressWarnings("unused") AutofillValue value) {
   8696     }
   8697 
   8698     /**
   8699      * Automatically fills the content of the virtual children within this view.
   8700      *
   8701      * <p>Views with virtual children support the Autofill Framework mainly by:
   8702      * <ul>
   8703      *   <li>Providing the metadata defining what the virtual children mean and how they can be
   8704      *       autofilled.
   8705      *   <li>Implementing the methods that autofill the virtual children.
   8706      * </ul>
   8707      * <p>{@link #onProvideAutofillVirtualStructure(ViewStructure, int)} is responsible for the
   8708      * former, this method is responsible for the latter - see {@link #autofill(AutofillValue)} and
   8709      * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} for more info about autofill.
   8710      *
   8711      * <p>If a child value is updated asynchronously, the next call to
   8712      * {@link AutofillManager#notifyValueChanged(View, int, AutofillValue)} must happen
   8713      * <b>after</b> the value was changed to the autofilled value. If not, the child will not be
   8714      * considered autofilled.
   8715      *
   8716      * <p><b>Note:</b> To indicate that a virtual view was autofilled,
   8717      * <code>?android:attr/autofilledHighlight</code> should be drawn over it until the data
   8718      * changes.
   8719      *
   8720      * @param values map of values to be autofilled, keyed by virtual child id.
   8721      *
   8722      * @attr ref android.R.styleable#Theme_autofilledHighlight
   8723      */
   8724     public void autofill(@NonNull @SuppressWarnings("unused") SparseArray<AutofillValue> values) {
   8725         if (!mContext.isAutofillCompatibilityEnabled()) {
   8726             return;
   8727         }
   8728         final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
   8729         if (provider == null) {
   8730             return;
   8731         }
   8732         final int valueCount = values.size();
   8733         for (int i = 0; i < valueCount; i++) {
   8734             final AutofillValue value = values.valueAt(i);
   8735             if (value.isText()) {
   8736                 final int virtualId = values.keyAt(i);
   8737                 final CharSequence text = value.getTextValue();
   8738                 final Bundle arguments = new Bundle();
   8739                 arguments.putCharSequence(
   8740                         AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text);
   8741                 provider.performAction(virtualId, AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
   8742             }
   8743         }
   8744     }
   8745 
   8746     /**
   8747      * Gets the unique, logical identifier of this view in the activity, for autofill purposes.
   8748      *
   8749      * <p>The autofill id is created on demand, unless it is explicitly set by
   8750      * {@link #setAutofillId(AutofillId)}.
   8751      *
   8752      * <p>See {@link #setAutofillId(AutofillId)} for more info.
   8753      *
   8754      * @return The View's autofill id.
   8755      */
   8756     public final AutofillId getAutofillId() {
   8757         if (mAutofillId == null) {
   8758             // The autofill id needs to be unique, but its value doesn't matter,
   8759             // so it's better to reuse the accessibility id to save space.
   8760             mAutofillId = new AutofillId(getAutofillViewId());
   8761         }
   8762         return mAutofillId;
   8763     }
   8764 
   8765     /**
   8766      * Sets the unique, logical identifier of this view in the activity, for autofill purposes.
   8767      *
   8768      * <p>The autofill id is created on demand, and this method should only be called when a view is
   8769      * reused after {@link #dispatchProvideAutofillStructure(ViewStructure, int)} is called, as
   8770      * that method creates a snapshot of the view that is passed along to the autofill service.
   8771      *
   8772      * <p>This method is typically used when view subtrees are recycled to represent different
   8773      * content* &mdash;in this case, the autofill id can be saved before the view content is swapped
   8774      * out, and restored later when it's swapped back in. For example:
   8775      *
   8776      * <pre>
   8777      * EditText reusableView = ...;
   8778      * ViewGroup parentView = ...;
   8779      * AutofillManager afm = ...;
   8780      *
   8781      * // Swap out the view and change its contents
   8782      * AutofillId oldId = reusableView.getAutofillId();
   8783      * CharSequence oldText = reusableView.getText();
   8784      * parentView.removeView(reusableView);
   8785      * AutofillId newId = afm.getNextAutofillId();
   8786      * reusableView.setText("New I am");
   8787      * reusableView.setAutofillId(newId);
   8788      * parentView.addView(reusableView);
   8789      *
   8790      * // Later, swap the old content back in
   8791      * parentView.removeView(reusableView);
   8792      * reusableView.setAutofillId(oldId);
   8793      * reusableView.setText(oldText);
   8794      * parentView.addView(reusableView);
   8795      * </pre>
   8796      *
   8797      * @param id an autofill ID that is unique in the {@link android.app.Activity} hosting the view,
   8798      * or {@code null} to reset it. Usually it's an id previously allocated to another view (and
   8799      * obtained through {@link #getAutofillId()}), or a new value obtained through
   8800      * {@link AutofillManager#getNextAutofillId()}.
   8801      *
   8802      * @throws IllegalStateException if the view is already {@link #isAttachedToWindow() attached to
   8803      * a window}.
   8804      *
   8805      * @throws IllegalArgumentException if the id is an autofill id associated with a virtual view.
   8806      */
   8807     public void setAutofillId(@Nullable AutofillId id) {
   8808         // TODO(b/37566627): add unit / CTS test for all possible combinations below
   8809         if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
   8810             Log.v(AUTOFILL_LOG_TAG, "setAutofill(): from " + mAutofillId + " to " + id);
   8811         }
   8812         if (isAttachedToWindow()) {
   8813             throw new IllegalStateException("Cannot set autofill id when view is attached");
   8814         }
   8815         if (id != null && !id.isNonVirtual()) {
   8816             throw new IllegalStateException("Cannot set autofill id assigned to virtual views");
   8817         }
   8818         if (id == null && (mPrivateFlags3 & PFLAG3_AUTOFILLID_EXPLICITLY_SET) == 0) {
   8819             // Ignore reset because it was never explicitly set before.
   8820             return;
   8821         }
   8822         mAutofillId = id;
   8823         if (id != null) {
   8824             mAutofillViewId = id.getViewId();
   8825             mPrivateFlags3 |= PFLAG3_AUTOFILLID_EXPLICITLY_SET;
   8826         } else {
   8827             mAutofillViewId = NO_ID;
   8828             mPrivateFlags3 &= ~PFLAG3_AUTOFILLID_EXPLICITLY_SET;
   8829         }
   8830     }
   8831 
   8832     /**
   8833      * Describes the autofill type of this view, so an
   8834      * {@link android.service.autofill.AutofillService} can create the proper {@link AutofillValue}
   8835      * when autofilling the view.
   8836      *
   8837      * <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it to properly
   8838      * support the Autofill Framework.
   8839      *
   8840      * @return either {@link #AUTOFILL_TYPE_NONE}, {@link #AUTOFILL_TYPE_TEXT},
   8841      * {@link #AUTOFILL_TYPE_LIST}, {@link #AUTOFILL_TYPE_DATE}, or {@link #AUTOFILL_TYPE_TOGGLE}.
   8842      *
   8843      * @see #onProvideAutofillStructure(ViewStructure, int)
   8844      * @see #autofill(AutofillValue)
   8845      */
   8846     public @AutofillType int getAutofillType() {
   8847         return AUTOFILL_TYPE_NONE;
   8848     }
   8849 
   8850     /**
   8851      * Gets the hints that help an {@link android.service.autofill.AutofillService} determine how
   8852      * to autofill the view with the user's data.
   8853      *
   8854      * <p>See {@link #setAutofillHints(String...)} for more info about these hints.
   8855      *
   8856      * @return The hints set via the attribute or {@link #setAutofillHints(String...)}, or
   8857      * {@code null} if no hints were set.
   8858      *
   8859      * @attr ref android.R.styleable#View_autofillHints
   8860      */
   8861     @ViewDebug.ExportedProperty()
   8862     @InspectableProperty
   8863     @Nullable public String[] getAutofillHints() {
   8864         return mAutofillHints;
   8865     }
   8866 
   8867     /**
   8868      * @hide
   8869      */
   8870     @TestApi
   8871     public boolean isAutofilled() {
   8872         return (mPrivateFlags3 & PFLAG3_IS_AUTOFILLED) != 0;
   8873     }
   8874 
   8875     /**
   8876      * Gets the {@link View}'s current autofill value.
   8877      *
   8878      * <p>By default returns {@code null}, but subclasses should override it and return an
   8879      * appropriate value to properly support the Autofill Framework.
   8880      *
   8881      * @see #onProvideAutofillStructure(ViewStructure, int)
   8882      * @see #autofill(AutofillValue)
   8883      */
   8884     @Nullable
   8885     public AutofillValue getAutofillValue() {
   8886         return null;
   8887     }
   8888 
   8889     /**
   8890      * Gets the mode for determining whether this view is important for autofill.
   8891      *
   8892      * <p>See {@link #setImportantForAutofill(int)} and {@link #isImportantForAutofill()} for more
   8893      * info about this mode.
   8894      *
   8895      * @return {@link #IMPORTANT_FOR_AUTOFILL_AUTO} by default, or value passed to
   8896      * {@link #setImportantForAutofill(int)}.
   8897      *
   8898      * @attr ref android.R.styleable#View_importantForAutofill
   8899      */
   8900     @ViewDebug.ExportedProperty(mapping = {
   8901             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_AUTO, to = "auto"),
   8902             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES, to = "yes"),
   8903             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO, to = "no"),
   8904             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
   8905                 to = "yesExcludeDescendants"),
   8906             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
   8907                 to = "noExcludeDescendants")})
   8908     @InspectableProperty(enumMapping = {
   8909             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_AUTO, name = "auto"),
   8910             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_YES, name = "yes"),
   8911             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_NO, name = "no"),
   8912             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
   8913                     name = "yesExcludeDescendants"),
   8914             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
   8915                     name = "noExcludeDescendants"),
   8916     })
   8917     public @AutofillImportance int getImportantForAutofill() {
   8918         return (mPrivateFlags3
   8919                 & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK) >> PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
   8920     }
   8921 
   8922     /**
   8923      * Sets the mode for determining whether this view is considered important for autofill.
   8924      *
   8925      * <p>The platform determines the importance for autofill automatically but you
   8926      * can use this method to customize the behavior. For example:
   8927      *
   8928      * <ol>
   8929      *   <li>When the view contents is irrelevant for autofill (for example, a text field used in a
   8930      *       "Captcha" challenge), it should be {@link #IMPORTANT_FOR_AUTOFILL_NO}.
   8931      *   <li>When both the view and its children are irrelevant for autofill (for example, the root
   8932      *       view of an activity containing a spreadhseet editor), it should be
   8933      *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
   8934      *   <li>When the view content is relevant for autofill but its children aren't (for example,
   8935      *       a credit card expiration date represented by a custom view that overrides the proper
   8936      *       autofill methods and has 2 children representing the month and year), it should
   8937      *       be {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}.
   8938      * </ol>
   8939      *
   8940      * <p><b>Note:</b> Setting the mode as {@link #IMPORTANT_FOR_AUTOFILL_NO} or
   8941      * {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS} does not guarantee the view (and its
   8942      * children) will be always be considered not important; for example, when the user explicitly
   8943      * makes an autofill request, all views are considered important. See
   8944      * {@link #isImportantForAutofill()} for more details about how the View's importance for
   8945      * autofill is used.
   8946      *
   8947      * @param mode {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, {@link #IMPORTANT_FOR_AUTOFILL_YES},
   8948      * {@link #IMPORTANT_FOR_AUTOFILL_NO}, {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS},
   8949      * or {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
   8950      *
   8951      * @attr ref android.R.styleable#View_importantForAutofill
   8952      */
   8953     public void setImportantForAutofill(@AutofillImportance int mode) {
   8954         mPrivateFlags3 &= ~PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
   8955         mPrivateFlags3 |= (mode << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT)
   8956                 & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
   8957     }
   8958 
   8959     /**
   8960      * Hints the Android System whether the {@link android.app.assist.AssistStructure.ViewNode}
   8961      * associated with this view is considered important for autofill purposes.
   8962      *
   8963      * <p>Generally speaking, a view is important for autofill if:
   8964      * <ol>
   8965      * <li>The view can be autofilled by an {@link android.service.autofill.AutofillService}.
   8966      * <li>The view contents can help an {@link android.service.autofill.AutofillService}
   8967      *     determine how other views can be autofilled.
   8968      * <ol>
   8969      *
   8970      * <p>For example, view containers should typically return {@code false} for performance reasons
   8971      * (since the important info is provided by their children), but if its properties have relevant
   8972      * information (for example, a resource id called {@code credentials}, it should return
   8973      * {@code true}. On the other hand, views representing labels or editable fields should
   8974      * typically return {@code true}, but in some cases they could return {@code false}
   8975      * (for example, if they're part of a "Captcha" mechanism).
   8976      *
   8977      * <p>The value returned by this method depends on the value returned by
   8978      * {@link #getImportantForAutofill()}:
   8979      *
   8980      * <ol>
   8981      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_YES} or
   8982      *       {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}, then it returns {@code true}
   8983      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_NO} or
   8984      *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}, then it returns {@code false}
   8985      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, then it uses some simple heuristics
   8986      *       that can return {@code true} in some cases (like a container with a resource id),
   8987      *       but {@code false} in most.
   8988      *   <li>otherwise, it returns {@code false}.
   8989      * </ol>
   8990      *
   8991      * <p>When a view is considered important for autofill:
   8992      * <ul>
   8993      *   <li>The view might automatically trigger an autofill request when focused on.
   8994      *   <li>The contents of the view are included in the {@link ViewStructure} used in an autofill
   8995      *       request.
   8996      * </ul>
   8997      *
   8998      * <p>On the other hand, when a view is considered not important for autofill:
   8999      * <ul>
   9000      *   <li>The view never automatically triggers autofill requests, but it can trigger a manual
   9001      *       request through {@link AutofillManager#requestAutofill(View)}.
   9002      *   <li>The contents of the view are not included in the {@link ViewStructure} used in an
   9003      *       autofill request, unless the request has the
   9004      *       {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag.
   9005      * </ul>
   9006      *
   9007      * @return whether the view is considered important for autofill.
   9008      *
   9009      * @see #setImportantForAutofill(int)
   9010      * @see #IMPORTANT_FOR_AUTOFILL_AUTO
   9011      * @see #IMPORTANT_FOR_AUTOFILL_YES
   9012      * @see #IMPORTANT_FOR_AUTOFILL_NO
   9013      * @see #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
   9014      * @see #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
   9015      * @see AutofillManager#requestAutofill(View)
   9016      */
   9017     public final boolean isImportantForAutofill() {
   9018         // Check parent mode to ensure we're not hidden.
   9019         ViewParent parent = mParent;
   9020         while (parent instanceof View) {
   9021             final int parentImportance = ((View) parent).getImportantForAutofill();
   9022             if (parentImportance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
   9023                     || parentImportance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS) {
   9024                 if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
   9025                     Log.v(AUTOFILL_LOG_TAG, "View (" +  this + ") is not important for autofill "
   9026                             + "because parent " + parent + "'s importance is " + parentImportance);
   9027                 }
   9028                 return false;
   9029             }
   9030             parent = parent.getParent();
   9031         }
   9032 
   9033         final int importance = getImportantForAutofill();
   9034 
   9035         // First, check the explicit states.
   9036         if (importance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
   9037                 || importance == IMPORTANT_FOR_AUTOFILL_YES) {
   9038             return true;
   9039         }
   9040         if (importance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
   9041                 || importance == IMPORTANT_FOR_AUTOFILL_NO) {
   9042             if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
   9043                 Log.v(AUTOFILL_LOG_TAG, "View (" +  this + ") is not important for autofill "
   9044                         + "because its importance is " + importance);
   9045             }
   9046             return false;
   9047         }
   9048 
   9049         // Then use some heuristics to handle AUTO.
   9050         if (importance != IMPORTANT_FOR_AUTOFILL_AUTO) {
   9051             Log.w(AUTOFILL_LOG_TAG, "invalid autofill importance (" + importance + " on view "
   9052                     + this);
   9053             return false;
   9054         }
   9055 
   9056         // Always include views that have an explicit resource id.
   9057         final int id = mID;
   9058         if (id != NO_ID && !isViewIdGenerated(id)) {
   9059             final Resources res = getResources();
   9060             String entry = null;
   9061             String pkg = null;
   9062             try {
   9063                 entry = res.getResourceEntryName(id);
   9064                 pkg = res.getResourcePackageName(id);
   9065             } catch (Resources.NotFoundException e) {
   9066                 // ignore
   9067             }
   9068             if (entry != null && pkg != null && pkg.equals(mContext.getPackageName())) {
   9069                 return true;
   9070             }
   9071         }
   9072 
   9073         // If the app developer explicitly set hints for it, it's important.
   9074         if (getAutofillHints() != null) {
   9075             return true;
   9076         }
   9077 
   9078         // Otherwise, assume it's not important...
   9079         return false;
   9080     }
   9081 
   9082     /**
   9083      * Sets the (optional) {@link ContentCaptureSession} associated with this view.
   9084      *
   9085      * <p>This method should be called when you need to associate a {@link ContentCaptureContext} to
   9086      * the content capture events associated with this view or its view hierarchy (if it's a
   9087      * {@link ViewGroup}).
   9088      *
   9089      * <p>For example, if your activity is associated with a web domain, first you would need to
   9090      * set the context for the main DOM:
   9091      *
   9092      * <pre>
   9093      *   ContentCaptureSession mainSession = rootView.getContentCaptureSession();
   9094      *   mainSession.setContentCaptureContext(ContentCaptureContext.forLocusId(Uri.parse(myUrl));
   9095      * </pre>
   9096      *
   9097      * <p>Then if the page had an {@code IFRAME}, you would create a new session for it:
   9098      *
   9099      * <pre>
   9100      *   ContentCaptureSession iframeSession = mainSession.createContentCaptureSession(
   9101      *       ContentCaptureContext.forLocusId(Uri.parse(iframeUrl)));
   9102      *   iframeView.setContentCaptureSession(iframeSession);
   9103      * </pre>
   9104      *
   9105      * @param contentCaptureSession a session created by
   9106      * {@link ContentCaptureSession#createContentCaptureSession(
   9107      *        android.view.contentcapture.ContentCaptureContext)}.
   9108      */
   9109     public void setContentCaptureSession(@Nullable ContentCaptureSession contentCaptureSession) {
   9110         mContentCaptureSession = contentCaptureSession;
   9111     }
   9112 
   9113     /**
   9114      * Gets the session used to notify content capture events.
   9115      *
   9116      * @return session explicitly set by {@link #setContentCaptureSession(ContentCaptureSession)},
   9117      * inherited by ancestors, default session or {@code null} if content capture is disabled for
   9118      * this view.
   9119      */
   9120     @Nullable
   9121     public final ContentCaptureSession getContentCaptureSession() {
   9122         if (mCachedContentCaptureSession != null) {
   9123             return mCachedContentCaptureSession;
   9124         }
   9125 
   9126         mCachedContentCaptureSession = getAndCacheContentCaptureSession();
   9127         return mCachedContentCaptureSession;
   9128     }
   9129 
   9130     @Nullable
   9131     private ContentCaptureSession getAndCacheContentCaptureSession() {
   9132         // First try the session explicitly set by setContentCaptureSession()
   9133         if (mContentCaptureSession != null) return mContentCaptureSession;
   9134 
   9135         // Then the session explicitly set in an ancestor
   9136         ContentCaptureSession session = null;
   9137         if (mParent instanceof View) {
   9138             session = ((View) mParent).getContentCaptureSession();
   9139         }
   9140 
   9141         // Finally, if no session was explicitly set, use the context's default session.
   9142         if (session == null) {
   9143             final ContentCaptureManager ccm = mContext
   9144                     .getSystemService(ContentCaptureManager.class);
   9145             return ccm == null ? null : ccm.getMainContentCaptureSession();
   9146         }
   9147         return session;
   9148     }
   9149 
   9150     @Nullable
   9151     private AutofillManager getAutofillManager() {
   9152         return mContext.getSystemService(AutofillManager.class);
   9153     }
   9154 
   9155     private boolean isAutofillable() {
   9156         if (getAutofillType() == AUTOFILL_TYPE_NONE) return false;
   9157 
   9158         if (!isImportantForAutofill()) {
   9159             // View is not important for "regular" autofill, so we must check if Augmented Autofill
   9160             // is enabled for the activity
   9161             final AutofillOptions options = mContext.getAutofillOptions();
   9162             if (options == null || !options.isAugmentedAutofillEnabled(mContext)) {
   9163                 return false;
   9164             }
   9165             final AutofillManager afm = getAutofillManager();
   9166             if (afm == null) return false;
   9167             afm.notifyViewEnteredForAugmentedAutofill(this);
   9168         }
   9169 
   9170         return getAutofillViewId() > LAST_APP_AUTOFILL_ID;
   9171     }
   9172 
   9173     /** @hide */
   9174     public boolean canNotifyAutofillEnterExitEvent() {
   9175         return isAutofillable() && isAttachedToWindow();
   9176     }
   9177 
   9178     private void populateVirtualStructure(ViewStructure structure,
   9179             AccessibilityNodeProvider provider, AccessibilityNodeInfo info,
   9180             boolean forAutofill) {
   9181         structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
   9182                 null, null, info.getViewIdResourceName());
   9183         Rect rect = structure.getTempRect();
   9184         info.getBoundsInParent(rect);
   9185         structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
   9186         structure.setVisibility(VISIBLE);
   9187         structure.setEnabled(info.isEnabled());
   9188         if (info.isClickable()) {
   9189             structure.setClickable(true);
   9190         }
   9191         if (info.isFocusable()) {
   9192             structure.setFocusable(true);
   9193         }
   9194         if (info.isFocused()) {
   9195             structure.setFocused(true);
   9196         }
   9197         if (info.isAccessibilityFocused()) {
   9198             structure.setAccessibilityFocused(true);
   9199         }
   9200         if (info.isSelected()) {
   9201             structure.setSelected(true);
   9202         }
   9203         if (info.isLongClickable()) {
   9204             structure.setLongClickable(true);
   9205         }
   9206         if (info.isCheckable()) {
   9207             structure.setCheckable(true);
   9208             if (info.isChecked()) {
   9209                 structure.setChecked(true);
   9210             }
   9211         }
   9212         if (info.isContextClickable()) {
   9213             structure.setContextClickable(true);
   9214         }
   9215         if (forAutofill) {
   9216             structure.setAutofillId(new AutofillId(getAutofillId(),
   9217                     AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId())));
   9218         }
   9219         CharSequence cname = info.getClassName();
   9220         structure.setClassName(cname != null ? cname.toString() : null);
   9221         structure.setContentDescription(info.getContentDescription());
   9222         if (forAutofill) {
   9223             final int maxTextLength = info.getMaxTextLength();
   9224             if (maxTextLength != -1) {
   9225                 structure.setMaxTextLength(maxTextLength);
   9226             }
   9227             structure.setHint(info.getHintText());
   9228         }
   9229         CharSequence text = info.getText();
   9230         boolean hasText = text != null || info.getError() != null;
   9231         if (hasText) {
   9232             structure.setText(text, info.getTextSelectionStart(), info.getTextSelectionEnd());
   9233         }
   9234         if (forAutofill) {
   9235             if (info.isEditable()) {
   9236                 structure.setDataIsSensitive(true);
   9237                 if (hasText) {
   9238                     structure.setAutofillType(AUTOFILL_TYPE_TEXT);
   9239                     structure.setAutofillValue(AutofillValue.forText(text));
   9240                 }
   9241                 int inputType = info.getInputType();
   9242                 if (inputType == 0 && info.isPassword()) {
   9243                     inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD;
   9244                 }
   9245                 structure.setInputType(inputType);
   9246             } else {
   9247                 structure.setDataIsSensitive(false);
   9248             }
   9249         }
   9250         final int NCHILDREN = info.getChildCount();
   9251         if (NCHILDREN > 0) {
   9252             structure.setChildCount(NCHILDREN);
   9253             for (int i=0; i<NCHILDREN; i++) {
   9254                 if (AccessibilityNodeInfo.getVirtualDescendantId(info.getChildNodeIds().get(i))
   9255                         == AccessibilityNodeProvider.HOST_VIEW_ID) {
   9256                     Log.e(VIEW_LOG_TAG, "Virtual view pointing to its host. Ignoring");
   9257                     continue;
   9258                 }
   9259                 AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
   9260                         AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
   9261                 ViewStructure child = structure.newChild(i);
   9262                 populateVirtualStructure(child, provider, cinfo, forAutofill);
   9263                 cinfo.recycle();
   9264             }
   9265         }
   9266     }
   9267 
   9268     /**
   9269      * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
   9270      * implementation calls {@link #onProvideStructure} and
   9271      * {@link #onProvideVirtualStructure}.
   9272      */
   9273     public void dispatchProvideStructure(ViewStructure structure) {
   9274         dispatchProvideStructure(structure, VIEW_STRUCTURE_FOR_ASSIST, /* flags= */ 0);
   9275     }
   9276 
   9277     /**
   9278      * Dispatches creation of a {@link ViewStructure}s for autofill purposes down the hierarchy,
   9279      * when an Assist structure is being created as part of an autofill request.
   9280      *
   9281      * <p>The default implementation does the following:
   9282      * <ul>
   9283      *   <li>Sets the {@link AutofillId} in the structure.
   9284      *   <li>Calls {@link #onProvideAutofillStructure(ViewStructure, int)}.
   9285      *   <li>Calls {@link #onProvideAutofillVirtualStructure(ViewStructure, int)}.
   9286      * </ul>
   9287      *
   9288      * <p>Typically, this method should only be overridden by subclasses that provide a view
   9289      * hierarchy (such as {@link ViewGroup}) - other classes should override
   9290      * {@link #onProvideAutofillStructure(ViewStructure, int)} or
   9291      * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} instead.
   9292      *
   9293      * <p>When overridden, it must:
   9294      *
   9295      * <ul>
   9296      *   <li>Either call
   9297      *       {@code super.dispatchProvideAutofillStructure(structure, flags)} or explicitly
   9298      *       set the {@link AutofillId} in the structure (for example, by calling
   9299      *       {@code structure.setAutofillId(getAutofillId())}).
   9300      *   <li>Decide how to handle the {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag - when
   9301      *       set, all views in the structure should be considered important for autofill,
   9302      *       regardless of what {@link #isImportantForAutofill()} returns. We encourage you to
   9303      *       respect this flag to provide a better user experience - this flag is typically used
   9304      *       when an user explicitly requested autofill. If the flag is not set,
   9305      *       then only views marked as important for autofill should be included in the
   9306      *       structure - skipping non-important views optimizes the overall autofill performance.
   9307      * </ul>
   9308      *
   9309      * @param structure fill in with structured view data for autofill purposes.
   9310      * @param flags optional flags.
   9311      *
   9312      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
   9313      */
   9314     public void dispatchProvideAutofillStructure(@NonNull ViewStructure structure,
   9315             @AutofillFlags int flags) {
   9316         dispatchProvideStructure(structure, VIEW_STRUCTURE_FOR_AUTOFILL, flags);
   9317     }
   9318 
   9319     private void dispatchProvideStructure(@NonNull ViewStructure structure,
   9320             @ViewStructureType int viewFor, @AutofillFlags int flags) {
   9321         if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
   9322             structure.setAutofillId(getAutofillId());
   9323             onProvideAutofillStructure(structure, flags);
   9324             onProvideAutofillVirtualStructure(structure, flags);
   9325         } else if (!isAssistBlocked()) {
   9326             onProvideStructure(structure);
   9327             onProvideVirtualStructure(structure);
   9328         } else {
   9329             structure.setClassName(getAccessibilityClassName().toString());
   9330             structure.setAssistBlocked(true);
   9331         }
   9332     }
   9333 
   9334     /**
   9335      * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
   9336      *
   9337      * Note: Called from the default {@link AccessibilityDelegate}.
   9338      *
   9339      * @hide
   9340      */
   9341     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
   9342         if (mAttachInfo == null) {
   9343             return;
   9344         }
   9345 
   9346         Rect bounds = mAttachInfo.mTmpInvalRect;
   9347 
   9348         getDrawingRect(bounds);
   9349         info.setBoundsInParent(bounds);
   9350 
   9351         getBoundsOnScreen(bounds, true);
   9352         info.setBoundsInScreen(bounds);
   9353 
   9354         ViewParent parent = getParentForAccessibility();
   9355         if (parent instanceof View) {
   9356             info.setParent((View) parent);
   9357         }
   9358 
   9359         if (mID != View.NO_ID) {
   9360             View rootView = getRootView();
   9361             if (rootView == null) {
   9362                 rootView = this;
   9363             }
   9364 
   9365             View label = rootView.findLabelForView(this, mID);
   9366             if (label != null) {
   9367                 info.setLabeledBy(label);
   9368             }
   9369 
   9370             if ((mAttachInfo.mAccessibilityFetchFlags
   9371                     & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
   9372                     && Resources.resourceHasPackage(mID)) {
   9373                 try {
   9374                     String viewId = getResources().getResourceName(mID);
   9375                     info.setViewIdResourceName(viewId);
   9376                 } catch (Resources.NotFoundException nfe) {
   9377                     /* ignore */
   9378                 }
   9379             }
   9380         }
   9381 
   9382         if (mLabelForId != View.NO_ID) {
   9383             View rootView = getRootView();
   9384             if (rootView == null) {
   9385                 rootView = this;
   9386             }
   9387             View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
   9388             if (labeled != null) {
   9389                 info.setLabelFor(labeled);
   9390             }
   9391         }
   9392 
   9393         if (mAccessibilityTraversalBeforeId != View.NO_ID) {
   9394             View rootView = getRootView();
   9395             if (rootView == null) {
   9396                 rootView = this;
   9397             }
   9398             View next = rootView.findViewInsideOutShouldExist(this,
   9399                     mAccessibilityTraversalBeforeId);
   9400             if (next != null && next.includeForAccessibility()) {
   9401                 info.setTraversalBefore(next);
   9402             }
   9403         }
   9404 
   9405         if (mAccessibilityTraversalAfterId != View.NO_ID) {
   9406             View rootView = getRootView();
   9407             if (rootView == null) {
   9408                 rootView = this;
   9409             }
   9410             View next = rootView.findViewInsideOutShouldExist(this,
   9411                     mAccessibilityTraversalAfterId);
   9412             if (next != null && next.includeForAccessibility()) {
   9413                 info.setTraversalAfter(next);
   9414             }
   9415         }
   9416 
   9417         info.setVisibleToUser(isVisibleToUser());
   9418 
   9419         info.setImportantForAccessibility(isImportantForAccessibility());
   9420         info.setPackageName(mContext.getPackageName());
   9421         info.setClassName(getAccessibilityClassName());
   9422         info.setContentDescription(getContentDescription());
   9423 
   9424         info.setEnabled(isEnabled());
   9425         info.setClickable(isClickable());
   9426         info.setFocusable(isFocusable());
   9427         info.setScreenReaderFocusable(isScreenReaderFocusable());
   9428         info.setFocused(isFocused());
   9429         info.setAccessibilityFocused(isAccessibilityFocused());
   9430         info.setSelected(isSelected());
   9431         info.setLongClickable(isLongClickable());
   9432         info.setContextClickable(isContextClickable());
   9433         info.setLiveRegion(getAccessibilityLiveRegion());
   9434         if ((mTooltipInfo != null) && (mTooltipInfo.mTooltipText != null)) {
   9435             info.setTooltipText(mTooltipInfo.mTooltipText);
   9436             info.addAction((mTooltipInfo.mTooltipPopup == null)
   9437                     ? AccessibilityNodeInfo.AccessibilityAction.ACTION_SHOW_TOOLTIP
   9438                     : AccessibilityNodeInfo.AccessibilityAction.ACTION_HIDE_TOOLTIP);
   9439         }
   9440 
   9441         // TODO: These make sense only if we are in an AdapterView but all
   9442         // views can be selected. Maybe from accessibility perspective
   9443         // we should report as selectable view in an AdapterView.
   9444         info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
   9445         info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
   9446 
   9447         if (isFocusable()) {
   9448             if (isFocused()) {
   9449                 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
   9450             } else {
   9451                 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
   9452             }
   9453         }
   9454 
   9455         if (!isAccessibilityFocused()) {
   9456             info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
   9457         } else {
   9458             info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
   9459         }
   9460 
   9461         if (isClickable() && isEnabled()) {
   9462             info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
   9463         }
   9464 
   9465         if (isLongClickable() && isEnabled()) {
   9466             info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
   9467         }
   9468 
   9469         if (isContextClickable() && isEnabled()) {
   9470             info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
   9471         }
   9472 
   9473         CharSequence text = getIterableTextForAccessibility();
   9474         if (text != null && text.length() > 0) {
   9475             info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
   9476 
   9477             info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
   9478             info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
   9479             info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
   9480             info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
   9481                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
   9482                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
   9483         }
   9484 
   9485         info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
   9486         populateAccessibilityNodeInfoDrawingOrderInParent(info);
   9487         info.setPaneTitle(mAccessibilityPaneTitle);
   9488         info.setHeading(isAccessibilityHeading());
   9489 
   9490         if (mTouchDelegate != null) {
   9491             info.setTouchDelegateInfo(mTouchDelegate.getTouchDelegateInfo());
   9492         }
   9493     }
   9494 
   9495     /**
   9496      * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
   9497      * additional data.
   9498      * <p>
   9499      * This method only needs overloading if the node is marked as having extra data available.
   9500      * </p>
   9501      *
   9502      * @param info The info to which to add the extra data. Never {@code null}.
   9503      * @param extraDataKey A key specifying the type of extra data to add to the info. The
   9504      *                     extra data should be added to the {@link Bundle} returned by
   9505      *                     the info's {@link AccessibilityNodeInfo#getExtras} method. Never
   9506      *                     {@code null}.
   9507      * @param arguments A {@link Bundle} holding any arguments relevant for this request. May be
   9508      *                  {@code null} if the service provided no arguments.
   9509      *
   9510      * @see AccessibilityNodeInfo#setAvailableExtraData(List)
   9511      */
   9512     public void addExtraDataToAccessibilityNodeInfo(
   9513             @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
   9514             @Nullable Bundle arguments) {
   9515     }
   9516 
   9517     /**
   9518      * Determine the order in which this view will be drawn relative to its siblings for a11y
   9519      *
   9520      * @param info The info whose drawing order should be populated
   9521      */
   9522     private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
   9523         /*
   9524          * If the view's bounds haven't been set yet, layout has not completed. In that situation,
   9525          * drawing order may not be well-defined, and some Views with custom drawing order may
   9526          * not be initialized sufficiently to respond properly getChildDrawingOrder.
   9527          */
   9528         if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
   9529             info.setDrawingOrder(0);
   9530             return;
   9531         }
   9532         int drawingOrderInParent = 1;
   9533         // Iterate up the hierarchy if parents are not important for a11y
   9534         View viewAtDrawingLevel = this;
   9535         final ViewParent parent = getParentForAccessibility();
   9536         while (viewAtDrawingLevel != parent) {
   9537             final ViewParent currentParent = viewAtDrawingLevel.getParent();
   9538             if (!(currentParent instanceof ViewGroup)) {
   9539                 // Should only happen for the Decor
   9540                 drawingOrderInParent = 0;
   9541                 break;
   9542             } else {
   9543                 final ViewGroup parentGroup = (ViewGroup) currentParent;
   9544                 final int childCount = parentGroup.getChildCount();
   9545                 if (childCount > 1) {
   9546                     List<View> preorderedList = parentGroup.buildOrderedChildList();
   9547                     if (preorderedList != null) {
   9548                         final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
   9549                         for (int i = 0; i < childDrawIndex; i++) {
   9550                             drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
   9551                         }
   9552                     } else {
   9553                         final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
   9554                         final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
   9555                         final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
   9556                                 .getChildDrawingOrder(childCount, childIndex) : childIndex;
   9557                         final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
   9558                         if (childDrawIndex != 0) {
   9559                             for (int i = 0; i < numChildrenToIterate; i++) {
   9560                                 final int otherDrawIndex = (customOrder ?
   9561                                         parentGroup.getChildDrawingOrder(childCount, i) : i);
   9562                                 if (otherDrawIndex < childDrawIndex) {
   9563                                     drawingOrderInParent +=
   9564                                             numViewsForAccessibility(parentGroup.getChildAt(i));
   9565                                 }
   9566                             }
   9567                         }
   9568                     }
   9569                 }
   9570             }
   9571             viewAtDrawingLevel = (View) currentParent;
   9572         }
   9573         info.setDrawingOrder(drawingOrderInParent);
   9574     }
   9575 
   9576     private static int numViewsForAccessibility(View view) {
   9577         if (view != null) {
   9578             if (view.includeForAccessibility()) {
   9579                 return 1;
   9580             } else if (view instanceof ViewGroup) {
   9581                 return ((ViewGroup) view).getNumChildrenForAccessibility();
   9582             }
   9583         }
   9584         return 0;
   9585     }
   9586 
   9587     private View findLabelForView(View view, int labeledId) {
   9588         if (mMatchLabelForPredicate == null) {
   9589             mMatchLabelForPredicate = new MatchLabelForPredicate();
   9590         }
   9591         mMatchLabelForPredicate.mLabeledId = labeledId;
   9592         return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
   9593     }
   9594 
   9595     /**
   9596      * Computes whether this virtual autofill view is visible to the user.
   9597      *
   9598      * <p><b>Note: </b>By default it returns {@code true}, but views providing a virtual hierarchy
   9599      * view must override it.
   9600      *
   9601      * @return Whether the view is visible on the screen.
   9602      */
   9603     public boolean isVisibleToUserForAutofill(int virtualId) {
   9604         if (mContext.isAutofillCompatibilityEnabled()) {
   9605             final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
   9606             if (provider != null) {
   9607                 final AccessibilityNodeInfo node = provider.createAccessibilityNodeInfo(virtualId);
   9608                 if (node != null) {
   9609                     return node.isVisibleToUser();
   9610                 }
   9611                 // if node is null, assume it's not visible anymore
   9612             } else {
   9613                 Log.w(VIEW_LOG_TAG, "isVisibleToUserForAutofill(" + virtualId + "): no provider");
   9614             }
   9615             return false;
   9616         }
   9617         return true;
   9618     }
   9619 
   9620     /**
   9621      * Computes whether this view is visible to the user. Such a view is
   9622      * attached, visible, all its predecessors are visible, it is not clipped
   9623      * entirely by its predecessors, and has an alpha greater than zero.
   9624      *
   9625      * @return Whether the view is visible on the screen.
   9626      *
   9627      * @hide
   9628      */
   9629     @UnsupportedAppUsage
   9630     public boolean isVisibleToUser() {
   9631         return isVisibleToUser(null);
   9632     }
   9633 
   9634     /**
   9635      * Computes whether the given portion of this view is visible to the user.
   9636      * Such a view is attached, visible, all its predecessors are visible,
   9637      * has an alpha greater than zero, and the specified portion is not
   9638      * clipped entirely by its predecessors.
   9639      *
   9640      * @param boundInView the portion of the view to test; coordinates should be relative; may be
   9641      *                    <code>null</code>, and the entire view will be tested in this case.
   9642      *                    When <code>true</code> is returned by the function, the actual visible
   9643      *                    region will be stored in this parameter; that is, if boundInView is fully
   9644      *                    contained within the view, no modification will be made, otherwise regions
   9645      *                    outside of the visible area of the view will be clipped.
   9646      *
   9647      * @return Whether the specified portion of the view is visible on the screen.
   9648      *
   9649      * @hide
   9650      */
   9651     @UnsupportedAppUsage
   9652     protected boolean isVisibleToUser(Rect boundInView) {
   9653         if (mAttachInfo != null) {
   9654             // Attached to invisible window means this view is not visible.
   9655             if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
   9656                 return false;
   9657             }
   9658             // An invisible predecessor or one with alpha zero means
   9659             // that this view is not visible to the user.
   9660             Object current = this;
   9661             while (current instanceof View) {
   9662                 View view = (View) current;
   9663                 // We have attach info so this view is attached and there is no
   9664                 // need to check whether we reach to ViewRootImpl on the way up.
   9665                 if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
   9666                         view.getVisibility() != VISIBLE) {
   9667                     return false;
   9668                 }
   9669                 current = view.mParent;
   9670             }
   9671             // Check if the view is entirely covered by its predecessors.
   9672             Rect visibleRect = mAttachInfo.mTmpInvalRect;
   9673             Point offset = mAttachInfo.mPoint;
   9674             if (!getGlobalVisibleRect(visibleRect, offset)) {
   9675                 return false;
   9676             }
   9677             // Check if the visible portion intersects the rectangle of interest.
   9678             if (boundInView != null) {
   9679                 visibleRect.offset(-offset.x, -offset.y);
   9680                 return boundInView.intersect(visibleRect);
   9681             }
   9682             return true;
   9683         }
   9684         return false;
   9685     }
   9686 
   9687     /**
   9688      * Returns the delegate for implementing accessibility support via
   9689      * composition. For more details see {@link AccessibilityDelegate}.
   9690      *
   9691      * @return The delegate, or null if none set.
   9692      */
   9693     public AccessibilityDelegate getAccessibilityDelegate() {
   9694         return mAccessibilityDelegate;
   9695     }
   9696 
   9697     /**
   9698      * Sets a delegate for implementing accessibility support via composition
   9699      * (as opposed to inheritance). For more details, see
   9700      * {@link AccessibilityDelegate}.
   9701      * <p>
   9702      * <strong>Note:</strong> On platform versions prior to
   9703      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
   9704      * views in the {@code android.widget.*} package are called <i>before</i>
   9705      * host methods. This prevents certain properties such as class name from
   9706      * being modified by overriding
   9707      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
   9708      * as any changes will be overwritten by the host class.
   9709      * <p>
   9710      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
   9711      * methods are called <i>after</i> host methods, which all properties to be
   9712      * modified without being overwritten by the host class.
   9713      *
   9714      * @param delegate the object to which accessibility method calls should be
   9715      *                 delegated
   9716      * @see AccessibilityDelegate
   9717      */
   9718     public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
   9719         mAccessibilityDelegate = delegate;
   9720     }
   9721 
   9722     /**
   9723      * Gets the provider for managing a virtual view hierarchy rooted at this View
   9724      * and reported to {@link android.accessibilityservice.AccessibilityService}s
   9725      * that explore the window content.
   9726      * <p>
   9727      * If this method returns an instance, this instance is responsible for managing
   9728      * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
   9729      * View including the one representing the View itself. Similarly the returned
   9730      * instance is responsible for performing accessibility actions on any virtual
   9731      * view or the root view itself.
   9732      * </p>
   9733      * <p>
   9734      * If an {@link AccessibilityDelegate} has been specified via calling
   9735      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   9736      * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
   9737      * is responsible for handling this call.
   9738      * </p>
   9739      *
   9740      * @return The provider.
   9741      *
   9742      * @see AccessibilityNodeProvider
   9743      */
   9744     public AccessibilityNodeProvider getAccessibilityNodeProvider() {
   9745         if (mAccessibilityDelegate != null) {
   9746             return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
   9747         } else {
   9748             return null;
   9749         }
   9750     }
   9751 
   9752     /**
   9753      * Gets the unique identifier of this view on the screen for accessibility purposes.
   9754      *
   9755      * @return The view accessibility id.
   9756      *
   9757      * @hide
   9758      */
   9759     @UnsupportedAppUsage
   9760     public int getAccessibilityViewId() {
   9761         if (mAccessibilityViewId == NO_ID) {
   9762             mAccessibilityViewId = sNextAccessibilityViewId++;
   9763         }
   9764         return mAccessibilityViewId;
   9765     }
   9766 
   9767     /**
   9768      * Gets the unique identifier of this view on the screen for autofill purposes.
   9769      *
   9770      * @return The view autofill id.
   9771      *
   9772      * @hide
   9773      */
   9774     public int getAutofillViewId() {
   9775         if (mAutofillViewId == NO_ID) {
   9776             mAutofillViewId = mContext.getNextAutofillId();
   9777         }
   9778         return mAutofillViewId;
   9779     }
   9780 
   9781     /**
   9782      * Gets the unique identifier of the window in which this View reseides.
   9783      *
   9784      * @return The window accessibility id.
   9785      *
   9786      * @hide
   9787      */
   9788     public int getAccessibilityWindowId() {
   9789         return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
   9790                 : AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
   9791     }
   9792 
   9793     /**
   9794      * Returns the {@link View}'s content description.
   9795      * <p>
   9796      * <strong>Note:</strong> Do not override this method, as it will have no
   9797      * effect on the content description presented to accessibility services.
   9798      * You must call {@link #setContentDescription(CharSequence)} to modify the
   9799      * content description.
   9800      *
   9801      * @return the content description
   9802      * @see #setContentDescription(CharSequence)
   9803      * @attr ref android.R.styleable#View_contentDescription
   9804      */
   9805     @ViewDebug.ExportedProperty(category = "accessibility")
   9806     @InspectableProperty
   9807     public CharSequence getContentDescription() {
   9808         return mContentDescription;
   9809     }
   9810 
   9811     /**
   9812      * Sets the {@link View}'s content description.
   9813      * <p>
   9814      * A content description briefly describes the view and is primarily used
   9815      * for accessibility support to determine how a view should be presented to
   9816      * the user. In the case of a view with no textual representation, such as
   9817      * {@link android.widget.ImageButton}, a useful content description
   9818      * explains what the view does. For example, an image button with a phone
   9819      * icon that is used to place a call may use "Call" as its content
   9820      * description. An image of a floppy disk that is used to save a file may
   9821      * use "Save".
   9822      *
   9823      * @param contentDescription The content description.
   9824      * @see #getContentDescription()
   9825      * @attr ref android.R.styleable#View_contentDescription
   9826      */
   9827     @RemotableViewMethod
   9828     public void setContentDescription(CharSequence contentDescription) {
   9829         if (mContentDescription == null) {
   9830             if (contentDescription == null) {
   9831                 return;
   9832             }
   9833         } else if (mContentDescription.equals(contentDescription)) {
   9834             return;
   9835         }
   9836         mContentDescription = contentDescription;
   9837         final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
   9838         if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
   9839             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
   9840             notifySubtreeAccessibilityStateChangedIfNeeded();
   9841         } else {
   9842             notifyViewAccessibilityStateChangedIfNeeded(
   9843                     AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
   9844         }
   9845     }
   9846 
   9847     /**
   9848      * Sets the id of a view before which this one is visited in accessibility traversal.
   9849      * A screen-reader must visit the content of this view before the content of the one
   9850      * it precedes. For example, if view B is set to be before view A, then a screen-reader
   9851      * will traverse the entire content of B before traversing the entire content of A,
   9852      * regardles of what traversal strategy it is using.
   9853      * <p>
   9854      * Views that do not have specified before/after relationships are traversed in order
   9855      * determined by the screen-reader.
   9856      * </p>
   9857      * <p>
   9858      * Setting that this view is before a view that is not important for accessibility
   9859      * or if this view is not important for accessibility will have no effect as the
   9860      * screen-reader is not aware of unimportant views.
   9861      * </p>
   9862      *
   9863      * @param beforeId The id of a view this one precedes in accessibility traversal.
   9864      *
   9865      * @attr ref android.R.styleable#View_accessibilityTraversalBefore
   9866      *
   9867      * @see #setImportantForAccessibility(int)
   9868      */
   9869     @RemotableViewMethod
   9870     public void setAccessibilityTraversalBefore(@IdRes int beforeId) {
   9871         if (mAccessibilityTraversalBeforeId == beforeId) {
   9872             return;
   9873         }
   9874         mAccessibilityTraversalBeforeId = beforeId;
   9875         notifyViewAccessibilityStateChangedIfNeeded(
   9876                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   9877     }
   9878 
   9879     /**
   9880      * Gets the id of a view before which this one is visited in accessibility traversal.
   9881      *
   9882      * @return The id of a view this one precedes in accessibility traversal if
   9883      *         specified, otherwise {@link #NO_ID}.
   9884      *
   9885      * @see #setAccessibilityTraversalBefore(int)
   9886      */
   9887     @IdRes
   9888     @InspectableProperty
   9889     public int getAccessibilityTraversalBefore() {
   9890         return mAccessibilityTraversalBeforeId;
   9891     }
   9892 
   9893     /**
   9894      * Sets the id of a view after which this one is visited in accessibility traversal.
   9895      * A screen-reader must visit the content of the other view before the content of this
   9896      * one. For example, if view B is set to be after view A, then a screen-reader
   9897      * will traverse the entire content of A before traversing the entire content of B,
   9898      * regardles of what traversal strategy it is using.
   9899      * <p>
   9900      * Views that do not have specified before/after relationships are traversed in order
   9901      * determined by the screen-reader.
   9902      * </p>
   9903      * <p>
   9904      * Setting that this view is after a view that is not important for accessibility
   9905      * or if this view is not important for accessibility will have no effect as the
   9906      * screen-reader is not aware of unimportant views.
   9907      * </p>
   9908      *
   9909      * @param afterId The id of a view this one succedees in accessibility traversal.
   9910      *
   9911      * @attr ref android.R.styleable#View_accessibilityTraversalAfter
   9912      *
   9913      * @see #setImportantForAccessibility(int)
   9914      */
   9915     @RemotableViewMethod
   9916     public void setAccessibilityTraversalAfter(@IdRes int afterId) {
   9917         if (mAccessibilityTraversalAfterId == afterId) {
   9918             return;
   9919         }
   9920         mAccessibilityTraversalAfterId = afterId;
   9921         notifyViewAccessibilityStateChangedIfNeeded(
   9922                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   9923     }
   9924 
   9925     /**
   9926      * Gets the id of a view after which this one is visited in accessibility traversal.
   9927      *
   9928      * @return The id of a view this one succeedes in accessibility traversal if
   9929      *         specified, otherwise {@link #NO_ID}.
   9930      *
   9931      * @see #setAccessibilityTraversalAfter(int)
   9932      */
   9933     @IdRes
   9934     @InspectableProperty
   9935     public int getAccessibilityTraversalAfter() {
   9936         return mAccessibilityTraversalAfterId;
   9937     }
   9938 
   9939     /**
   9940      * Gets the id of a view for which this view serves as a label for
   9941      * accessibility purposes.
   9942      *
   9943      * @return The labeled view id.
   9944      */
   9945     @IdRes
   9946     @ViewDebug.ExportedProperty(category = "accessibility")
   9947     @InspectableProperty
   9948     public int getLabelFor() {
   9949         return mLabelForId;
   9950     }
   9951 
   9952     /**
   9953      * Sets the id of a view for which this view serves as a label for
   9954      * accessibility purposes.
   9955      *
   9956      * @param id The labeled view id.
   9957      */
   9958     @RemotableViewMethod
   9959     public void setLabelFor(@IdRes int id) {
   9960         if (mLabelForId == id) {
   9961             return;
   9962         }
   9963         mLabelForId = id;
   9964         if (mLabelForId != View.NO_ID
   9965                 && mID == View.NO_ID) {
   9966             mID = generateViewId();
   9967         }
   9968         notifyViewAccessibilityStateChangedIfNeeded(
   9969                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   9970     }
   9971 
   9972     /**
   9973      * Invoked whenever this view loses focus, either by losing window focus or by losing
   9974      * focus within its window. This method can be used to clear any state tied to the
   9975      * focus. For instance, if a button is held pressed with the trackball and the window
   9976      * loses focus, this method can be used to cancel the press.
   9977      *
   9978      * Subclasses of View overriding this method should always call super.onFocusLost().
   9979      *
   9980      * @see #onFocusChanged(boolean, int, android.graphics.Rect)
   9981      * @see #onWindowFocusChanged(boolean)
   9982      *
   9983      * @hide pending API council approval
   9984      */
   9985     @CallSuper
   9986     @UnsupportedAppUsage
   9987     protected void onFocusLost() {
   9988         resetPressedState();
   9989     }
   9990 
   9991     private void resetPressedState() {
   9992         if ((mViewFlags & ENABLED_MASK) == DISABLED) {
   9993             return;
   9994         }
   9995 
   9996         if (isPressed()) {
   9997             setPressed(false);
   9998 
   9999             if (!mHasPerformedLongPress) {
   10000                 removeLongPressCallback();
   10001             }
   10002         }
   10003     }
   10004 
   10005     /**
   10006      * Returns true if this view has focus
   10007      *
   10008      * @return True if this view has focus, false otherwise.
   10009      */
   10010     @ViewDebug.ExportedProperty(category = "focus")
   10011     @InspectableProperty(hasAttributeId = false)
   10012     public boolean isFocused() {
   10013         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
   10014     }
   10015 
   10016     /**
   10017      * Find the view in the hierarchy rooted at this view that currently has
   10018      * focus.
   10019      *
   10020      * @return The view that currently has focus, or null if no focused view can
   10021      *         be found.
   10022      */
   10023     public View findFocus() {
   10024         return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
   10025     }
   10026 
   10027     /**
   10028      * Indicates whether this view is one of the set of scrollable containers in
   10029      * its window.
   10030      *
   10031      * @return whether this view is one of the set of scrollable containers in
   10032      * its window
   10033      *
   10034      * @attr ref android.R.styleable#View_isScrollContainer
   10035      */
   10036     @InspectableProperty(name = "isScrollContainer")
   10037     public boolean isScrollContainer() {
   10038         return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
   10039     }
   10040 
   10041     /**
   10042      * Change whether this view is one of the set of scrollable containers in
   10043      * its window.  This will be used to determine whether the window can
   10044      * resize or must pan when a soft input area is open -- scrollable
   10045      * containers allow the window to use resize mode since the container
   10046      * will appropriately shrink.
   10047      *
   10048      * @attr ref android.R.styleable#View_isScrollContainer
   10049      */
   10050     public void setScrollContainer(boolean isScrollContainer) {
   10051         if (isScrollContainer) {
   10052             if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
   10053                 mAttachInfo.mScrollContainers.add(this);
   10054                 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
   10055             }
   10056             mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
   10057         } else {
   10058             if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
   10059                 mAttachInfo.mScrollContainers.remove(this);
   10060             }
   10061             mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
   10062         }
   10063     }
   10064 
   10065     /**
   10066      * Returns the quality of the drawing cache.
   10067      *
   10068      * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
   10069      *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
   10070      *
   10071      * @see #setDrawingCacheQuality(int)
   10072      * @see #setDrawingCacheEnabled(boolean)
   10073      * @see #isDrawingCacheEnabled()
   10074      *
   10075      * @attr ref android.R.styleable#View_drawingCacheQuality
   10076      *
   10077      * @deprecated The view drawing cache was largely made obsolete with the introduction of
   10078      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
   10079      * layers are largely unnecessary and can easily result in a net loss in performance due to the
   10080      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
   10081      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
   10082      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
   10083      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
   10084      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
   10085      * software-rendered usages are discouraged and have compatibility issues with hardware-only
   10086      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
   10087      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
   10088      * reports or unit testing the {@link PixelCopy} API is recommended.
   10089      */
   10090     @Deprecated
   10091     @DrawingCacheQuality
   10092     @InspectableProperty(enumMapping = {
   10093             @EnumEntry(value = DRAWING_CACHE_QUALITY_LOW, name = "low"),
   10094             @EnumEntry(value = DRAWING_CACHE_QUALITY_HIGH, name = "high"),
   10095             @EnumEntry(value = DRAWING_CACHE_QUALITY_AUTO, name = "auto")
   10096     })
   10097     public int getDrawingCacheQuality() {
   10098         return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
   10099     }
   10100 
   10101     /**
   10102      * Set the drawing cache quality of this view. This value is used only when the
   10103      * drawing cache is enabled
   10104      *
   10105      * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
   10106      *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
   10107      *
   10108      * @see #getDrawingCacheQuality()
   10109      * @see #setDrawingCacheEnabled(boolean)
   10110      * @see #isDrawingCacheEnabled()
   10111      *
   10112      * @attr ref android.R.styleable#View_drawingCacheQuality
   10113      *
   10114      * @deprecated The view drawing cache was largely made obsolete with the introduction of
   10115      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
   10116      * layers are largely unnecessary and can easily result in a net loss in performance due to the
   10117      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
   10118      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
   10119      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
   10120      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
   10121      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
   10122      * software-rendered usages are discouraged and have compatibility issues with hardware-only
   10123      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
   10124      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
   10125      * reports or unit testing the {@link PixelCopy} API is recommended.
   10126      */
   10127     @Deprecated
   10128     public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
   10129         setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
   10130     }
   10131 
   10132     /**
   10133      * Returns whether the screen should remain on, corresponding to the current
   10134      * value of {@link #KEEP_SCREEN_ON}.
   10135      *
   10136      * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
   10137      *
   10138      * @see #setKeepScreenOn(boolean)
   10139      *
   10140      * @attr ref android.R.styleable#View_keepScreenOn
   10141      */
   10142     @InspectableProperty
   10143     public boolean getKeepScreenOn() {
   10144         return (mViewFlags & KEEP_SCREEN_ON) != 0;
   10145     }
   10146 
   10147     /**
   10148      * Controls whether the screen should remain on, modifying the
   10149      * value of {@link #KEEP_SCREEN_ON}.
   10150      *
   10151      * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
   10152      *
   10153      * @see #getKeepScreenOn()
   10154      *
   10155      * @attr ref android.R.styleable#View_keepScreenOn
   10156      */
   10157     public void setKeepScreenOn(boolean keepScreenOn) {
   10158         setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
   10159     }
   10160 
   10161     /**
   10162      * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
   10163      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
   10164      *
   10165      * @attr ref android.R.styleable#View_nextFocusLeft
   10166      */
   10167     @IdRes
   10168     @InspectableProperty(name = "nextFocusLeft")
   10169     public int getNextFocusLeftId() {
   10170         return mNextFocusLeftId;
   10171     }
   10172 
   10173     /**
   10174      * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
   10175      * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
   10176      * decide automatically.
   10177      *
   10178      * @attr ref android.R.styleable#View_nextFocusLeft
   10179      */
   10180     public void setNextFocusLeftId(@IdRes int nextFocusLeftId) {
   10181         mNextFocusLeftId = nextFocusLeftId;
   10182     }
   10183 
   10184     /**
   10185      * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
   10186      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
   10187      *
   10188      * @attr ref android.R.styleable#View_nextFocusRight
   10189      */
   10190     @IdRes
   10191     @InspectableProperty(name = "nextFocusRight")
   10192     public int getNextFocusRightId() {
   10193         return mNextFocusRightId;
   10194     }
   10195 
   10196     /**
   10197      * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
   10198      * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
   10199      * decide automatically.
   10200      *
   10201      * @attr ref android.R.styleable#View_nextFocusRight
   10202      */
   10203     public void setNextFocusRightId(@IdRes int nextFocusRightId) {
   10204         mNextFocusRightId = nextFocusRightId;
   10205     }
   10206 
   10207     /**
   10208      * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
   10209      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
   10210      *
   10211      * @attr ref android.R.styleable#View_nextFocusUp
   10212      */
   10213     @IdRes
   10214     @InspectableProperty(name = "nextFocusUp")
   10215     public int getNextFocusUpId() {
   10216         return mNextFocusUpId;
   10217     }
   10218 
   10219     /**
   10220      * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
   10221      * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
   10222      * decide automatically.
   10223      *
   10224      * @attr ref android.R.styleable#View_nextFocusUp
   10225      */
   10226     public void setNextFocusUpId(@IdRes int nextFocusUpId) {
   10227         mNextFocusUpId = nextFocusUpId;
   10228     }
   10229 
   10230     /**
   10231      * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
   10232      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
   10233      *
   10234      * @attr ref android.R.styleable#View_nextFocusDown
   10235      */
   10236     @IdRes
   10237     @InspectableProperty(name = "nextFocusDown")
   10238     public int getNextFocusDownId() {
   10239         return mNextFocusDownId;
   10240     }
   10241 
   10242     /**
   10243      * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
   10244      * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
   10245      * decide automatically.
   10246      *
   10247      * @attr ref android.R.styleable#View_nextFocusDown
   10248      */
   10249     public void setNextFocusDownId(@IdRes int nextFocusDownId) {
   10250         mNextFocusDownId = nextFocusDownId;
   10251     }
   10252 
   10253     /**
   10254      * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
   10255      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
   10256      *
   10257      * @attr ref android.R.styleable#View_nextFocusForward
   10258      */
   10259     @IdRes
   10260     @InspectableProperty(name = "nextFocusForward")
   10261     public int getNextFocusForwardId() {
   10262         return mNextFocusForwardId;
   10263     }
   10264 
   10265     /**
   10266      * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
   10267      * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
   10268      * decide automatically.
   10269      *
   10270      * @attr ref android.R.styleable#View_nextFocusForward
   10271      */
   10272     public void setNextFocusForwardId(@IdRes int nextFocusForwardId) {
   10273         mNextFocusForwardId = nextFocusForwardId;
   10274     }
   10275 
   10276     /**
   10277      * Gets the id of the root of the next keyboard navigation cluster.
   10278      * @return The next keyboard navigation cluster ID, or {@link #NO_ID} if the framework should
   10279      * decide automatically.
   10280      *
   10281      * @attr ref android.R.styleable#View_nextClusterForward
   10282      */
   10283     @IdRes
   10284     @InspectableProperty(name = "nextClusterForward")
   10285     public int getNextClusterForwardId() {
   10286         return mNextClusterForwardId;
   10287     }
   10288 
   10289     /**
   10290      * Sets the id of the view to use as the root of the next keyboard navigation cluster.
   10291      * @param nextClusterForwardId The next cluster ID, or {@link #NO_ID} if the framework should
   10292      * decide automatically.
   10293      *
   10294      * @attr ref android.R.styleable#View_nextClusterForward
   10295      */
   10296     public void setNextClusterForwardId(@IdRes int nextClusterForwardId) {
   10297         mNextClusterForwardId = nextClusterForwardId;
   10298     }
   10299 
   10300     /**
   10301      * Returns the visibility of this view and all of its ancestors
   10302      *
   10303      * @return True if this view and all of its ancestors are {@link #VISIBLE}
   10304      */
   10305     public boolean isShown() {
   10306         View current = this;
   10307         //noinspection ConstantConditions
   10308         do {
   10309             if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
   10310                 return false;
   10311             }
   10312             ViewParent parent = current.mParent;
   10313             if (parent == null) {
   10314                 return false; // We are not attached to the view root
   10315             }
   10316             if (!(parent instanceof View)) {
   10317                 return true;
   10318             }
   10319             current = (View) parent;
   10320         } while (current != null);
   10321 
   10322         return false;
   10323     }
   10324 
   10325     /**
   10326      * Called by the view hierarchy when the content insets for a window have
   10327      * changed, to allow it to adjust its content to fit within those windows.
   10328      * The content insets tell you the space that the status bar, input method,
   10329      * and other system windows infringe on the application's window.
   10330      *
   10331      * <p>You do not normally need to deal with this function, since the default
   10332      * window decoration given to applications takes care of applying it to the
   10333      * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
   10334      * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
   10335      * and your content can be placed under those system elements.  You can then
   10336      * use this method within your view hierarchy if you have parts of your UI
   10337      * which you would like to ensure are not being covered.
   10338      *
   10339      * <p>The default implementation of this method simply applies the content
   10340      * insets to the view's padding, consuming that content (modifying the
   10341      * insets to be 0), and returning true.  This behavior is off by default, but can
   10342      * be enabled through {@link #setFitsSystemWindows(boolean)}.
   10343      *
   10344      * <p>This function's traversal down the hierarchy is depth-first.  The same content
   10345      * insets object is propagated down the hierarchy, so any changes made to it will
   10346      * be seen by all following views (including potentially ones above in
   10347      * the hierarchy since this is a depth-first traversal).  The first view
   10348      * that returns true will abort the entire traversal.
   10349      *
   10350      * <p>The default implementation works well for a situation where it is
   10351      * used with a container that covers the entire window, allowing it to
   10352      * apply the appropriate insets to its content on all edges.  If you need
   10353      * a more complicated layout (such as two different views fitting system
   10354      * windows, one on the top of the window, and one on the bottom),
   10355      * you can override the method and handle the insets however you would like.
   10356      * Note that the insets provided by the framework are always relative to the
   10357      * far edges of the window, not accounting for the location of the called view
   10358      * within that window.  (In fact when this method is called you do not yet know
   10359      * where the layout will place the view, as it is done before layout happens.)
   10360      *
   10361      * <p>Note: unlike many View methods, there is no dispatch phase to this
   10362      * call.  If you are overriding it in a ViewGroup and want to allow the
   10363      * call to continue to your children, you must be sure to call the super
   10364      * implementation.
   10365      *
   10366      * <p>Here is a sample layout that makes use of fitting system windows
   10367      * to have controls for a video view placed inside of the window decorations
   10368      * that it hides and shows.  This can be used with code like the second
   10369      * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
   10370      *
   10371      * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
   10372      *
   10373      * @param insets Current content insets of the window.  Prior to
   10374      * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
   10375      * the insets or else you and Android will be unhappy.
   10376      *
   10377      * @return {@code true} if this view applied the insets and it should not
   10378      * continue propagating further down the hierarchy, {@code false} otherwise.
   10379      * @see #getFitsSystemWindows()
   10380      * @see #setFitsSystemWindows(boolean)
   10381      * @see #setSystemUiVisibility(int)
   10382      *
   10383      * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
   10384      * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
   10385      * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
   10386      * to implement handling their own insets.
   10387      */
   10388     @Deprecated
   10389     protected boolean fitSystemWindows(Rect insets) {
   10390         if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
   10391             if (insets == null) {
   10392                 // Null insets by definition have already been consumed.
   10393                 // This call cannot apply insets since there are none to apply,
   10394                 // so return false.
   10395                 return false;
   10396             }
   10397             // If we're not in the process of dispatching the newer apply insets call,
   10398             // that means we're not in the compatibility path. Dispatch into the newer
   10399             // apply insets path and take things from there.
   10400             try {
   10401                 mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
   10402                 return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
   10403             } finally {
   10404                 mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
   10405             }
   10406         } else {
   10407             // We're being called from the newer apply insets path.
   10408             // Perform the standard fallback behavior.
   10409             return fitSystemWindowsInt(insets);
   10410         }
   10411     }
   10412 
   10413     private boolean fitSystemWindowsInt(Rect insets) {
   10414         if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
   10415             mUserPaddingStart = UNDEFINED_PADDING;
   10416             mUserPaddingEnd = UNDEFINED_PADDING;
   10417             Rect localInsets = sThreadLocal.get();
   10418             if (localInsets == null) {
   10419                 localInsets = new Rect();
   10420                 sThreadLocal.set(localInsets);
   10421             }
   10422             boolean res = computeFitSystemWindows(insets, localInsets);
   10423             mUserPaddingLeftInitial = localInsets.left;
   10424             mUserPaddingRightInitial = localInsets.right;
   10425             internalSetPadding(localInsets.left, localInsets.top,
   10426                     localInsets.right, localInsets.bottom);
   10427             return res;
   10428         }
   10429         return false;
   10430     }
   10431 
   10432     /**
   10433      * Called when the view should apply {@link WindowInsets} according to its internal policy.
   10434      *
   10435      * <p>This method should be overridden by views that wish to apply a policy different from or
   10436      * in addition to the default behavior. Clients that wish to force a view subtree
   10437      * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
   10438      *
   10439      * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
   10440      * it will be called during dispatch instead of this method. The listener may optionally
   10441      * call this method from its own implementation if it wishes to apply the view's default
   10442      * insets policy in addition to its own.</p>
   10443      *
   10444      * <p>Implementations of this method should either return the insets parameter unchanged
   10445      * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
   10446      * that this view applied itself. This allows new inset types added in future platform
   10447      * versions to pass through existing implementations unchanged without being erroneously
   10448      * consumed.</p>
   10449      *
   10450      * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
   10451      * property is set then the view will consume the system window insets and apply them
   10452      * as padding for the view.</p>
   10453      *
   10454      * @param insets Insets to apply
   10455      * @return The supplied insets with any applied insets consumed
   10456      */
   10457     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
   10458         if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
   10459             // We weren't called from within a direct call to fitSystemWindows,
   10460             // call into it as a fallback in case we're in a class that overrides it
   10461             // and has logic to perform.
   10462             if (fitSystemWindows(insets.getSystemWindowInsetsAsRect())) {
   10463                 return insets.consumeSystemWindowInsets();
   10464             }
   10465         } else {
   10466             // We were called from within a direct call to fitSystemWindows.
   10467             if (fitSystemWindowsInt(insets.getSystemWindowInsetsAsRect())) {
   10468                 return insets.consumeSystemWindowInsets();
   10469             }
   10470         }
   10471         return insets;
   10472     }
   10473 
   10474     /**
   10475      * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
   10476      * window insets to this view. The listener's
   10477      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
   10478      * method will be called instead of the view's
   10479      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
   10480      *
   10481      * @param listener Listener to set
   10482      *
   10483      * @see #onApplyWindowInsets(WindowInsets)
   10484      */
   10485     public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
   10486         getListenerInfo().mOnApplyWindowInsetsListener = listener;
   10487     }
   10488 
   10489     /**
   10490      * Request to apply the given window insets to this view or another view in its subtree.
   10491      *
   10492      * <p>This method should be called by clients wishing to apply insets corresponding to areas
   10493      * obscured by window decorations or overlays. This can include the status and navigation bars,
   10494      * action bars, input methods and more. New inset categories may be added in the future.
   10495      * The method returns the insets provided minus any that were applied by this view or its
   10496      * children.</p>
   10497      *
   10498      * <p>Clients wishing to provide custom behavior should override the
   10499      * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
   10500      * {@link OnApplyWindowInsetsListener} via the
   10501      * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
   10502      * method.</p>
   10503      *
   10504      * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
   10505      * </p>
   10506      *
   10507      * @param insets Insets to apply
   10508      * @return The provided insets minus the insets that were consumed
   10509      */
   10510     public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
   10511         try {
   10512             mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
   10513             if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
   10514                 return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
   10515             } else {
   10516                 return onApplyWindowInsets(insets);
   10517             }
   10518         } finally {
   10519             mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
   10520         }
   10521     }
   10522 
   10523     /**
   10524      * Sets a {@link WindowInsetsAnimationListener} to be notified about animations of windows that
   10525      * cause insets.
   10526      *
   10527      * @param listener The listener to set.
   10528      * @hide pending unhide
   10529      */
   10530     public void setWindowInsetsAnimationListener(WindowInsetsAnimationListener listener) {
   10531         getListenerInfo().mWindowInsetsAnimationListener = listener;
   10532     }
   10533 
   10534     void dispatchWindowInsetsAnimationStarted(InsetsAnimation animation) {
   10535         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationListener != null) {
   10536             mListenerInfo.mWindowInsetsAnimationListener.onStarted(animation);
   10537         }
   10538     }
   10539 
   10540     WindowInsets dispatchWindowInsetsAnimationProgress(WindowInsets insets) {
   10541         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationListener != null) {
   10542             return mListenerInfo.mWindowInsetsAnimationListener.onProgress(insets);
   10543         } else {
   10544             return insets;
   10545         }
   10546     }
   10547 
   10548     void dispatchWindowInsetsAnimationFinished(InsetsAnimation animation) {
   10549         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationListener != null) {
   10550             mListenerInfo.mWindowInsetsAnimationListener.onFinished(animation);
   10551         }
   10552     }
   10553 
   10554     /**
   10555      * Sets a list of areas within this view's post-layout coordinate space where the system
   10556      * should not intercept touch or other pointing device gestures. <em>This method should
   10557      * be called by {@link #onLayout(boolean, int, int, int, int)} or {@link #onDraw(Canvas)}.</em>
   10558      *
   10559      * <p>Use this to tell the system which specific sub-areas of a view need to receive gesture
   10560      * input in order to function correctly in the presence of global system gestures that may
   10561      * conflict. For example, if the system wishes to capture swipe-in-from-screen-edge gestures
   10562      * to provide system-level navigation functionality, a view such as a navigation drawer
   10563      * container can mark the left (or starting) edge of itself as requiring gesture capture
   10564      * priority using this API. The system may then choose to relax its own gesture recognition
   10565      * to allow the app to consume the user's gesture. It is not necessary for an app to register
   10566      * exclusion rects for broadly spanning regions such as the entirety of a
   10567      * <code>ScrollView</code> or for simple press and release click targets such as
   10568      * <code>Button</code>. Mark an exclusion rect when interacting with a view requires
   10569      * a precision touch gesture in a small area in either the X or Y dimension, such as
   10570      * an edge swipe or dragging a <code>SeekBar</code> thumb.</p>
   10571      *
   10572      * <p>Do not modify the provided list after this method is called.</p>
   10573      *
   10574      * @param rects A list of precision gesture regions that this view needs to function correctly
   10575      */
   10576     public void setSystemGestureExclusionRects(@NonNull List<Rect> rects) {
   10577         if (rects.isEmpty() && mListenerInfo == null) return;
   10578 
   10579         final ListenerInfo info = getListenerInfo();
   10580         if (rects.isEmpty()) {
   10581             info.mSystemGestureExclusionRects = null;
   10582             if (info.mPositionUpdateListener != null) {
   10583                 mRenderNode.removePositionUpdateListener(info.mPositionUpdateListener);
   10584             }
   10585         } else {
   10586             info.mSystemGestureExclusionRects = rects;
   10587             if (info.mPositionUpdateListener == null) {
   10588                 info.mPositionUpdateListener = new RenderNode.PositionUpdateListener() {
   10589                     @Override
   10590                     public void positionChanged(long n, int l, int t, int r, int b) {
   10591                         postUpdateSystemGestureExclusionRects();
   10592                     }
   10593 
   10594                     @Override
   10595                     public void positionLost(long frameNumber) {
   10596                         postUpdateSystemGestureExclusionRects();
   10597                     }
   10598                 };
   10599                 mRenderNode.addPositionUpdateListener(info.mPositionUpdateListener);
   10600             }
   10601         }
   10602         postUpdateSystemGestureExclusionRects();
   10603     }
   10604 
   10605     /**
   10606      * WARNING: this can be called by a hwui worker thread, not just the UI thread!
   10607      */
   10608     void postUpdateSystemGestureExclusionRects() {
   10609         // Potentially racey from a background thread. It's ok if it's not perfect.
   10610         final Handler h = getHandler();
   10611         if (h != null) {
   10612             h.postAtFrontOfQueue(this::updateSystemGestureExclusionRects);
   10613         }
   10614     }
   10615 
   10616     void updateSystemGestureExclusionRects() {
   10617         final AttachInfo ai = mAttachInfo;
   10618         if (ai != null) {
   10619             ai.mViewRootImpl.updateSystemGestureExclusionRectsForView(this);
   10620         }
   10621     }
   10622 
   10623     /**
   10624      * Retrieve the list of areas within this view's post-layout coordinate space where the system
   10625      * should not intercept touch or other pointing device gestures.
   10626      *
   10627      * <p>Do not modify the returned list.</p>
   10628      *
   10629      * @return the list set by {@link #setSystemGestureExclusionRects(List)}
   10630      */
   10631     @NonNull
   10632     public List<Rect> getSystemGestureExclusionRects() {
   10633         final ListenerInfo info = mListenerInfo;
   10634         if (info != null) {
   10635             final List<Rect> list = info.mSystemGestureExclusionRects;
   10636             if (list != null) {
   10637                 return list;
   10638             }
   10639         }
   10640         return Collections.emptyList();
   10641     }
   10642 
   10643     /**
   10644      * Compute the view's coordinate within the surface.
   10645      *
   10646      * <p>Computes the coordinates of this view in its surface. The argument
   10647      * must be an array of two integers. After the method returns, the array
   10648      * contains the x and y location in that order.</p>
   10649      *
   10650      * @param location an array of two integers in which to hold the coordinates
   10651      */
   10652     public void getLocationInSurface(@NonNull @Size(2) int[] location) {
   10653         getLocationInWindow(location);
   10654         if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
   10655             location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
   10656             location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
   10657         }
   10658     }
   10659 
   10660     /**
   10661      * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
   10662      * only available if the view is attached.
   10663      *
   10664      * @return WindowInsets from the top of the view hierarchy or null if View is detached
   10665      */
   10666     public WindowInsets getRootWindowInsets() {
   10667         if (mAttachInfo != null) {
   10668             return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
   10669         }
   10670         return null;
   10671     }
   10672 
   10673     /**
   10674      * Retrieves the single {@link WindowInsetsController} of the window this view is attached to.
   10675      *
   10676      * @return The {@link WindowInsetsController} or {@code null} if the view isn't attached to a
   10677      *         a window.
   10678      * @see Window#getInsetsController()
   10679      * @hide pending unhide
   10680      */
   10681     public @Nullable WindowInsetsController getWindowInsetsController() {
   10682         if (mAttachInfo != null) {
   10683             return mAttachInfo.mViewRootImpl.getInsetsController();
   10684         }
   10685         return null;
   10686     }
   10687 
   10688     /**
   10689      * @hide Compute the insets that should be consumed by this view and the ones
   10690      * that should propagate to those under it.
   10691      *
   10692      * Note: This is used by appcompat's ActionBarOverlayLayout through reflection.
   10693      *
   10694      * @param inoutInsets the insets given to this view
   10695      * @param outLocalInsets the insets that should be applied to this view
   10696      * @deprecated use {@link #computeSystemWindowInsets}
   10697      * @return
   10698      */
   10699     @Deprecated
   10700     @UnsupportedAppUsage
   10701     protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
   10702         WindowInsets innerInsets = computeSystemWindowInsets(new WindowInsets(inoutInsets),
   10703                 outLocalInsets);
   10704         inoutInsets.set(innerInsets.getSystemWindowInsetsAsRect());
   10705         return innerInsets.isSystemWindowInsetsConsumed();
   10706     }
   10707 
   10708     /**
   10709      * Compute insets that should be consumed by this view and the ones that should propagate
   10710      * to those under it.
   10711      *
   10712      * @param in Insets currently being processed by this View, likely received as a parameter
   10713      *           to {@link #onApplyWindowInsets(WindowInsets)}.
   10714      * @param outLocalInsets A Rect that will receive the insets that should be consumed
   10715      *                       by this view
   10716      * @return Insets that should be passed along to views under this one
   10717      */
   10718     public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
   10719         if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
   10720                 || mAttachInfo == null
   10721                 || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
   10722                 && !mAttachInfo.mOverscanRequested)) {
   10723             outLocalInsets.set(in.getSystemWindowInsetsAsRect());
   10724             return in.consumeSystemWindowInsets().inset(outLocalInsets);
   10725         } else {
   10726             // The application wants to take care of fitting system window for
   10727             // the content...  however we still need to take care of any overscan here.
   10728             final Rect overscan = mAttachInfo.mOverscanInsets;
   10729             outLocalInsets.set(overscan);
   10730             return in.inset(outLocalInsets);
   10731         }
   10732     }
   10733 
   10734     /**
   10735      * Sets whether or not this view should account for system screen decorations
   10736      * such as the status bar and inset its content; that is, controlling whether
   10737      * the default implementation of {@link #fitSystemWindows(Rect)} will be
   10738      * executed.  See that method for more details.
   10739      *
   10740      * <p>Note that if you are providing your own implementation of
   10741      * {@link #fitSystemWindows(Rect)}, then there is no need to set this
   10742      * flag to true -- your implementation will be overriding the default
   10743      * implementation that checks this flag.
   10744      *
   10745      * @param fitSystemWindows If true, then the default implementation of
   10746      * {@link #fitSystemWindows(Rect)} will be executed.
   10747      *
   10748      * @attr ref android.R.styleable#View_fitsSystemWindows
   10749      * @see #getFitsSystemWindows()
   10750      * @see #fitSystemWindows(Rect)
   10751      * @see #setSystemUiVisibility(int)
   10752      */
   10753     public void setFitsSystemWindows(boolean fitSystemWindows) {
   10754         setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
   10755     }
   10756 
   10757     /**
   10758      * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
   10759      * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
   10760      * will be executed.
   10761      *
   10762      * @return {@code true} if the default implementation of
   10763      * {@link #fitSystemWindows(Rect)} will be executed.
   10764      *
   10765      * @attr ref android.R.styleable#View_fitsSystemWindows
   10766      * @see #setFitsSystemWindows(boolean)
   10767      * @see #fitSystemWindows(Rect)
   10768      * @see #setSystemUiVisibility(int)
   10769      */
   10770     @ViewDebug.ExportedProperty
   10771     @InspectableProperty
   10772     public boolean getFitsSystemWindows() {
   10773         return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
   10774     }
   10775 
   10776     /** @hide */
   10777     @UnsupportedAppUsage
   10778     public boolean fitsSystemWindows() {
   10779         return getFitsSystemWindows();
   10780     }
   10781 
   10782     /**
   10783      * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
   10784      * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
   10785      */
   10786     @Deprecated
   10787     public void requestFitSystemWindows() {
   10788         if (mParent != null) {
   10789             mParent.requestFitSystemWindows();
   10790         }
   10791     }
   10792 
   10793     /**
   10794      * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
   10795      */
   10796     public void requestApplyInsets() {
   10797         requestFitSystemWindows();
   10798     }
   10799 
   10800     /**
   10801      * For use by PhoneWindow to make its own system window fitting optional.
   10802      * @hide
   10803      */
   10804     @UnsupportedAppUsage
   10805     public void makeOptionalFitsSystemWindows() {
   10806         setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
   10807     }
   10808 
   10809     /**
   10810      * Returns the outsets, which areas of the device that aren't a surface, but we would like to
   10811      * treat them as such.
   10812      * @hide
   10813      */
   10814     public void getOutsets(Rect outOutsetRect) {
   10815         if (mAttachInfo != null) {
   10816             outOutsetRect.set(mAttachInfo.mOutsets);
   10817         } else {
   10818             outOutsetRect.setEmpty();
   10819         }
   10820     }
   10821 
   10822     /**
   10823      * Returns the visibility status for this view.
   10824      *
   10825      * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
   10826      * @attr ref android.R.styleable#View_visibility
   10827      */
   10828     @ViewDebug.ExportedProperty(mapping = {
   10829         @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
   10830         @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
   10831         @ViewDebug.IntToString(from = GONE,      to = "GONE")
   10832     })
   10833     @InspectableProperty(enumMapping = {
   10834             @EnumEntry(value = VISIBLE, name = "visible"),
   10835             @EnumEntry(value = INVISIBLE, name = "invisible"),
   10836             @EnumEntry(value = GONE, name = "gone")
   10837     })
   10838     @Visibility
   10839     public int getVisibility() {
   10840         return mViewFlags & VISIBILITY_MASK;
   10841     }
   10842 
   10843     /**
   10844      * Set the visibility state of this view.
   10845      *
   10846      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
   10847      * @attr ref android.R.styleable#View_visibility
   10848      */
   10849     @RemotableViewMethod
   10850     public void setVisibility(@Visibility int visibility) {
   10851         setFlags(visibility, VISIBILITY_MASK);
   10852     }
   10853 
   10854     /**
   10855      * Returns the enabled status for this view. The interpretation of the
   10856      * enabled state varies by subclass.
   10857      *
   10858      * @return True if this view is enabled, false otherwise.
   10859      */
   10860     @ViewDebug.ExportedProperty
   10861     @InspectableProperty
   10862     public boolean isEnabled() {
   10863         return (mViewFlags & ENABLED_MASK) == ENABLED;
   10864     }
   10865 
   10866     /**
   10867      * Set the enabled state of this view. The interpretation of the enabled
   10868      * state varies by subclass.
   10869      *
   10870      * @param enabled True if this view is enabled, false otherwise.
   10871      */
   10872     @RemotableViewMethod
   10873     public void setEnabled(boolean enabled) {
   10874         if (enabled == isEnabled()) return;
   10875 
   10876         setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
   10877 
   10878         /*
   10879          * The View most likely has to change its appearance, so refresh
   10880          * the drawable state.
   10881          */
   10882         refreshDrawableState();
   10883 
   10884         // Invalidate too, since the default behavior for views is to be
   10885         // be drawn at 50% alpha rather than to change the drawable.
   10886         invalidate(true);
   10887 
   10888         if (!enabled) {
   10889             cancelPendingInputEvents();
   10890         }
   10891     }
   10892 
   10893     /**
   10894      * Set whether this view can receive the focus.
   10895      * <p>
   10896      * Setting this to false will also ensure that this view is not focusable
   10897      * in touch mode.
   10898      *
   10899      * @param focusable If true, this view can receive the focus.
   10900      *
   10901      * @see #setFocusableInTouchMode(boolean)
   10902      * @see #setFocusable(int)
   10903      * @attr ref android.R.styleable#View_focusable
   10904      */
   10905     public void setFocusable(boolean focusable) {
   10906         setFocusable(focusable ? FOCUSABLE : NOT_FOCUSABLE);
   10907     }
   10908 
   10909     /**
   10910      * Sets whether this view can receive focus.
   10911      * <p>
   10912      * Setting this to {@link #FOCUSABLE_AUTO} tells the framework to determine focusability
   10913      * automatically based on the view's interactivity. This is the default.
   10914      * <p>
   10915      * Setting this to NOT_FOCUSABLE will ensure that this view is also not focusable
   10916      * in touch mode.
   10917      *
   10918      * @param focusable One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE},
   10919      *                  or {@link #FOCUSABLE_AUTO}.
   10920      * @see #setFocusableInTouchMode(boolean)
   10921      * @attr ref android.R.styleable#View_focusable
   10922      */
   10923     public void setFocusable(@Focusable int focusable) {
   10924         if ((focusable & (FOCUSABLE_AUTO | FOCUSABLE)) == 0) {
   10925             setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
   10926         }
   10927         setFlags(focusable, FOCUSABLE_MASK);
   10928     }
   10929 
   10930     /**
   10931      * Set whether this view can receive focus while in touch mode.
   10932      *
   10933      * Setting this to true will also ensure that this view is focusable.
   10934      *
   10935      * @param focusableInTouchMode If true, this view can receive the focus while
   10936      *   in touch mode.
   10937      *
   10938      * @see #setFocusable(boolean)
   10939      * @attr ref android.R.styleable#View_focusableInTouchMode
   10940      */
   10941     public void setFocusableInTouchMode(boolean focusableInTouchMode) {
   10942         // Focusable in touch mode should always be set before the focusable flag
   10943         // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
   10944         // which, in touch mode, will not successfully request focus on this view
   10945         // because the focusable in touch mode flag is not set
   10946         setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
   10947 
   10948         // Clear FOCUSABLE_AUTO if set.
   10949         if (focusableInTouchMode) {
   10950             // Clears FOCUSABLE_AUTO if set.
   10951             setFlags(FOCUSABLE, FOCUSABLE_MASK);
   10952         }
   10953     }
   10954 
   10955     /**
   10956      * Sets the hints that help an {@link android.service.autofill.AutofillService} determine how
   10957      * to autofill the view with the user's data.
   10958      *
   10959      * <p>Typically, there is only one way to autofill a view, but there could be more than one.
   10960      * For example, if the application accepts either an username or email address to identify
   10961      * an user.
   10962      *
   10963      * <p>These hints are not validated by the Android System, but passed "as is" to the service.
   10964      * Hence, they can have any value, but it's recommended to use the {@code AUTOFILL_HINT_}
   10965      * constants such as:
   10966      * {@link #AUTOFILL_HINT_USERNAME}, {@link #AUTOFILL_HINT_PASSWORD},
   10967      * {@link #AUTOFILL_HINT_EMAIL_ADDRESS},
   10968      * {@link #AUTOFILL_HINT_NAME},
   10969      * {@link #AUTOFILL_HINT_PHONE},
   10970      * {@link #AUTOFILL_HINT_POSTAL_ADDRESS}, {@link #AUTOFILL_HINT_POSTAL_CODE},
   10971      * {@link #AUTOFILL_HINT_CREDIT_CARD_NUMBER}, {@link #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE},
   10972      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE},
   10973      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
   10974      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH} or
   10975      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}.
   10976      *
   10977      * @param autofillHints The autofill hints to set. If the array is emtpy, {@code null} is set.
   10978      * @attr ref android.R.styleable#View_autofillHints
   10979      */
   10980     public void setAutofillHints(@Nullable String... autofillHints) {
   10981         if (autofillHints == null || autofillHints.length == 0) {
   10982             mAutofillHints = null;
   10983         } else {
   10984             mAutofillHints = autofillHints;
   10985         }
   10986     }
   10987 
   10988     /**
   10989      * @hide
   10990      */
   10991     @TestApi
   10992     public void setAutofilled(boolean isAutofilled) {
   10993         boolean wasChanged = isAutofilled != isAutofilled();
   10994 
   10995         if (wasChanged) {
   10996             if (isAutofilled) {
   10997                 mPrivateFlags3 |= PFLAG3_IS_AUTOFILLED;
   10998             } else {
   10999                 mPrivateFlags3 &= ~PFLAG3_IS_AUTOFILLED;
   11000             }
   11001 
   11002             invalidate();
   11003         }
   11004     }
   11005 
   11006     /**
   11007      * Set whether this view should have sound effects enabled for events such as
   11008      * clicking and touching.
   11009      *
   11010      * <p>You may wish to disable sound effects for a view if you already play sounds,
   11011      * for instance, a dial key that plays dtmf tones.
   11012      *
   11013      * @param soundEffectsEnabled whether sound effects are enabled for this view.
   11014      * @see #isSoundEffectsEnabled()
   11015      * @see #playSoundEffect(int)
   11016      * @attr ref android.R.styleable#View_soundEffectsEnabled
   11017      */
   11018     public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
   11019         setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
   11020     }
   11021 
   11022     /**
   11023      * @return whether this view should have sound effects enabled for events such as
   11024      *     clicking and touching.
   11025      *
   11026      * @see #setSoundEffectsEnabled(boolean)
   11027      * @see #playSoundEffect(int)
   11028      * @attr ref android.R.styleable#View_soundEffectsEnabled
   11029      */
   11030     @ViewDebug.ExportedProperty
   11031     @InspectableProperty
   11032     public boolean isSoundEffectsEnabled() {
   11033         return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
   11034     }
   11035 
   11036     /**
   11037      * Set whether this view should have haptic feedback for events such as
   11038      * long presses.
   11039      *
   11040      * <p>You may wish to disable haptic feedback if your view already controls
   11041      * its own haptic feedback.
   11042      *
   11043      * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
   11044      * @see #isHapticFeedbackEnabled()
   11045      * @see #performHapticFeedback(int)
   11046      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
   11047      */
   11048     public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
   11049         setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
   11050     }
   11051 
   11052     /**
   11053      * @return whether this view should have haptic feedback enabled for events
   11054      * long presses.
   11055      *
   11056      * @see #setHapticFeedbackEnabled(boolean)
   11057      * @see #performHapticFeedback(int)
   11058      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
   11059      */
   11060     @ViewDebug.ExportedProperty
   11061     @InspectableProperty
   11062     public boolean isHapticFeedbackEnabled() {
   11063         return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
   11064     }
   11065 
   11066     /**
   11067      * Returns the layout direction for this view.
   11068      *
   11069      * @return One of {@link #LAYOUT_DIRECTION_LTR},
   11070      *   {@link #LAYOUT_DIRECTION_RTL},
   11071      *   {@link #LAYOUT_DIRECTION_INHERIT} or
   11072      *   {@link #LAYOUT_DIRECTION_LOCALE}.
   11073      *
   11074      * @attr ref android.R.styleable#View_layoutDirection
   11075      *
   11076      * @hide
   11077      */
   11078     @ViewDebug.ExportedProperty(category = "layout", mapping = {
   11079         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
   11080         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
   11081         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
   11082         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
   11083     })
   11084     @InspectableProperty(hasAttributeId = false, enumMapping = {
   11085             @EnumEntry(value = LAYOUT_DIRECTION_LTR, name = "ltr"),
   11086             @EnumEntry(value = LAYOUT_DIRECTION_RTL, name = "rtl"),
   11087             @EnumEntry(value = LAYOUT_DIRECTION_INHERIT, name = "inherit"),
   11088             @EnumEntry(value = LAYOUT_DIRECTION_LOCALE, name = "locale")
   11089     })
   11090     @LayoutDir
   11091     public int getRawLayoutDirection() {
   11092         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
   11093     }
   11094 
   11095     /**
   11096      * Set the layout direction for this view. This will propagate a reset of layout direction
   11097      * resolution to the view's children and resolve layout direction for this view.
   11098      *
   11099      * @param layoutDirection the layout direction to set. Should be one of:
   11100      *
   11101      * {@link #LAYOUT_DIRECTION_LTR},
   11102      * {@link #LAYOUT_DIRECTION_RTL},
   11103      * {@link #LAYOUT_DIRECTION_INHERIT},
   11104      * {@link #LAYOUT_DIRECTION_LOCALE}.
   11105      *
   11106      * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
   11107      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
   11108      * will return the default {@link #LAYOUT_DIRECTION_LTR}.
   11109      *
   11110      * @attr ref android.R.styleable#View_layoutDirection
   11111      */
   11112     @RemotableViewMethod
   11113     public void setLayoutDirection(@LayoutDir int layoutDirection) {
   11114         if (getRawLayoutDirection() != layoutDirection) {
   11115             // Reset the current layout direction and the resolved one
   11116             mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
   11117             resetRtlProperties();
   11118             // Set the new layout direction (filtered)
   11119             mPrivateFlags2 |=
   11120                     ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
   11121             // We need to resolve all RTL properties as they all depend on layout direction
   11122             resolveRtlPropertiesIfNeeded();
   11123             requestLayout();
   11124             invalidate(true);
   11125         }
   11126     }
   11127 
   11128     /**
   11129      * Returns the resolved layout direction for this view.
   11130      *
   11131      * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
   11132      * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
   11133      *
   11134      * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
   11135      * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
   11136      *
   11137      * @attr ref android.R.styleable#View_layoutDirection
   11138      */
   11139     @ViewDebug.ExportedProperty(category = "layout", mapping = {
   11140         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
   11141         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
   11142     })
   11143     @InspectableProperty(enumMapping = {
   11144             @EnumEntry(value = LAYOUT_DIRECTION_LTR, name = "ltr"),
   11145             @EnumEntry(value = LAYOUT_DIRECTION_RTL, name = "rtl")
   11146     })
   11147     @ResolvedLayoutDir
   11148     public int getLayoutDirection() {
   11149         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
   11150         if (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
   11151             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
   11152             return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
   11153         }
   11154         return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
   11155                 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
   11156     }
   11157 
   11158     /**
   11159      * Indicates whether or not this view's layout is right-to-left. This is resolved from
   11160      * layout attribute and/or the inherited value from the parent
   11161      *
   11162      * @return true if the layout is right-to-left.
   11163      *
   11164      * @hide
   11165      */
   11166     @ViewDebug.ExportedProperty(category = "layout")
   11167     @UnsupportedAppUsage
   11168     public boolean isLayoutRtl() {
   11169         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
   11170     }
   11171 
   11172     /**
   11173      * Indicates whether the view is currently tracking transient state that the
   11174      * app should not need to concern itself with saving and restoring, but that
   11175      * the framework should take special note to preserve when possible.
   11176      *
   11177      * <p>A view with transient state cannot be trivially rebound from an external
   11178      * data source, such as an adapter binding item views in a list. This may be
   11179      * because the view is performing an animation, tracking user selection
   11180      * of content, or similar.</p>
   11181      *
   11182      * @return true if the view has transient state
   11183      */
   11184     @ViewDebug.ExportedProperty(category = "layout")
   11185     public boolean hasTransientState() {
   11186         return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
   11187     }
   11188 
   11189     /**
   11190      * Set whether this view is currently tracking transient state that the
   11191      * framework should attempt to preserve when possible. This flag is reference counted,
   11192      * so every call to setHasTransientState(true) should be paired with a later call
   11193      * to setHasTransientState(false).
   11194      *
   11195      * <p>A view with transient state cannot be trivially rebound from an external
   11196      * data source, such as an adapter binding item views in a list. This may be
   11197      * because the view is performing an animation, tracking user selection
   11198      * of content, or similar.</p>
   11199      *
   11200      * @param hasTransientState true if this view has transient state
   11201      */
   11202     public void setHasTransientState(boolean hasTransientState) {
   11203         final boolean oldHasTransientState = hasTransientState();
   11204         mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
   11205                 mTransientStateCount - 1;
   11206         if (mTransientStateCount < 0) {
   11207             mTransientStateCount = 0;
   11208             Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
   11209                     "unmatched pair of setHasTransientState calls");
   11210         } else if ((hasTransientState && mTransientStateCount == 1) ||
   11211                 (!hasTransientState && mTransientStateCount == 0)) {
   11212             // update flag if we've just incremented up from 0 or decremented down to 0
   11213             mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
   11214                     (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
   11215             final boolean newHasTransientState = hasTransientState();
   11216             if (mParent != null && newHasTransientState != oldHasTransientState) {
   11217                 try {
   11218                     mParent.childHasTransientStateChanged(this, newHasTransientState);
   11219                 } catch (AbstractMethodError e) {
   11220                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   11221                             " does not fully implement ViewParent", e);
   11222                 }
   11223             }
   11224         }
   11225     }
   11226 
   11227     /**
   11228      * Returns true if this view is currently attached to a window.
   11229      */
   11230     public boolean isAttachedToWindow() {
   11231         return mAttachInfo != null;
   11232     }
   11233 
   11234     /**
   11235      * Returns true if this view has been through at least one layout since it
   11236      * was last attached to or detached from a window.
   11237      */
   11238     public boolean isLaidOut() {
   11239         return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
   11240     }
   11241 
   11242     /**
   11243      * @return {@code true} if laid-out and not about to do another layout.
   11244      */
   11245     boolean isLayoutValid() {
   11246         return isLaidOut() && ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == 0);
   11247     }
   11248 
   11249     /**
   11250      * If this view doesn't do any drawing on its own, set this flag to
   11251      * allow further optimizations. By default, this flag is not set on
   11252      * View, but could be set on some View subclasses such as ViewGroup.
   11253      *
   11254      * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
   11255      * you should clear this flag.
   11256      *
   11257      * @param willNotDraw whether or not this View draw on its own
   11258      */
   11259     public void setWillNotDraw(boolean willNotDraw) {
   11260         setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
   11261     }
   11262 
   11263     /**
   11264      * Returns whether or not this View draws on its own.
   11265      *
   11266      * @return true if this view has nothing to draw, false otherwise
   11267      */
   11268     @ViewDebug.ExportedProperty(category = "drawing")
   11269     public boolean willNotDraw() {
   11270         return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
   11271     }
   11272 
   11273     /**
   11274      * When a View's drawing cache is enabled, drawing is redirected to an
   11275      * offscreen bitmap. Some views, like an ImageView, must be able to
   11276      * bypass this mechanism if they already draw a single bitmap, to avoid
   11277      * unnecessary usage of the memory.
   11278      *
   11279      * @param willNotCacheDrawing true if this view does not cache its
   11280      *        drawing, false otherwise
   11281      *
   11282      * @deprecated The view drawing cache was largely made obsolete with the introduction of
   11283      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
   11284      * layers are largely unnecessary and can easily result in a net loss in performance due to the
   11285      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
   11286      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
   11287      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
   11288      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
   11289      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
   11290      * software-rendered usages are discouraged and have compatibility issues with hardware-only
   11291      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
   11292      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
   11293      * reports or unit testing the {@link PixelCopy} API is recommended.
   11294      */
   11295     @Deprecated
   11296     public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
   11297         setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
   11298     }
   11299 
   11300     /**
   11301      * Returns whether or not this View can cache its drawing or not.
   11302      *
   11303      * @return true if this view does not cache its drawing, false otherwise
   11304      *
   11305      * @deprecated The view drawing cache was largely made obsolete with the introduction of
   11306      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
   11307      * layers are largely unnecessary and can easily result in a net loss in performance due to the
   11308      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
   11309      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
   11310      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
   11311      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
   11312      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
   11313      * software-rendered usages are discouraged and have compatibility issues with hardware-only
   11314      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
   11315      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
   11316      * reports or unit testing the {@link PixelCopy} API is recommended.
   11317      */
   11318     @ViewDebug.ExportedProperty(category = "drawing")
   11319     @Deprecated
   11320     public boolean willNotCacheDrawing() {
   11321         return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
   11322     }
   11323 
   11324     /**
   11325      * Indicates whether this view reacts to click events or not.
   11326      *
   11327      * @return true if the view is clickable, false otherwise
   11328      *
   11329      * @see #setClickable(boolean)
   11330      * @attr ref android.R.styleable#View_clickable
   11331      */
   11332     @ViewDebug.ExportedProperty
   11333     @InspectableProperty
   11334     public boolean isClickable() {
   11335         return (mViewFlags & CLICKABLE) == CLICKABLE;
   11336     }
   11337 
   11338     /**
   11339      * Enables or disables click events for this view. When a view
   11340      * is clickable it will change its state to "pressed" on every click.
   11341      * Subclasses should set the view clickable to visually react to
   11342      * user's clicks.
   11343      *
   11344      * @param clickable true to make the view clickable, false otherwise
   11345      *
   11346      * @see #isClickable()
   11347      * @attr ref android.R.styleable#View_clickable
   11348      */
   11349     public void setClickable(boolean clickable) {
   11350         setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
   11351     }
   11352 
   11353     /**
   11354      * Indicates whether this view reacts to long click events or not.
   11355      *
   11356      * @return true if the view is long clickable, false otherwise
   11357      *
   11358      * @see #setLongClickable(boolean)
   11359      * @attr ref android.R.styleable#View_longClickable
   11360      */
   11361     @InspectableProperty
   11362     public boolean isLongClickable() {
   11363         return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
   11364     }
   11365 
   11366     /**
   11367      * Enables or disables long click events for this view. When a view is long
   11368      * clickable it reacts to the user holding down the button for a longer
   11369      * duration than a tap. This event can either launch the listener or a
   11370      * context menu.
   11371      *
   11372      * @param longClickable true to make the view long clickable, false otherwise
   11373      * @see #isLongClickable()
   11374      * @attr ref android.R.styleable#View_longClickable
   11375      */
   11376     public void setLongClickable(boolean longClickable) {
   11377         setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
   11378     }
   11379 
   11380     /**
   11381      * Indicates whether this view reacts to context clicks or not.
   11382      *
   11383      * @return true if the view is context clickable, false otherwise
   11384      * @see #setContextClickable(boolean)
   11385      * @attr ref android.R.styleable#View_contextClickable
   11386      */
   11387     @InspectableProperty
   11388     public boolean isContextClickable() {
   11389         return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
   11390     }
   11391 
   11392     /**
   11393      * Enables or disables context clicking for this view. This event can launch the listener.
   11394      *
   11395      * @param contextClickable true to make the view react to a context click, false otherwise
   11396      * @see #isContextClickable()
   11397      * @attr ref android.R.styleable#View_contextClickable
   11398      */
   11399     public void setContextClickable(boolean contextClickable) {
   11400         setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
   11401     }
   11402 
   11403     /**
   11404      * Sets the pressed state for this view and provides a touch coordinate for
   11405      * animation hinting.
   11406      *
   11407      * @param pressed Pass true to set the View's internal state to "pressed",
   11408      *            or false to reverts the View's internal state from a
   11409      *            previously set "pressed" state.
   11410      * @param x The x coordinate of the touch that caused the press
   11411      * @param y The y coordinate of the touch that caused the press
   11412      */
   11413     private void setPressed(boolean pressed, float x, float y) {
   11414         if (pressed) {
   11415             drawableHotspotChanged(x, y);
   11416         }
   11417 
   11418         setPressed(pressed);
   11419     }
   11420 
   11421     /**
   11422      * Sets the pressed state for this view.
   11423      *
   11424      * @see #isClickable()
   11425      * @see #setClickable(boolean)
   11426      *
   11427      * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
   11428      *        the View's internal state from a previously set "pressed" state.
   11429      */
   11430     public void setPressed(boolean pressed) {
   11431         final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
   11432 
   11433         if (pressed) {
   11434             mPrivateFlags |= PFLAG_PRESSED;
   11435         } else {
   11436             mPrivateFlags &= ~PFLAG_PRESSED;
   11437         }
   11438 
   11439         if (needsRefresh) {
   11440             refreshDrawableState();
   11441         }
   11442         dispatchSetPressed(pressed);
   11443     }
   11444 
   11445     /**
   11446      * Dispatch setPressed to all of this View's children.
   11447      *
   11448      * @see #setPressed(boolean)
   11449      *
   11450      * @param pressed The new pressed state
   11451      */
   11452     protected void dispatchSetPressed(boolean pressed) {
   11453     }
   11454 
   11455     /**
   11456      * Indicates whether the view is currently in pressed state. Unless
   11457      * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
   11458      * the pressed state.
   11459      *
   11460      * @see #setPressed(boolean)
   11461      * @see #isClickable()
   11462      * @see #setClickable(boolean)
   11463      *
   11464      * @return true if the view is currently pressed, false otherwise
   11465      */
   11466     @ViewDebug.ExportedProperty
   11467     @InspectableProperty(hasAttributeId = false)
   11468     public boolean isPressed() {
   11469         return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
   11470     }
   11471 
   11472     /**
   11473      * @hide
   11474      * Indicates whether this view will participate in data collection through
   11475      * {@link ViewStructure}.  If true, it will not provide any data
   11476      * for itself or its children.  If false, the normal data collection will be allowed.
   11477      *
   11478      * @return Returns false if assist data collection is not blocked, else true.
   11479      *
   11480      * @see #setAssistBlocked(boolean)
   11481      * @attr ref android.R.styleable#View_assistBlocked
   11482      */
   11483     public boolean isAssistBlocked() {
   11484         return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
   11485     }
   11486 
   11487     /**
   11488      * @hide
   11489      * Controls whether assist data collection from this view and its children is enabled
   11490      * (that is, whether {@link #onProvideStructure} and
   11491      * {@link #onProvideVirtualStructure} will be called).  The default value is false,
   11492      * allowing normal assist collection.  Setting this to false will disable assist collection.
   11493      *
   11494      * @param enabled Set to true to <em>disable</em> assist data collection, or false
   11495      * (the default) to allow it.
   11496      *
   11497      * @see #isAssistBlocked()
   11498      * @see #onProvideStructure
   11499      * @see #onProvideVirtualStructure
   11500      * @attr ref android.R.styleable#View_assistBlocked
   11501      */
   11502     @UnsupportedAppUsage
   11503     public void setAssistBlocked(boolean enabled) {
   11504         if (enabled) {
   11505             mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
   11506         } else {
   11507             mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
   11508         }
   11509     }
   11510 
   11511     /**
   11512      * Indicates whether this view will save its state (that is,
   11513      * whether its {@link #onSaveInstanceState} method will be called).
   11514      *
   11515      * @return Returns true if the view state saving is enabled, else false.
   11516      *
   11517      * @see #setSaveEnabled(boolean)
   11518      * @attr ref android.R.styleable#View_saveEnabled
   11519      */
   11520     @InspectableProperty
   11521     public boolean isSaveEnabled() {
   11522         return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
   11523     }
   11524 
   11525     /**
   11526      * Controls whether the saving of this view's state is
   11527      * enabled (that is, whether its {@link #onSaveInstanceState} method
   11528      * will be called).  Note that even if freezing is enabled, the
   11529      * view still must have an id assigned to it (via {@link #setId(int)})
   11530      * for its state to be saved.  This flag can only disable the
   11531      * saving of this view; any child views may still have their state saved.
   11532      *
   11533      * @param enabled Set to false to <em>disable</em> state saving, or true
   11534      * (the default) to allow it.
   11535      *
   11536      * @see #isSaveEnabled()
   11537      * @see #setId(int)
   11538      * @see #onSaveInstanceState()
   11539      * @attr ref android.R.styleable#View_saveEnabled
   11540      */
   11541     public void setSaveEnabled(boolean enabled) {
   11542         setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
   11543     }
   11544 
   11545     /**
   11546      * Gets whether the framework should discard touches when the view's
   11547      * window is obscured by another visible window.
   11548      * Refer to the {@link View} security documentation for more details.
   11549      *
   11550      * @return True if touch filtering is enabled.
   11551      *
   11552      * @see #setFilterTouchesWhenObscured(boolean)
   11553      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
   11554      */
   11555     @ViewDebug.ExportedProperty
   11556     @InspectableProperty
   11557     public boolean getFilterTouchesWhenObscured() {
   11558         return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
   11559     }
   11560 
   11561     /**
   11562      * Sets whether the framework should discard touches when the view's
   11563      * window is obscured by another visible window.
   11564      * Refer to the {@link View} security documentation for more details.
   11565      *
   11566      * @param enabled True if touch filtering should be enabled.
   11567      *
   11568      * @see #getFilterTouchesWhenObscured
   11569      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
   11570      */
   11571     public void setFilterTouchesWhenObscured(boolean enabled) {
   11572         setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
   11573                 FILTER_TOUCHES_WHEN_OBSCURED);
   11574     }
   11575 
   11576     /**
   11577      * Indicates whether the entire hierarchy under this view will save its
   11578      * state when a state saving traversal occurs from its parent.  The default
   11579      * is true; if false, these views will not be saved unless
   11580      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
   11581      *
   11582      * @return Returns true if the view state saving from parent is enabled, else false.
   11583      *
   11584      * @see #setSaveFromParentEnabled(boolean)
   11585      */
   11586     public boolean isSaveFromParentEnabled() {
   11587         return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
   11588     }
   11589 
   11590     /**
   11591      * Controls whether the entire hierarchy under this view will save its
   11592      * state when a state saving traversal occurs from its parent.  The default
   11593      * is true; if false, these views will not be saved unless
   11594      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
   11595      *
   11596      * @param enabled Set to false to <em>disable</em> state saving, or true
   11597      * (the default) to allow it.
   11598      *
   11599      * @see #isSaveFromParentEnabled()
   11600      * @see #setId(int)
   11601      * @see #onSaveInstanceState()
   11602      */
   11603     public void setSaveFromParentEnabled(boolean enabled) {
   11604         setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
   11605     }
   11606 
   11607 
   11608     /**
   11609      * Returns whether this View is currently able to take focus.
   11610      *
   11611      * @return True if this view can take focus, or false otherwise.
   11612      */
   11613     @ViewDebug.ExportedProperty(category = "focus")
   11614     public final boolean isFocusable() {
   11615         return FOCUSABLE == (mViewFlags & FOCUSABLE);
   11616     }
   11617 
   11618     /**
   11619      * Returns the focusable setting for this view.
   11620      *
   11621      * @return One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE}, or {@link #FOCUSABLE_AUTO}.
   11622      * @attr ref android.R.styleable#View_focusable
   11623      */
   11624     @ViewDebug.ExportedProperty(mapping = {
   11625             @ViewDebug.IntToString(from = NOT_FOCUSABLE, to = "NOT_FOCUSABLE"),
   11626             @ViewDebug.IntToString(from = FOCUSABLE, to = "FOCUSABLE"),
   11627             @ViewDebug.IntToString(from = FOCUSABLE_AUTO, to = "FOCUSABLE_AUTO")
   11628             }, category = "focus")
   11629     @InspectableProperty(enumMapping = {
   11630             @EnumEntry(value = NOT_FOCUSABLE, name = "false"),
   11631             @EnumEntry(value = FOCUSABLE, name = "true"),
   11632             @EnumEntry(value = FOCUSABLE_AUTO, name = "auto")
   11633     })
   11634     @Focusable
   11635     public int getFocusable() {
   11636         return (mViewFlags & FOCUSABLE_AUTO) > 0 ? FOCUSABLE_AUTO : mViewFlags & FOCUSABLE;
   11637     }
   11638 
   11639     /**
   11640      * When a view is focusable, it may not want to take focus when in touch mode.
   11641      * For example, a button would like focus when the user is navigating via a D-pad
   11642      * so that the user can click on it, but once the user starts touching the screen,
   11643      * the button shouldn't take focus
   11644      * @return Whether the view is focusable in touch mode.
   11645      * @attr ref android.R.styleable#View_focusableInTouchMode
   11646      */
   11647     @ViewDebug.ExportedProperty(category = "focus")
   11648     @InspectableProperty
   11649     public final boolean isFocusableInTouchMode() {
   11650         return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
   11651     }
   11652 
   11653     /**
   11654      * Returns whether the view should be treated as a focusable unit by screen reader
   11655      * accessibility tools.
   11656      * @see #setScreenReaderFocusable(boolean)
   11657      *
   11658      * @return Whether the view should be treated as a focusable unit by screen reader.
   11659      *
   11660      * @attr ref android.R.styleable#View_screenReaderFocusable
   11661      */
   11662     @InspectableProperty
   11663     public boolean isScreenReaderFocusable() {
   11664         return (mPrivateFlags3 & PFLAG3_SCREEN_READER_FOCUSABLE) != 0;
   11665     }
   11666 
   11667     /**
   11668      * Sets whether this View should be a focusable element for screen readers
   11669      * and include non-focusable Views from its subtree when providing feedback.
   11670      * <p>
   11671      * Note: this is similar to using <a href="#attr_android:focusable">{@code android:focusable},
   11672      * but does not impact input focus behavior.
   11673      *
   11674      * @param screenReaderFocusable Whether the view should be treated as a unit by screen reader
   11675      *                              accessibility tools.
   11676      *
   11677      * @attr ref android.R.styleable#View_screenReaderFocusable
   11678      */
   11679     public void setScreenReaderFocusable(boolean screenReaderFocusable) {
   11680         updatePflags3AndNotifyA11yIfChanged(PFLAG3_SCREEN_READER_FOCUSABLE, screenReaderFocusable);
   11681     }
   11682 
   11683     /**
   11684      * Gets whether this view is a heading for accessibility purposes.
   11685      *
   11686      * @return {@code true} if the view is a heading, {@code false} otherwise.
   11687      *
   11688      * @attr ref android.R.styleable#View_accessibilityHeading
   11689      */
   11690     @InspectableProperty
   11691     public boolean isAccessibilityHeading() {
   11692         return (mPrivateFlags3 & PFLAG3_ACCESSIBILITY_HEADING) != 0;
   11693     }
   11694 
   11695     /**
   11696      * Set if view is a heading for a section of content for accessibility purposes.
   11697      *
   11698      * @param isHeading {@code true} if the view is a heading, {@code false} otherwise.
   11699      *
   11700      * @attr ref android.R.styleable#View_accessibilityHeading
   11701      */
   11702     public void setAccessibilityHeading(boolean isHeading) {
   11703         updatePflags3AndNotifyA11yIfChanged(PFLAG3_ACCESSIBILITY_HEADING, isHeading);
   11704     }
   11705 
   11706     private void updatePflags3AndNotifyA11yIfChanged(int mask, boolean newValue) {
   11707         int pflags3 = mPrivateFlags3;
   11708         if (newValue) {
   11709             pflags3 |= mask;
   11710         } else {
   11711             pflags3 &= ~mask;
   11712         }
   11713 
   11714         if (pflags3 != mPrivateFlags3) {
   11715             mPrivateFlags3 = pflags3;
   11716             notifyViewAccessibilityStateChangedIfNeeded(
   11717                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   11718         }
   11719     }
   11720 
   11721     /**
   11722      * Find the nearest view in the specified direction that can take focus.
   11723      * This does not actually give focus to that view.
   11724      *
   11725      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
   11726      *
   11727      * @return The nearest focusable in the specified direction, or null if none
   11728      *         can be found.
   11729      */
   11730     public View focusSearch(@FocusRealDirection int direction) {
   11731         if (mParent != null) {
   11732             return mParent.focusSearch(this, direction);
   11733         } else {
   11734             return null;
   11735         }
   11736     }
   11737 
   11738     /**
   11739      * Returns whether this View is a root of a keyboard navigation cluster.
   11740      *
   11741      * @return True if this view is a root of a cluster, or false otherwise.
   11742      * @attr ref android.R.styleable#View_keyboardNavigationCluster
   11743      */
   11744     @ViewDebug.ExportedProperty(category = "focus")
   11745     @InspectableProperty
   11746     public final boolean isKeyboardNavigationCluster() {
   11747         return (mPrivateFlags3 & PFLAG3_CLUSTER) != 0;
   11748     }
   11749 
   11750     /**
   11751      * Searches up the view hierarchy to find the top-most cluster. All deeper/nested clusters
   11752      * will be ignored.
   11753      *
   11754      * @return the keyboard navigation cluster that this view is in (can be this view)
   11755      *         or {@code null} if not in one
   11756      */
   11757     View findKeyboardNavigationCluster() {
   11758         if (mParent instanceof View) {
   11759             View cluster = ((View) mParent).findKeyboardNavigationCluster();
   11760             if (cluster != null) {
   11761                 return cluster;
   11762             } else if (isKeyboardNavigationCluster()) {
   11763                 return this;
   11764             }
   11765         }
   11766         return null;
   11767     }
   11768 
   11769     /**
   11770      * Set whether this view is a root of a keyboard navigation cluster.
   11771      *
   11772      * @param isCluster If true, this view is a root of a cluster.
   11773      *
   11774      * @attr ref android.R.styleable#View_keyboardNavigationCluster
   11775      */
   11776     public void setKeyboardNavigationCluster(boolean isCluster) {
   11777         if (isCluster) {
   11778             mPrivateFlags3 |= PFLAG3_CLUSTER;
   11779         } else {
   11780             mPrivateFlags3 &= ~PFLAG3_CLUSTER;
   11781         }
   11782     }
   11783 
   11784     /**
   11785      * Sets this View as the one which receives focus the next time cluster navigation jumps
   11786      * to the cluster containing this View. This does NOT change focus even if the cluster
   11787      * containing this view is current.
   11788      *
   11789      * @hide
   11790      */
   11791     @TestApi
   11792     public final void setFocusedInCluster() {
   11793         setFocusedInCluster(findKeyboardNavigationCluster());
   11794     }
   11795 
   11796     private void setFocusedInCluster(View cluster) {
   11797         if (this instanceof ViewGroup) {
   11798             ((ViewGroup) this).mFocusedInCluster = null;
   11799         }
   11800         if (cluster == this) {
   11801             return;
   11802         }
   11803         ViewParent parent = mParent;
   11804         View child = this;
   11805         while (parent instanceof ViewGroup) {
   11806             ((ViewGroup) parent).mFocusedInCluster = child;
   11807             if (parent == cluster) {
   11808                 break;
   11809             }
   11810             child = (View) parent;
   11811             parent = parent.getParent();
   11812         }
   11813     }
   11814 
   11815     private void updateFocusedInCluster(View oldFocus, @FocusDirection int direction) {
   11816         if (oldFocus != null) {
   11817             View oldCluster = oldFocus.findKeyboardNavigationCluster();
   11818             View cluster = findKeyboardNavigationCluster();
   11819             if (oldCluster != cluster) {
   11820                 // Going from one cluster to another, so save last-focused.
   11821                 // This covers cluster jumps because they are always FOCUS_DOWN
   11822                 oldFocus.setFocusedInCluster(oldCluster);
   11823                 if (!(oldFocus.mParent instanceof ViewGroup)) {
   11824                     return;
   11825                 }
   11826                 if (direction == FOCUS_FORWARD || direction == FOCUS_BACKWARD) {
   11827                     // This is a result of ordered navigation so consider navigation through
   11828                     // the previous cluster "complete" and clear its last-focused memory.
   11829                     ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
   11830                 } else if (oldFocus instanceof ViewGroup
   11831                         && ((ViewGroup) oldFocus).getDescendantFocusability()
   11832                                 == ViewGroup.FOCUS_AFTER_DESCENDANTS
   11833                         && ViewRootImpl.isViewDescendantOf(this, oldFocus)) {
   11834                     // This means oldFocus is not focusable since it obviously has a focusable
   11835                     // child (this). Don't restore focus to it in the future.
   11836                     ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
   11837                 }
   11838             }
   11839         }
   11840     }
   11841 
   11842     /**
   11843      * Returns whether this View should receive focus when the focus is restored for the view
   11844      * hierarchy containing this view.
   11845      * <p>
   11846      * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
   11847      * window or serves as a target of cluster navigation.
   11848      *
   11849      * @see #restoreDefaultFocus()
   11850      *
   11851      * @return {@code true} if this view is the default-focus view, {@code false} otherwise
   11852      * @attr ref android.R.styleable#View_focusedByDefault
   11853      */
   11854     @ViewDebug.ExportedProperty(category = "focus")
   11855     @InspectableProperty
   11856     public final boolean isFocusedByDefault() {
   11857         return (mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0;
   11858     }
   11859 
   11860     /**
   11861      * Sets whether this View should receive focus when the focus is restored for the view
   11862      * hierarchy containing this view.
   11863      * <p>
   11864      * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
   11865      * window or serves as a target of cluster navigation.
   11866      *
   11867      * @param isFocusedByDefault {@code true} to set this view as the default-focus view,
   11868      *                           {@code false} otherwise.
   11869      *
   11870      * @see #restoreDefaultFocus()
   11871      *
   11872      * @attr ref android.R.styleable#View_focusedByDefault
   11873      */
   11874     public void setFocusedByDefault(boolean isFocusedByDefault) {
   11875         if (isFocusedByDefault == ((mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0)) {
   11876             return;
   11877         }
   11878 
   11879         if (isFocusedByDefault) {
   11880             mPrivateFlags3 |= PFLAG3_FOCUSED_BY_DEFAULT;
   11881         } else {
   11882             mPrivateFlags3 &= ~PFLAG3_FOCUSED_BY_DEFAULT;
   11883         }
   11884 
   11885         if (mParent instanceof ViewGroup) {
   11886             if (isFocusedByDefault) {
   11887                 ((ViewGroup) mParent).setDefaultFocus(this);
   11888             } else {
   11889                 ((ViewGroup) mParent).clearDefaultFocus(this);
   11890             }
   11891         }
   11892     }
   11893 
   11894     /**
   11895      * Returns whether the view hierarchy with this view as a root contain a default-focus view.
   11896      *
   11897      * @return {@code true} if this view has default focus, {@code false} otherwise
   11898      */
   11899     boolean hasDefaultFocus() {
   11900         return isFocusedByDefault();
   11901     }
   11902 
   11903     /**
   11904      * Find the nearest keyboard navigation cluster in the specified direction.
   11905      * This does not actually give focus to that cluster.
   11906      *
   11907      * @param currentCluster The starting point of the search. Null means the current cluster is not
   11908      *                       found yet
   11909      * @param direction Direction to look
   11910      *
   11911      * @return The nearest keyboard navigation cluster in the specified direction, or null if none
   11912      *         can be found
   11913      */
   11914     public View keyboardNavigationClusterSearch(View currentCluster,
   11915             @FocusDirection int direction) {
   11916         if (isKeyboardNavigationCluster()) {
   11917             currentCluster = this;
   11918         }
   11919         if (isRootNamespace()) {
   11920             // Root namespace means we should consider ourselves the top of the
   11921             // tree for group searching; otherwise we could be group searching
   11922             // into other tabs.  see LocalActivityManager and TabHost for more info.
   11923             return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
   11924                     this, currentCluster, direction);
   11925         } else if (mParent != null) {
   11926             return mParent.keyboardNavigationClusterSearch(currentCluster, direction);
   11927         }
   11928         return null;
   11929     }
   11930 
   11931     /**
   11932      * This method is the last chance for the focused view and its ancestors to
   11933      * respond to an arrow key. This is called when the focused view did not
   11934      * consume the key internally, nor could the view system find a new view in
   11935      * the requested direction to give focus to.
   11936      *
   11937      * @param focused The currently focused view.
   11938      * @param direction The direction focus wants to move. One of FOCUS_UP,
   11939      *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
   11940      * @return True if the this view consumed this unhandled move.
   11941      */
   11942     public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
   11943         return false;
   11944     }
   11945 
   11946     /**
   11947      * Sets whether this View should use a default focus highlight when it gets focused but doesn't
   11948      * have {@link android.R.attr#state_focused} defined in its background.
   11949      *
   11950      * @param defaultFocusHighlightEnabled {@code true} to set this view to use a default focus
   11951      *                                      highlight, {@code false} otherwise.
   11952      *
   11953      * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
   11954      */
   11955     public void setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled) {
   11956         mDefaultFocusHighlightEnabled = defaultFocusHighlightEnabled;
   11957     }
   11958 
   11959     /**
   11960 
   11961     /**
   11962      * Returns whether this View should use a default focus highlight when it gets focused but
   11963      * doesn't have {@link android.R.attr#state_focused} defined in its background.
   11964      *
   11965      * @return True if this View should use a default focus highlight.
   11966      * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
   11967      */
   11968     @ViewDebug.ExportedProperty(category = "focus")
   11969     @InspectableProperty
   11970     public final boolean getDefaultFocusHighlightEnabled() {
   11971         return mDefaultFocusHighlightEnabled;
   11972     }
   11973 
   11974     /**
   11975      * If a user manually specified the next view id for a particular direction,
   11976      * use the root to look up the view.
   11977      * @param root The root view of the hierarchy containing this view.
   11978      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
   11979      * or FOCUS_BACKWARD.
   11980      * @return The user specified next view, or null if there is none.
   11981      */
   11982     View findUserSetNextFocus(View root, @FocusDirection int direction) {
   11983         switch (direction) {
   11984             case FOCUS_LEFT:
   11985                 if (mNextFocusLeftId == View.NO_ID) return null;
   11986                 return findViewInsideOutShouldExist(root, mNextFocusLeftId);
   11987             case FOCUS_RIGHT:
   11988                 if (mNextFocusRightId == View.NO_ID) return null;
   11989                 return findViewInsideOutShouldExist(root, mNextFocusRightId);
   11990             case FOCUS_UP:
   11991                 if (mNextFocusUpId == View.NO_ID) return null;
   11992                 return findViewInsideOutShouldExist(root, mNextFocusUpId);
   11993             case FOCUS_DOWN:
   11994                 if (mNextFocusDownId == View.NO_ID) return null;
   11995                 return findViewInsideOutShouldExist(root, mNextFocusDownId);
   11996             case FOCUS_FORWARD:
   11997                 if (mNextFocusForwardId == View.NO_ID) return null;
   11998                 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
   11999             case FOCUS_BACKWARD: {
   12000                 if (mID == View.NO_ID) return null;
   12001                 final int id = mID;
   12002                 return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
   12003                     @Override
   12004                     public boolean test(View t) {
   12005                         return t.mNextFocusForwardId == id;
   12006                     }
   12007                 });
   12008             }
   12009         }
   12010         return null;
   12011     }
   12012 
   12013     /**
   12014      * If a user manually specified the next keyboard-navigation cluster for a particular direction,
   12015      * use the root to look up the view.
   12016      *
   12017      * @param root the root view of the hierarchy containing this view
   12018      * @param direction {@link #FOCUS_FORWARD} or {@link #FOCUS_BACKWARD}
   12019      * @return the user-specified next cluster, or {@code null} if there is none
   12020      */
   12021     View findUserSetNextKeyboardNavigationCluster(View root, @FocusDirection int direction) {
   12022         switch (direction) {
   12023             case FOCUS_FORWARD:
   12024                 if (mNextClusterForwardId == View.NO_ID) return null;
   12025                 return findViewInsideOutShouldExist(root, mNextClusterForwardId);
   12026             case FOCUS_BACKWARD: {
   12027                 if (mID == View.NO_ID) return null;
   12028                 final int id = mID;
   12029                 return root.findViewByPredicateInsideOut(this,
   12030                         (Predicate<View>) t -> t.mNextClusterForwardId == id);
   12031             }
   12032         }
   12033         return null;
   12034     }
   12035 
   12036     private View findViewInsideOutShouldExist(View root, int id) {
   12037         if (mMatchIdPredicate == null) {
   12038             mMatchIdPredicate = new MatchIdPredicate();
   12039         }
   12040         mMatchIdPredicate.mId = id;
   12041         View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
   12042         if (result == null) {
   12043             Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
   12044         }
   12045         return result;
   12046     }
   12047 
   12048     /**
   12049      * Find and return all focusable views that are descendants of this view,
   12050      * possibly including this view if it is focusable itself.
   12051      *
   12052      * @param direction The direction of the focus
   12053      * @return A list of focusable views
   12054      */
   12055     public ArrayList<View> getFocusables(@FocusDirection int direction) {
   12056         ArrayList<View> result = new ArrayList<View>(24);
   12057         addFocusables(result, direction);
   12058         return result;
   12059     }
   12060 
   12061     /**
   12062      * Add any focusable views that are descendants of this view (possibly
   12063      * including this view if it is focusable itself) to views.  If we are in touch mode,
   12064      * only add views that are also focusable in touch mode.
   12065      *
   12066      * @param views Focusable views found so far
   12067      * @param direction The direction of the focus
   12068      */
   12069     public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
   12070         addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
   12071     }
   12072 
   12073     /**
   12074      * Adds any focusable views that are descendants of this view (possibly
   12075      * including this view if it is focusable itself) to views. This method
   12076      * adds all focusable views regardless if we are in touch mode or
   12077      * only views focusable in touch mode if we are in touch mode or
   12078      * only views that can take accessibility focus if accessibility is enabled
   12079      * depending on the focusable mode parameter.
   12080      *
   12081      * @param views Focusable views found so far or null if all we are interested is
   12082      *        the number of focusables.
   12083      * @param direction The direction of the focus.
   12084      * @param focusableMode The type of focusables to be added.
   12085      *
   12086      * @see #FOCUSABLES_ALL
   12087      * @see #FOCUSABLES_TOUCH_MODE
   12088      */
   12089     public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
   12090             @FocusableMode int focusableMode) {
   12091         if (views == null) {
   12092             return;
   12093         }
   12094         if (!canTakeFocus()) {
   12095             return;
   12096         }
   12097         if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
   12098                 && !isFocusableInTouchMode()) {
   12099             return;
   12100         }
   12101         views.add(this);
   12102     }
   12103 
   12104     /**
   12105      * Adds any keyboard navigation cluster roots that are descendants of this view (possibly
   12106      * including this view if it is a cluster root itself) to views.
   12107      *
   12108      * @param views Keyboard navigation cluster roots found so far
   12109      * @param direction Direction to look
   12110      */
   12111     public void addKeyboardNavigationClusters(
   12112             @NonNull Collection<View> views,
   12113             int direction) {
   12114         if (!isKeyboardNavigationCluster()) {
   12115             return;
   12116         }
   12117         if (!hasFocusable()) {
   12118             return;
   12119         }
   12120         views.add(this);
   12121     }
   12122 
   12123     /**
   12124      * Finds the Views that contain given text. The containment is case insensitive.
   12125      * The search is performed by either the text that the View renders or the content
   12126      * description that describes the view for accessibility purposes and the view does
   12127      * not render or both. Clients can specify how the search is to be performed via
   12128      * passing the {@link #FIND_VIEWS_WITH_TEXT} and
   12129      * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
   12130      *
   12131      * @param outViews The output list of matching Views.
   12132      * @param searched The text to match against.
   12133      *
   12134      * @see #FIND_VIEWS_WITH_TEXT
   12135      * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
   12136      * @see #setContentDescription(CharSequence)
   12137      */
   12138     public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
   12139             @FindViewFlags int flags) {
   12140         if (getAccessibilityNodeProvider() != null) {
   12141             if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
   12142                 outViews.add(this);
   12143             }
   12144         } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
   12145                 && (searched != null && searched.length() > 0)
   12146                 && (mContentDescription != null && mContentDescription.length() > 0)) {
   12147             String searchedLowerCase = searched.toString().toLowerCase();
   12148             String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
   12149             if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
   12150                 outViews.add(this);
   12151             }
   12152         }
   12153     }
   12154 
   12155     /**
   12156      * Find and return all touchable views that are descendants of this view,
   12157      * possibly including this view if it is touchable itself.
   12158      *
   12159      * @return A list of touchable views
   12160      */
   12161     public ArrayList<View> getTouchables() {
   12162         ArrayList<View> result = new ArrayList<View>();
   12163         addTouchables(result);
   12164         return result;
   12165     }
   12166 
   12167     /**
   12168      * Add any touchable views that are descendants of this view (possibly
   12169      * including this view if it is touchable itself) to views.
   12170      *
   12171      * @param views Touchable views found so far
   12172      */
   12173     public void addTouchables(ArrayList<View> views) {
   12174         final int viewFlags = mViewFlags;
   12175 
   12176         if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
   12177                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
   12178                 && (viewFlags & ENABLED_MASK) == ENABLED) {
   12179             views.add(this);
   12180         }
   12181     }
   12182 
   12183     /**
   12184      * Returns whether this View is accessibility focused.
   12185      *
   12186      * @return True if this View is accessibility focused.
   12187      */
   12188     @InspectableProperty(hasAttributeId = false)
   12189     public boolean isAccessibilityFocused() {
   12190         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
   12191     }
   12192 
   12193     /**
   12194      * Call this to try to give accessibility focus to this view.
   12195      *
   12196      * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
   12197      * returns false or the view is no visible or the view already has accessibility
   12198      * focus.
   12199      *
   12200      * See also {@link #focusSearch(int)}, which is what you call to say that you
   12201      * have focus, and you want your parent to look for the next one.
   12202      *
   12203      * @return Whether this view actually took accessibility focus.
   12204      *
   12205      * @hide
   12206      */
   12207     @UnsupportedAppUsage
   12208     public boolean requestAccessibilityFocus() {
   12209         AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
   12210         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
   12211             return false;
   12212         }
   12213         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
   12214             return false;
   12215         }
   12216         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
   12217             mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
   12218             ViewRootImpl viewRootImpl = getViewRootImpl();
   12219             if (viewRootImpl != null) {
   12220                 viewRootImpl.setAccessibilityFocus(this, null);
   12221             }
   12222             invalidate();
   12223             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
   12224             return true;
   12225         }
   12226         return false;
   12227     }
   12228 
   12229     /**
   12230      * Call this to try to clear accessibility focus of this view.
   12231      *
   12232      * See also {@link #focusSearch(int)}, which is what you call to say that you
   12233      * have focus, and you want your parent to look for the next one.
   12234      *
   12235      * @hide
   12236      */
   12237     @UnsupportedAppUsage
   12238     public void clearAccessibilityFocus() {
   12239         clearAccessibilityFocusNoCallbacks(0);
   12240 
   12241         // Clear the global reference of accessibility focus if this view or
   12242         // any of its descendants had accessibility focus. This will NOT send
   12243         // an event or update internal state if focus is cleared from a
   12244         // descendant view, which may leave views in inconsistent states.
   12245         final ViewRootImpl viewRootImpl = getViewRootImpl();
   12246         if (viewRootImpl != null) {
   12247             final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
   12248             if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
   12249                 viewRootImpl.setAccessibilityFocus(null, null);
   12250             }
   12251         }
   12252     }
   12253 
   12254     private void sendAccessibilityHoverEvent(int eventType) {
   12255         // Since we are not delivering to a client accessibility events from not
   12256         // important views (unless the clinet request that) we need to fire the
   12257         // event from the deepest view exposed to the client. As a consequence if
   12258         // the user crosses a not exposed view the client will see enter and exit
   12259         // of the exposed predecessor followed by and enter and exit of that same
   12260         // predecessor when entering and exiting the not exposed descendant. This
   12261         // is fine since the client has a clear idea which view is hovered at the
   12262         // price of a couple more events being sent. This is a simple and
   12263         // working solution.
   12264         View source = this;
   12265         while (true) {
   12266             if (source.includeForAccessibility()) {
   12267                 source.sendAccessibilityEvent(eventType);
   12268                 return;
   12269             }
   12270             ViewParent parent = source.getParent();
   12271             if (parent instanceof View) {
   12272                 source = (View) parent;
   12273             } else {
   12274                 return;
   12275             }
   12276         }
   12277     }
   12278 
   12279     /**
   12280      * Clears accessibility focus without calling any callback methods
   12281      * normally invoked in {@link #clearAccessibilityFocus()}. This method
   12282      * is used separately from that one for clearing accessibility focus when
   12283      * giving this focus to another view.
   12284      *
   12285      * @param action The action, if any, that led to focus being cleared. Set to
   12286      * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
   12287      * the window.
   12288      */
   12289     void clearAccessibilityFocusNoCallbacks(int action) {
   12290         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
   12291             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
   12292             invalidate();
   12293             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
   12294                 AccessibilityEvent event = AccessibilityEvent.obtain(
   12295                         AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
   12296                 event.setAction(action);
   12297                 if (mAccessibilityDelegate != null) {
   12298                     mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
   12299                 } else {
   12300                     sendAccessibilityEventUnchecked(event);
   12301                 }
   12302             }
   12303         }
   12304     }
   12305 
   12306     /**
   12307      * Call this to try to give focus to a specific view or to one of its
   12308      * descendants.
   12309      *
   12310      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
   12311      * false), or if it can't be focused due to other conditions (not focusable in touch mode
   12312      * ({@link #isFocusableInTouchMode}) while the device is in touch mode, not visible, not
   12313      * enabled, or has no size).
   12314      *
   12315      * See also {@link #focusSearch(int)}, which is what you call to say that you
   12316      * have focus, and you want your parent to look for the next one.
   12317      *
   12318      * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
   12319      * {@link #FOCUS_DOWN} and <code>null</code>.
   12320      *
   12321      * @return Whether this view or one of its descendants actually took focus.
   12322      */
   12323     public final boolean requestFocus() {
   12324         return requestFocus(View.FOCUS_DOWN);
   12325     }
   12326 
   12327     /**
   12328      * This will request focus for whichever View was last focused within this
   12329      * cluster before a focus-jump out of it.
   12330      *
   12331      * @hide
   12332      */
   12333     @TestApi
   12334     public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
   12335         // Prioritize focusableByDefault over algorithmic focus selection.
   12336         if (restoreDefaultFocus()) {
   12337             return true;
   12338         }
   12339         return requestFocus(direction);
   12340     }
   12341 
   12342     /**
   12343      * This will request focus for whichever View not in a cluster was last focused before a
   12344      * focus-jump to a cluster. If no non-cluster View has previously had focus, this will focus
   12345      * the "first" focusable view it finds.
   12346      *
   12347      * @hide
   12348      */
   12349     @TestApi
   12350     public boolean restoreFocusNotInCluster() {
   12351         return requestFocus(View.FOCUS_DOWN);
   12352     }
   12353 
   12354     /**
   12355      * Gives focus to the default-focus view in the view hierarchy that has this view as a root.
   12356      * If the default-focus view cannot be found, falls back to calling {@link #requestFocus(int)}.
   12357      *
   12358      * @return Whether this view or one of its descendants actually took focus
   12359      */
   12360     public boolean restoreDefaultFocus() {
   12361         return requestFocus(View.FOCUS_DOWN);
   12362     }
   12363 
   12364     /**
   12365      * Call this to try to give focus to a specific view or to one of its
   12366      * descendants and give it a hint about what direction focus is heading.
   12367      *
   12368      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
   12369      * false), or if it is focusable and it is not focusable in touch mode
   12370      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
   12371      *
   12372      * See also {@link #focusSearch(int)}, which is what you call to say that you
   12373      * have focus, and you want your parent to look for the next one.
   12374      *
   12375      * This is equivalent to calling {@link #requestFocus(int, Rect)} with
   12376      * <code>null</code> set for the previously focused rectangle.
   12377      *
   12378      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
   12379      * @return Whether this view or one of its descendants actually took focus.
   12380      */
   12381     public final boolean requestFocus(int direction) {
   12382         return requestFocus(direction, null);
   12383     }
   12384 
   12385     /**
   12386      * Call this to try to give focus to a specific view or to one of its descendants
   12387      * and give it hints about the direction and a specific rectangle that the focus
   12388      * is coming from.  The rectangle can help give larger views a finer grained hint
   12389      * about where focus is coming from, and therefore, where to show selection, or
   12390      * forward focus change internally.
   12391      *
   12392      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
   12393      * false), or if it is focusable and it is not focusable in touch mode
   12394      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
   12395      *
   12396      * A View will not take focus if it is not visible.
   12397      *
   12398      * A View will not take focus if one of its parents has
   12399      * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
   12400      * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
   12401      *
   12402      * See also {@link #focusSearch(int)}, which is what you call to say that you
   12403      * have focus, and you want your parent to look for the next one.
   12404      *
   12405      * You may wish to override this method if your custom {@link View} has an internal
   12406      * {@link View} that it wishes to forward the request to.
   12407      *
   12408      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
   12409      * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
   12410      *        to give a finer grained hint about where focus is coming from.  May be null
   12411      *        if there is no hint.
   12412      * @return Whether this view or one of its descendants actually took focus.
   12413      */
   12414     public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
   12415         return requestFocusNoSearch(direction, previouslyFocusedRect);
   12416     }
   12417 
   12418     private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
   12419         // need to be focusable
   12420         if (!canTakeFocus()) {
   12421             return false;
   12422         }
   12423 
   12424         // need to be focusable in touch mode if in touch mode
   12425         if (isInTouchMode() &&
   12426             (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
   12427                return false;
   12428         }
   12429 
   12430         // need to not have any parents blocking us
   12431         if (hasAncestorThatBlocksDescendantFocus()) {
   12432             return false;
   12433         }
   12434 
   12435         if (!isLayoutValid()) {
   12436             mPrivateFlags |= PFLAG_WANTS_FOCUS;
   12437         } else {
   12438             clearParentsWantFocus();
   12439         }
   12440 
   12441         handleFocusGainInternal(direction, previouslyFocusedRect);
   12442         return true;
   12443     }
   12444 
   12445     void clearParentsWantFocus() {
   12446         if (mParent instanceof View) {
   12447             ((View) mParent).mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
   12448             ((View) mParent).clearParentsWantFocus();
   12449         }
   12450     }
   12451 
   12452     /**
   12453      * Call this to try to give focus to a specific view or to one of its descendants. This is a
   12454      * special variant of {@link #requestFocus() } that will allow views that are not focusable in
   12455      * touch mode to request focus when they are touched.
   12456      *
   12457      * @return Whether this view or one of its descendants actually took focus.
   12458      *
   12459      * @see #isInTouchMode()
   12460      *
   12461      */
   12462     public final boolean requestFocusFromTouch() {
   12463         // Leave touch mode if we need to
   12464         if (isInTouchMode()) {
   12465             ViewRootImpl viewRoot = getViewRootImpl();
   12466             if (viewRoot != null) {
   12467                 viewRoot.ensureTouchMode(false);
   12468             }
   12469         }
   12470         return requestFocus(View.FOCUS_DOWN);
   12471     }
   12472 
   12473     /**
   12474      * @return Whether any ancestor of this view blocks descendant focus.
   12475      */
   12476     private boolean hasAncestorThatBlocksDescendantFocus() {
   12477         final boolean focusableInTouchMode = isFocusableInTouchMode();
   12478         ViewParent ancestor = mParent;
   12479         while (ancestor instanceof ViewGroup) {
   12480             final ViewGroup vgAncestor = (ViewGroup) ancestor;
   12481             if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
   12482                     || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
   12483                 return true;
   12484             } else {
   12485                 ancestor = vgAncestor.getParent();
   12486             }
   12487         }
   12488         return false;
   12489     }
   12490 
   12491     /**
   12492      * Gets the mode for determining whether this View is important for accessibility.
   12493      * A view is important for accessibility if it fires accessibility events and if it
   12494      * is reported to accessibility services that query the screen.
   12495      *
   12496      * @return The mode for determining whether a view is important for accessibility, one
   12497      * of {@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, {@link #IMPORTANT_FOR_ACCESSIBILITY_YES},
   12498      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO}, or
   12499      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}.
   12500      *
   12501      * @attr ref android.R.styleable#View_importantForAccessibility
   12502      *
   12503      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
   12504      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
   12505      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
   12506      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
   12507      */
   12508     @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
   12509             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
   12510             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
   12511             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
   12512             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
   12513                     to = "noHideDescendants")
   12514         })
   12515     @InspectableProperty(enumMapping = {
   12516             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_AUTO, name = "auto"),
   12517             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_YES, name = "yes"),
   12518             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_NO, name = "no"),
   12519             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
   12520                     name = "noHideDescendants"),
   12521     })
   12522     public int getImportantForAccessibility() {
   12523         return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
   12524                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
   12525     }
   12526 
   12527     /**
   12528      * Sets the live region mode for this view. This indicates to accessibility
   12529      * services whether they should automatically notify the user about changes
   12530      * to the view's content description or text, or to the content descriptions
   12531      * or text of the view's children (where applicable).
   12532      * <p>
   12533      * For example, in a login screen with a TextView that displays an "incorrect
   12534      * password" notification, that view should be marked as a live region with
   12535      * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
   12536      * <p>
   12537      * To disable change notifications for this view, use
   12538      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
   12539      * mode for most views.
   12540      * <p>
   12541      * To indicate that the user should be notified of changes, use
   12542      * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
   12543      * <p>
   12544      * If the view's changes should interrupt ongoing speech and notify the user
   12545      * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
   12546      *
   12547      * @param mode The live region mode for this view, one of:
   12548      *        <ul>
   12549      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
   12550      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
   12551      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
   12552      *        </ul>
   12553      * @attr ref android.R.styleable#View_accessibilityLiveRegion
   12554      */
   12555     public void setAccessibilityLiveRegion(int mode) {
   12556         if (mode != getAccessibilityLiveRegion()) {
   12557             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
   12558             mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
   12559                     & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
   12560             notifyViewAccessibilityStateChangedIfNeeded(
   12561                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   12562         }
   12563     }
   12564 
   12565     /**
   12566      * Gets the live region mode for this View.
   12567      *
   12568      * @return The live region mode for the view.
   12569      *
   12570      * @attr ref android.R.styleable#View_accessibilityLiveRegion
   12571      *
   12572      * @see #setAccessibilityLiveRegion(int)
   12573      */
   12574     @InspectableProperty(enumMapping = {
   12575             @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_NONE, name = "none"),
   12576             @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_POLITE, name = "polite"),
   12577             @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_ASSERTIVE, name = "assertive")
   12578     })
   12579     public int getAccessibilityLiveRegion() {
   12580         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
   12581                 >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
   12582     }
   12583 
   12584     /**
   12585      * Sets how to determine whether this view is important for accessibility
   12586      * which is if it fires accessibility events and if it is reported to
   12587      * accessibility services that query the screen.
   12588      *
   12589      * @param mode How to determine whether this view is important for accessibility.
   12590      *
   12591      * @attr ref android.R.styleable#View_importantForAccessibility
   12592      *
   12593      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
   12594      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
   12595      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
   12596      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
   12597      */
   12598     public void setImportantForAccessibility(int mode) {
   12599         final int oldMode = getImportantForAccessibility();
   12600         if (mode != oldMode) {
   12601             final boolean hideDescendants =
   12602                     mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
   12603 
   12604             // If this node or its descendants are no longer important, try to
   12605             // clear accessibility focus.
   12606             if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
   12607                 final View focusHost = findAccessibilityFocusHost(hideDescendants);
   12608                 if (focusHost != null) {
   12609                     focusHost.clearAccessibilityFocus();
   12610                 }
   12611             }
   12612 
   12613             // If we're moving between AUTO and another state, we might not need
   12614             // to send a subtree changed notification. We'll store the computed
   12615             // importance, since we'll need to check it later to make sure.
   12616             final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
   12617                     || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
   12618             final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
   12619             mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
   12620             mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
   12621                     & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
   12622             if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
   12623                 notifySubtreeAccessibilityStateChangedIfNeeded();
   12624             } else {
   12625                 notifyViewAccessibilityStateChangedIfNeeded(
   12626                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   12627             }
   12628         }
   12629     }
   12630 
   12631     /**
   12632      * Returns the view within this view's hierarchy that is hosting
   12633      * accessibility focus.
   12634      *
   12635      * @param searchDescendants whether to search for focus in descendant views
   12636      * @return the view hosting accessibility focus, or {@code null}
   12637      */
   12638     private View findAccessibilityFocusHost(boolean searchDescendants) {
   12639         if (isAccessibilityFocusedViewOrHost()) {
   12640             return this;
   12641         }
   12642 
   12643         if (searchDescendants) {
   12644             final ViewRootImpl viewRoot = getViewRootImpl();
   12645             if (viewRoot != null) {
   12646                 final View focusHost = viewRoot.getAccessibilityFocusedHost();
   12647                 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
   12648                     return focusHost;
   12649                 }
   12650             }
   12651         }
   12652 
   12653         return null;
   12654     }
   12655 
   12656     /**
   12657      * Computes whether this view should be exposed for accessibility. In
   12658      * general, views that are interactive or provide information are exposed
   12659      * while views that serve only as containers are hidden.
   12660      * <p>
   12661      * If an ancestor of this view has importance
   12662      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
   12663      * returns <code>false</code>.
   12664      * <p>
   12665      * Otherwise, the value is computed according to the view's
   12666      * {@link #getImportantForAccessibility()} value:
   12667      * <ol>
   12668      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
   12669      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
   12670      * </code>
   12671      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
   12672      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
   12673      * view satisfies any of the following:
   12674      * <ul>
   12675      * <li>Is actionable, e.g. {@link #isClickable()},
   12676      * {@link #isLongClickable()}, or {@link #isFocusable()}
   12677      * <li>Has an {@link AccessibilityDelegate}
   12678      * <li>Has an interaction listener, e.g. {@link OnTouchListener},
   12679      * {@link OnKeyListener}, etc.
   12680      * <li>Is an accessibility live region, e.g.
   12681      * {@link #getAccessibilityLiveRegion()} is not
   12682      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
   12683      * </ul>
   12684      * <li>Has an accessibility pane title, see {@link #setAccessibilityPaneTitle}</li>
   12685      * </ol>
   12686      *
   12687      * @return Whether the view is exposed for accessibility.
   12688      * @see #setImportantForAccessibility(int)
   12689      * @see #getImportantForAccessibility()
   12690      */
   12691     public boolean isImportantForAccessibility() {
   12692         final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
   12693                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
   12694         if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
   12695                 || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
   12696             return false;
   12697         }
   12698 
   12699         // Check parent mode to ensure we're not hidden.
   12700         ViewParent parent = mParent;
   12701         while (parent instanceof View) {
   12702             if (((View) parent).getImportantForAccessibility()
   12703                     == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
   12704                 return false;
   12705             }
   12706             parent = parent.getParent();
   12707         }
   12708 
   12709         return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
   12710                 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
   12711                 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE
   12712                 || isAccessibilityPane();
   12713     }
   12714 
   12715     /**
   12716      * Gets the parent for accessibility purposes. Note that the parent for
   12717      * accessibility is not necessary the immediate parent. It is the first
   12718      * predecessor that is important for accessibility.
   12719      *
   12720      * @return The parent for accessibility purposes.
   12721      */
   12722     public ViewParent getParentForAccessibility() {
   12723         if (mParent instanceof View) {
   12724             View parentView = (View) mParent;
   12725             if (parentView.includeForAccessibility()) {
   12726                 return mParent;
   12727             } else {
   12728                 return mParent.getParentForAccessibility();
   12729             }
   12730         }
   12731         return null;
   12732     }
   12733 
   12734     /** @hide */
   12735     View getSelfOrParentImportantForA11y() {
   12736         if (isImportantForAccessibility()) return this;
   12737         ViewParent parent = getParentForAccessibility();
   12738         if (parent instanceof View) return (View) parent;
   12739         return null;
   12740     }
   12741 
   12742     /**
   12743      * Adds the children of this View relevant for accessibility to the given list
   12744      * as output. Since some Views are not important for accessibility the added
   12745      * child views are not necessarily direct children of this view, rather they are
   12746      * the first level of descendants important for accessibility.
   12747      *
   12748      * @param outChildren The output list that will receive children for accessibility.
   12749      */
   12750     public void addChildrenForAccessibility(ArrayList<View> outChildren) {
   12751 
   12752     }
   12753 
   12754     /**
   12755      * Whether to regard this view for accessibility. A view is regarded for
   12756      * accessibility if it is important for accessibility or the querying
   12757      * accessibility service has explicitly requested that view not
   12758      * important for accessibility are regarded.
   12759      *
   12760      * @return Whether to regard the view for accessibility.
   12761      *
   12762      * @hide
   12763      */
   12764     @UnsupportedAppUsage
   12765     public boolean includeForAccessibility() {
   12766         if (mAttachInfo != null) {
   12767             return (mAttachInfo.mAccessibilityFetchFlags
   12768                     & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
   12769                     || isImportantForAccessibility();
   12770         }
   12771         return false;
   12772     }
   12773 
   12774     /**
   12775      * Returns whether the View is considered actionable from
   12776      * accessibility perspective. Such view are important for
   12777      * accessibility.
   12778      *
   12779      * @return True if the view is actionable for accessibility.
   12780      *
   12781      * @hide
   12782      */
   12783     public boolean isActionableForAccessibility() {
   12784         return (isClickable() || isLongClickable() || isFocusable());
   12785     }
   12786 
   12787     /**
   12788      * Returns whether the View has registered callbacks which makes it
   12789      * important for accessibility.
   12790      *
   12791      * @return True if the view is actionable for accessibility.
   12792      */
   12793     private boolean hasListenersForAccessibility() {
   12794         ListenerInfo info = getListenerInfo();
   12795         return mTouchDelegate != null || info.mOnKeyListener != null
   12796                 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
   12797                 || info.mOnHoverListener != null || info.mOnDragListener != null;
   12798     }
   12799 
   12800     /**
   12801      * Notifies that the accessibility state of this view changed. The change
   12802      * is local to this view and does not represent structural changes such
   12803      * as children and parent. For example, the view became focusable. The
   12804      * notification is at at most once every
   12805      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
   12806      * to avoid unnecessary load to the system. Also once a view has a pending
   12807      * notification this method is a NOP until the notification has been sent.
   12808      *
   12809      * @hide
   12810      */
   12811     @UnsupportedAppUsage
   12812     public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
   12813         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
   12814             return;
   12815         }
   12816 
   12817         // Changes to views with a pane title count as window state changes, as the pane title
   12818         // marks them as significant parts of the UI.
   12819         if ((changeType != AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE)
   12820                 && isAccessibilityPane()) {
   12821             // If the pane isn't visible, content changed events are sufficient unless we're
   12822             // reporting that the view just disappeared
   12823             if ((getVisibility() == VISIBLE)
   12824                     || (changeType == AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED)) {
   12825                 final AccessibilityEvent event = AccessibilityEvent.obtain();
   12826                 onInitializeAccessibilityEvent(event);
   12827                 event.setEventType(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
   12828                 event.setContentChangeTypes(changeType);
   12829                 event.setSource(this);
   12830                 onPopulateAccessibilityEvent(event);
   12831                 if (mParent != null) {
   12832                     try {
   12833                         mParent.requestSendAccessibilityEvent(this, event);
   12834                     } catch (AbstractMethodError e) {
   12835                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName()
   12836                                 + " does not fully implement ViewParent", e);
   12837                     }
   12838                 }
   12839                 return;
   12840             }
   12841         }
   12842 
   12843         // If this is a live region, we should send a subtree change event
   12844         // from this view immediately. Otherwise, we can let it propagate up.
   12845         if (getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE) {
   12846             final AccessibilityEvent event = AccessibilityEvent.obtain();
   12847             event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
   12848             event.setContentChangeTypes(changeType);
   12849             sendAccessibilityEventUnchecked(event);
   12850         } else if (mParent != null) {
   12851             try {
   12852                 mParent.notifySubtreeAccessibilityStateChanged(this, this, changeType);
   12853             } catch (AbstractMethodError e) {
   12854                 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   12855                         " does not fully implement ViewParent", e);
   12856             }
   12857         }
   12858     }
   12859 
   12860     /**
   12861      * Notifies that the accessibility state of this view changed. The change
   12862      * is *not* local to this view and does represent structural changes such
   12863      * as children and parent. For example, the view size changed. The
   12864      * notification is at at most once every
   12865      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
   12866      * to avoid unnecessary load to the system. Also once a view has a pending
   12867      * notification this method is a NOP until the notification has been sent.
   12868      *
   12869      * @hide
   12870      */
   12871     @UnsupportedAppUsage
   12872     public void notifySubtreeAccessibilityStateChangedIfNeeded() {
   12873         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
   12874             return;
   12875         }
   12876 
   12877         if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
   12878             mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
   12879             if (mParent != null) {
   12880                 try {
   12881                     mParent.notifySubtreeAccessibilityStateChanged(
   12882                             this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
   12883                 } catch (AbstractMethodError e) {
   12884                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   12885                             " does not fully implement ViewParent", e);
   12886                 }
   12887             }
   12888         }
   12889     }
   12890 
   12891     /**
   12892      * Changes the visibility of this View without triggering any other changes. This should only
   12893      * be used by animation frameworks, such as {@link android.transition.Transition}, where
   12894      * visibility changes should not adjust focus or trigger a new layout. Application developers
   12895      * should use {@link #setVisibility} instead to ensure that the hierarchy is correctly updated.
   12896      *
   12897      * <p>Only call this method when a temporary visibility must be applied during an
   12898      * animation and the original visibility value is guaranteed to be reset after the
   12899      * animation completes. Use {@link #setVisibility} in all other cases.</p>
   12900      *
   12901      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
   12902      * @see #setVisibility(int)
   12903      */
   12904     public void setTransitionVisibility(@Visibility int visibility) {
   12905         mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
   12906     }
   12907 
   12908     /**
   12909      * Reset the flag indicating the accessibility state of the subtree rooted
   12910      * at this view changed.
   12911      */
   12912     void resetSubtreeAccessibilityStateChanged() {
   12913         mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
   12914     }
   12915 
   12916     /**
   12917      * Report an accessibility action to this view's parents for delegated processing.
   12918      *
   12919      * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
   12920      * call this method to delegate an accessibility action to a supporting parent. If the parent
   12921      * returns true from its
   12922      * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
   12923      * method this method will return true to signify that the action was consumed.</p>
   12924      *
   12925      * <p>This method is useful for implementing nested scrolling child views. If
   12926      * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
   12927      * a custom view implementation may invoke this method to allow a parent to consume the
   12928      * scroll first. If this method returns true the custom view should skip its own scrolling
   12929      * behavior.</p>
   12930      *
   12931      * @param action Accessibility action to delegate
   12932      * @param arguments Optional action arguments
   12933      * @return true if the action was consumed by a parent
   12934      */
   12935     public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
   12936         for (ViewParent p = getParent(); p != null; p = p.getParent()) {
   12937             if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
   12938                 return true;
   12939             }
   12940         }
   12941         return false;
   12942     }
   12943 
   12944     /**
   12945      * Performs the specified accessibility action on the view. For
   12946      * possible accessibility actions look at {@link AccessibilityNodeInfo}.
   12947      * <p>
   12948      * If an {@link AccessibilityDelegate} has been specified via calling
   12949      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   12950      * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
   12951      * is responsible for handling this call.
   12952      * </p>
   12953      *
   12954      * <p>The default implementation will delegate
   12955      * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
   12956      * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
   12957      * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
   12958      *
   12959      * @param action The action to perform.
   12960      * @param arguments Optional action arguments.
   12961      * @return Whether the action was performed.
   12962      */
   12963     public boolean performAccessibilityAction(int action, Bundle arguments) {
   12964       if (mAccessibilityDelegate != null) {
   12965           return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
   12966       } else {
   12967           return performAccessibilityActionInternal(action, arguments);
   12968       }
   12969     }
   12970 
   12971    /**
   12972     * @see #performAccessibilityAction(int, Bundle)
   12973     *
   12974     * Note: Called from the default {@link AccessibilityDelegate}.
   12975     *
   12976     * @hide
   12977     */
   12978     @UnsupportedAppUsage
   12979     public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
   12980         if (isNestedScrollingEnabled()
   12981                 && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
   12982                 || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
   12983                 || action == R.id.accessibilityActionScrollUp
   12984                 || action == R.id.accessibilityActionScrollLeft
   12985                 || action == R.id.accessibilityActionScrollDown
   12986                 || action == R.id.accessibilityActionScrollRight)) {
   12987             if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
   12988                 return true;
   12989             }
   12990         }
   12991 
   12992         switch (action) {
   12993             case AccessibilityNodeInfo.ACTION_CLICK: {
   12994                 if (isClickable()) {
   12995                     performClickInternal();
   12996                     return true;
   12997                 }
   12998             } break;
   12999             case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
   13000                 if (isLongClickable()) {
   13001                     performLongClick();
   13002                     return true;
   13003                 }
   13004             } break;
   13005             case AccessibilityNodeInfo.ACTION_FOCUS: {
   13006                 if (!hasFocus()) {
   13007                     // Get out of touch mode since accessibility
   13008                     // wants to move focus around.
   13009                     getViewRootImpl().ensureTouchMode(false);
   13010                     return requestFocus();
   13011                 }
   13012             } break;
   13013             case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
   13014                 if (hasFocus()) {
   13015                     clearFocus();
   13016                     return !isFocused();
   13017                 }
   13018             } break;
   13019             case AccessibilityNodeInfo.ACTION_SELECT: {
   13020                 if (!isSelected()) {
   13021                     setSelected(true);
   13022                     return isSelected();
   13023                 }
   13024             } break;
   13025             case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
   13026                 if (isSelected()) {
   13027                     setSelected(false);
   13028                     return !isSelected();
   13029                 }
   13030             } break;
   13031             case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
   13032                 if (!isAccessibilityFocused()) {
   13033                     return requestAccessibilityFocus();
   13034                 }
   13035             } break;
   13036             case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
   13037                 if (isAccessibilityFocused()) {
   13038                     clearAccessibilityFocus();
   13039                     return true;
   13040                 }
   13041             } break;
   13042             case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
   13043                 if (arguments != null) {
   13044                     final int granularity = arguments.getInt(
   13045                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
   13046                     final boolean extendSelection = arguments.getBoolean(
   13047                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
   13048                     return traverseAtGranularity(granularity, true, extendSelection);
   13049                 }
   13050             } break;
   13051             case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
   13052                 if (arguments != null) {
   13053                     final int granularity = arguments.getInt(
   13054                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
   13055                     final boolean extendSelection = arguments.getBoolean(
   13056                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
   13057                     return traverseAtGranularity(granularity, false, extendSelection);
   13058                 }
   13059             } break;
   13060             case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
   13061                 CharSequence text = getIterableTextForAccessibility();
   13062                 if (text == null) {
   13063                     return false;
   13064                 }
   13065                 final int start = (arguments != null) ? arguments.getInt(
   13066                         AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
   13067                 final int end = (arguments != null) ? arguments.getInt(
   13068                 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
   13069                 // Only cursor position can be specified (selection length == 0)
   13070                 if ((getAccessibilitySelectionStart() != start
   13071                         || getAccessibilitySelectionEnd() != end)
   13072                         && (start == end)) {
   13073                     setAccessibilitySelection(start, end);
   13074                     notifyViewAccessibilityStateChangedIfNeeded(
   13075                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   13076                     return true;
   13077                 }
   13078             } break;
   13079             case R.id.accessibilityActionShowOnScreen: {
   13080                 if (mAttachInfo != null) {
   13081                     final Rect r = mAttachInfo.mTmpInvalRect;
   13082                     getDrawingRect(r);
   13083                     return requestRectangleOnScreen(r, true);
   13084                 }
   13085             } break;
   13086             case R.id.accessibilityActionContextClick: {
   13087                 if (isContextClickable()) {
   13088                     performContextClick();
   13089                     return true;
   13090                 }
   13091             } break;
   13092             case R.id.accessibilityActionShowTooltip: {
   13093                 if ((mTooltipInfo != null) && (mTooltipInfo.mTooltipPopup != null)) {
   13094                     // Tooltip already showing
   13095                     return false;
   13096                 }
   13097                 return showLongClickTooltip(0, 0);
   13098             }
   13099             case R.id.accessibilityActionHideTooltip: {
   13100                 if ((mTooltipInfo == null) || (mTooltipInfo.mTooltipPopup == null)) {
   13101                     // No tooltip showing
   13102                     return false;
   13103                 }
   13104                 hideTooltip();
   13105                 return true;
   13106             }
   13107         }
   13108         return false;
   13109     }
   13110 
   13111     private boolean traverseAtGranularity(int granularity, boolean forward,
   13112             boolean extendSelection) {
   13113         CharSequence text = getIterableTextForAccessibility();
   13114         if (text == null || text.length() == 0) {
   13115             return false;
   13116         }
   13117         TextSegmentIterator iterator = getIteratorForGranularity(granularity);
   13118         if (iterator == null) {
   13119             return false;
   13120         }
   13121         int current = getAccessibilitySelectionEnd();
   13122         if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
   13123             current = forward ? 0 : text.length();
   13124         }
   13125         final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
   13126         if (range == null) {
   13127             return false;
   13128         }
   13129         final int segmentStart = range[0];
   13130         final int segmentEnd = range[1];
   13131         int selectionStart;
   13132         int selectionEnd;
   13133         if (extendSelection && isAccessibilitySelectionExtendable()) {
   13134             selectionStart = getAccessibilitySelectionStart();
   13135             if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
   13136                 selectionStart = forward ? segmentStart : segmentEnd;
   13137             }
   13138             selectionEnd = forward ? segmentEnd : segmentStart;
   13139         } else {
   13140             selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
   13141         }
   13142         setAccessibilitySelection(selectionStart, selectionEnd);
   13143         final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
   13144                 : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
   13145         sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
   13146         return true;
   13147     }
   13148 
   13149     /**
   13150      * Gets the text reported for accessibility purposes.
   13151      *
   13152      * @return The accessibility text.
   13153      *
   13154      * @hide
   13155      */
   13156     @UnsupportedAppUsage
   13157     public CharSequence getIterableTextForAccessibility() {
   13158         return getContentDescription();
   13159     }
   13160 
   13161     /**
   13162      * Gets whether accessibility selection can be extended.
   13163      *
   13164      * @return If selection is extensible.
   13165      *
   13166      * @hide
   13167      */
   13168     public boolean isAccessibilitySelectionExtendable() {
   13169         return false;
   13170     }
   13171 
   13172     /**
   13173      * @hide
   13174      */
   13175     public int getAccessibilitySelectionStart() {
   13176         return mAccessibilityCursorPosition;
   13177     }
   13178 
   13179     /**
   13180      * @hide
   13181      */
   13182     public int getAccessibilitySelectionEnd() {
   13183         return getAccessibilitySelectionStart();
   13184     }
   13185 
   13186     /**
   13187      * @hide
   13188      */
   13189     public void setAccessibilitySelection(int start, int end) {
   13190         if (start ==  end && end == mAccessibilityCursorPosition) {
   13191             return;
   13192         }
   13193         if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
   13194             mAccessibilityCursorPosition = start;
   13195         } else {
   13196             mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
   13197         }
   13198         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
   13199     }
   13200 
   13201     private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
   13202             int fromIndex, int toIndex) {
   13203         if (mParent == null) {
   13204             return;
   13205         }
   13206         AccessibilityEvent event = AccessibilityEvent.obtain(
   13207                 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
   13208         onInitializeAccessibilityEvent(event);
   13209         onPopulateAccessibilityEvent(event);
   13210         event.setFromIndex(fromIndex);
   13211         event.setToIndex(toIndex);
   13212         event.setAction(action);
   13213         event.setMovementGranularity(granularity);
   13214         mParent.requestSendAccessibilityEvent(this, event);
   13215     }
   13216 
   13217     /**
   13218      * @hide
   13219      */
   13220     @UnsupportedAppUsage
   13221     public TextSegmentIterator getIteratorForGranularity(int granularity) {
   13222         switch (granularity) {
   13223             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
   13224                 CharSequence text = getIterableTextForAccessibility();
   13225                 if (text != null && text.length() > 0) {
   13226                     CharacterTextSegmentIterator iterator =
   13227                         CharacterTextSegmentIterator.getInstance(
   13228                                 mContext.getResources().getConfiguration().locale);
   13229                     iterator.initialize(text.toString());
   13230                     return iterator;
   13231                 }
   13232             } break;
   13233             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
   13234                 CharSequence text = getIterableTextForAccessibility();
   13235                 if (text != null && text.length() > 0) {
   13236                     WordTextSegmentIterator iterator =
   13237                         WordTextSegmentIterator.getInstance(
   13238                                 mContext.getResources().getConfiguration().locale);
   13239                     iterator.initialize(text.toString());
   13240                     return iterator;
   13241                 }
   13242             } break;
   13243             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
   13244                 CharSequence text = getIterableTextForAccessibility();
   13245                 if (text != null && text.length() > 0) {
   13246                     ParagraphTextSegmentIterator iterator =
   13247                         ParagraphTextSegmentIterator.getInstance();
   13248                     iterator.initialize(text.toString());
   13249                     return iterator;
   13250                 }
   13251             } break;
   13252         }
   13253         return null;
   13254     }
   13255 
   13256     /**
   13257      * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
   13258      * and {@link #onFinishTemporaryDetach()}.
   13259      *
   13260      * <p>This method always returns {@code true} when called directly or indirectly from
   13261      * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
   13262      * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
   13263      * <ul>
   13264      *     <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
   13265      *     <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
   13266      * </ul>
   13267      * </p>
   13268      *
   13269      * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
   13270      * and {@link #onFinishTemporaryDetach()}.
   13271      */
   13272     public final boolean isTemporarilyDetached() {
   13273         return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
   13274     }
   13275 
   13276     /**
   13277      * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
   13278      * a container View.
   13279      */
   13280     @CallSuper
   13281     public void dispatchStartTemporaryDetach() {
   13282         mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
   13283         notifyEnterOrExitForAutoFillIfNeeded(false);
   13284         onStartTemporaryDetach();
   13285     }
   13286 
   13287     /**
   13288      * This is called when a container is going to temporarily detach a child, with
   13289      * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
   13290      * It will either be followed by {@link #onFinishTemporaryDetach()} or
   13291      * {@link #onDetachedFromWindow()} when the container is done.
   13292      */
   13293     public void onStartTemporaryDetach() {
   13294         removeUnsetPressCallback();
   13295         mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
   13296     }
   13297 
   13298     /**
   13299      * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
   13300      * a container View.
   13301      */
   13302     @CallSuper
   13303     public void dispatchFinishTemporaryDetach() {
   13304         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
   13305         onFinishTemporaryDetach();
   13306         if (hasWindowFocus() && hasFocus()) {
   13307             notifyFocusChangeToInputMethodManager(true /* hasFocus */);
   13308         }
   13309         notifyEnterOrExitForAutoFillIfNeeded(true);
   13310     }
   13311 
   13312     /**
   13313      * Called after {@link #onStartTemporaryDetach} when the container is done
   13314      * changing the view.
   13315      */
   13316     public void onFinishTemporaryDetach() {
   13317     }
   13318 
   13319     /**
   13320      * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
   13321      * for this view's window.  Returns null if the view is not currently attached
   13322      * to the window.  Normally you will not need to use this directly, but
   13323      * just use the standard high-level event callbacks like
   13324      * {@link #onKeyDown(int, KeyEvent)}.
   13325      */
   13326     public KeyEvent.DispatcherState getKeyDispatcherState() {
   13327         return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
   13328     }
   13329 
   13330     /**
   13331      * Dispatch a key event before it is processed by any input method
   13332      * associated with the view hierarchy.  This can be used to intercept
   13333      * key events in special situations before the IME consumes them; a
   13334      * typical example would be handling the BACK key to update the application's
   13335      * UI instead of allowing the IME to see it and close itself.
   13336      *
   13337      * @param event The key event to be dispatched.
   13338      * @return True if the event was handled, false otherwise.
   13339      */
   13340     public boolean dispatchKeyEventPreIme(KeyEvent event) {
   13341         return onKeyPreIme(event.getKeyCode(), event);
   13342     }
   13343 
   13344     /**
   13345      * Dispatch a key event to the next view on the focus path. This path runs
   13346      * from the top of the view tree down to the currently focused view. If this
   13347      * view has focus, it will dispatch to itself. Otherwise it will dispatch
   13348      * the next node down the focus path. This method also fires any key
   13349      * listeners.
   13350      *
   13351      * @param event The key event to be dispatched.
   13352      * @return True if the event was handled, false otherwise.
   13353      */
   13354     public boolean dispatchKeyEvent(KeyEvent event) {
   13355         if (mInputEventConsistencyVerifier != null) {
   13356             mInputEventConsistencyVerifier.onKeyEvent(event, 0);
   13357         }
   13358 
   13359         // Give any attached key listener a first crack at the event.
   13360         //noinspection SimplifiableIfStatement
   13361         ListenerInfo li = mListenerInfo;
   13362         if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
   13363                 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
   13364             return true;
   13365         }
   13366 
   13367         if (event.dispatch(this, mAttachInfo != null
   13368                 ? mAttachInfo.mKeyDispatchState : null, this)) {
   13369             return true;
   13370         }
   13371 
   13372         if (mInputEventConsistencyVerifier != null) {
   13373             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
   13374         }
   13375         return false;
   13376     }
   13377 
   13378     /**
   13379      * Dispatches a key shortcut event.
   13380      *
   13381      * @param event The key event to be dispatched.
   13382      * @return True if the event was handled by the view, false otherwise.
   13383      */
   13384     public boolean dispatchKeyShortcutEvent(KeyEvent event) {
   13385         return onKeyShortcut(event.getKeyCode(), event);
   13386     }
   13387 
   13388     /**
   13389      * Pass the touch screen motion event down to the target view, or this
   13390      * view if it is the target.
   13391      *
   13392      * @param event The motion event to be dispatched.
   13393      * @return True if the event was handled by the view, false otherwise.
   13394      */
   13395     public boolean dispatchTouchEvent(MotionEvent event) {
   13396         // If the event should be handled by accessibility focus first.
   13397         if (event.isTargetAccessibilityFocus()) {
   13398             // We don't have focus or no virtual descendant has it, do not handle the event.
   13399             if (!isAccessibilityFocusedViewOrHost()) {
   13400                 return false;
   13401             }
   13402             // We have focus and got the event, then use normal event dispatch.
   13403             event.setTargetAccessibilityFocus(false);
   13404         }
   13405 
   13406         boolean result = false;
   13407 
   13408         if (mInputEventConsistencyVerifier != null) {
   13409             mInputEventConsistencyVerifier.onTouchEvent(event, 0);
   13410         }
   13411 
   13412         final int actionMasked = event.getActionMasked();
   13413         if (actionMasked == MotionEvent.ACTION_DOWN) {
   13414             // Defensive cleanup for new gesture
   13415             stopNestedScroll();
   13416         }
   13417 
   13418         if (onFilterTouchEventForSecurity(event)) {
   13419             if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
   13420                 result = true;
   13421             }
   13422             //noinspection SimplifiableIfStatement
   13423             ListenerInfo li = mListenerInfo;
   13424             if (li != null && li.mOnTouchListener != null
   13425                     && (mViewFlags & ENABLED_MASK) == ENABLED
   13426                     && li.mOnTouchListener.onTouch(this, event)) {
   13427                 result = true;
   13428             }
   13429 
   13430             if (!result && onTouchEvent(event)) {
   13431                 result = true;
   13432             }
   13433         }
   13434 
   13435         if (!result && mInputEventConsistencyVerifier != null) {
   13436             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
   13437         }
   13438 
   13439         // Clean up after nested scrolls if this is the end of a gesture;
   13440         // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
   13441         // of the gesture.
   13442         if (actionMasked == MotionEvent.ACTION_UP ||
   13443                 actionMasked == MotionEvent.ACTION_CANCEL ||
   13444                 (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
   13445             stopNestedScroll();
   13446         }
   13447 
   13448         return result;
   13449     }
   13450 
   13451     boolean isAccessibilityFocusedViewOrHost() {
   13452         return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
   13453                 .getAccessibilityFocusedHost() == this);
   13454     }
   13455 
   13456     /**
   13457      * Returns whether this view can receive pointer events.
   13458      *
   13459      * @return {@code true} if this view can receive pointer events.
   13460      * @hide
   13461      */
   13462     protected boolean canReceivePointerEvents() {
   13463         return (mViewFlags & VISIBILITY_MASK) == VISIBLE || getAnimation() != null;
   13464     }
   13465 
   13466     /**
   13467      * Filter the touch event to apply security policies.
   13468      *
   13469      * @param event The motion event to be filtered.
   13470      * @return True if the event should be dispatched, false if the event should be dropped.
   13471      *
   13472      * @see #getFilterTouchesWhenObscured
   13473      */
   13474     public boolean onFilterTouchEventForSecurity(MotionEvent event) {
   13475         //noinspection RedundantIfStatement
   13476         if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
   13477                 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
   13478             // Window is obscured, drop this touch.
   13479             return false;
   13480         }
   13481         return true;
   13482     }
   13483 
   13484     /**
   13485      * Pass a trackball motion event down to the focused view.
   13486      *
   13487      * @param event The motion event to be dispatched.
   13488      * @return True if the event was handled by the view, false otherwise.
   13489      */
   13490     public boolean dispatchTrackballEvent(MotionEvent event) {
   13491         if (mInputEventConsistencyVerifier != null) {
   13492             mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
   13493         }
   13494 
   13495         return onTrackballEvent(event);
   13496     }
   13497 
   13498     /**
   13499      * Pass a captured pointer event down to the focused view.
   13500      *
   13501      * @param event The motion event to be dispatched.
   13502      * @return True if the event was handled by the view, false otherwise.
   13503      */
   13504     public boolean dispatchCapturedPointerEvent(MotionEvent event) {
   13505         if (!hasPointerCapture()) {
   13506             return false;
   13507         }
   13508         //noinspection SimplifiableIfStatement
   13509         ListenerInfo li = mListenerInfo;
   13510         if (li != null && li.mOnCapturedPointerListener != null
   13511                 && li.mOnCapturedPointerListener.onCapturedPointer(this, event)) {
   13512             return true;
   13513         }
   13514         return onCapturedPointerEvent(event);
   13515     }
   13516 
   13517     /**
   13518      * Dispatch a generic motion event.
   13519      * <p>
   13520      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
   13521      * are delivered to the view under the pointer.  All other generic motion events are
   13522      * delivered to the focused view.  Hover events are handled specially and are delivered
   13523      * to {@link #onHoverEvent(MotionEvent)}.
   13524      * </p>
   13525      *
   13526      * @param event The motion event to be dispatched.
   13527      * @return True if the event was handled by the view, false otherwise.
   13528      */
   13529     public boolean dispatchGenericMotionEvent(MotionEvent event) {
   13530         if (mInputEventConsistencyVerifier != null) {
   13531             mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
   13532         }
   13533 
   13534         final int source = event.getSource();
   13535         if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
   13536             final int action = event.getAction();
   13537             if (action == MotionEvent.ACTION_HOVER_ENTER
   13538                     || action == MotionEvent.ACTION_HOVER_MOVE
   13539                     || action == MotionEvent.ACTION_HOVER_EXIT) {
   13540                 if (dispatchHoverEvent(event)) {
   13541                     return true;
   13542                 }
   13543             } else if (dispatchGenericPointerEvent(event)) {
   13544                 return true;
   13545             }
   13546         } else if (dispatchGenericFocusedEvent(event)) {
   13547             return true;
   13548         }
   13549 
   13550         if (dispatchGenericMotionEventInternal(event)) {
   13551             return true;
   13552         }
   13553 
   13554         if (mInputEventConsistencyVerifier != null) {
   13555             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
   13556         }
   13557         return false;
   13558     }
   13559 
   13560     private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
   13561         //noinspection SimplifiableIfStatement
   13562         ListenerInfo li = mListenerInfo;
   13563         if (li != null && li.mOnGenericMotionListener != null
   13564                 && (mViewFlags & ENABLED_MASK) == ENABLED
   13565                 && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
   13566             return true;
   13567         }
   13568 
   13569         if (onGenericMotionEvent(event)) {
   13570             return true;
   13571         }
   13572 
   13573         final int actionButton = event.getActionButton();
   13574         switch (event.getActionMasked()) {
   13575             case MotionEvent.ACTION_BUTTON_PRESS:
   13576                 if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
   13577                         && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
   13578                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
   13579                     if (performContextClick(event.getX(), event.getY())) {
   13580                         mInContextButtonPress = true;
   13581                         setPressed(true, event.getX(), event.getY());
   13582                         removeTapCallback();
   13583                         removeLongPressCallback();
   13584                         return true;
   13585                     }
   13586                 }
   13587                 break;
   13588 
   13589             case MotionEvent.ACTION_BUTTON_RELEASE:
   13590                 if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
   13591                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
   13592                     mInContextButtonPress = false;
   13593                     mIgnoreNextUpEvent = true;
   13594                 }
   13595                 break;
   13596         }
   13597 
   13598         if (mInputEventConsistencyVerifier != null) {
   13599             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
   13600         }
   13601         return false;
   13602     }
   13603 
   13604     /**
   13605      * Dispatch a hover event.
   13606      * <p>
   13607      * Do not call this method directly.
   13608      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
   13609      * </p>
   13610      *
   13611      * @param event The motion event to be dispatched.
   13612      * @return True if the event was handled by the view, false otherwise.
   13613      */
   13614     protected boolean dispatchHoverEvent(MotionEvent event) {
   13615         ListenerInfo li = mListenerInfo;
   13616         //noinspection SimplifiableIfStatement
   13617         if (li != null && li.mOnHoverListener != null
   13618                 && (mViewFlags & ENABLED_MASK) == ENABLED
   13619                 && li.mOnHoverListener.onHover(this, event)) {
   13620             return true;
   13621         }
   13622 
   13623         return onHoverEvent(event);
   13624     }
   13625 
   13626     /**
   13627      * Returns true if the view has a child to which it has recently sent
   13628      * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
   13629      * it does not have a hovered child, then it must be the innermost hovered view.
   13630      * @hide
   13631      */
   13632     protected boolean hasHoveredChild() {
   13633         return false;
   13634     }
   13635 
   13636     /**
   13637      * Returns true if the given point, in local coordinates, is inside the hovered child.
   13638      *
   13639      * @hide
   13640      */
   13641     protected boolean pointInHoveredChild(MotionEvent event) {
   13642         return false;
   13643     }
   13644 
   13645     /**
   13646      * Dispatch a generic motion event to the view under the first pointer.
   13647      * <p>
   13648      * Do not call this method directly.
   13649      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
   13650      * </p>
   13651      *
   13652      * @param event The motion event to be dispatched.
   13653      * @return True if the event was handled by the view, false otherwise.
   13654      */
   13655     protected boolean dispatchGenericPointerEvent(MotionEvent event) {
   13656         return false;
   13657     }
   13658 
   13659     /**
   13660      * Dispatch a generic motion event to the currently focused view.
   13661      * <p>
   13662      * Do not call this method directly.
   13663      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
   13664      * </p>
   13665      *
   13666      * @param event The motion event to be dispatched.
   13667      * @return True if the event was handled by the view, false otherwise.
   13668      */
   13669     protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
   13670         return false;
   13671     }
   13672 
   13673     /**
   13674      * Dispatch a pointer event.
   13675      * <p>
   13676      * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
   13677      * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
   13678      * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
   13679      * and should not be expected to handle other pointing device features.
   13680      * </p>
   13681      *
   13682      * @param event The motion event to be dispatched.
   13683      * @return True if the event was handled by the view, false otherwise.
   13684      * @hide
   13685      */
   13686     @UnsupportedAppUsage
   13687     public final boolean dispatchPointerEvent(MotionEvent event) {
   13688         if (event.isTouchEvent()) {
   13689             return dispatchTouchEvent(event);
   13690         } else {
   13691             return dispatchGenericMotionEvent(event);
   13692         }
   13693     }
   13694 
   13695     /**
   13696      * Called when the window containing this view gains or loses window focus.
   13697      * ViewGroups should override to route to their children.
   13698      *
   13699      * @param hasFocus True if the window containing this view now has focus,
   13700      *        false otherwise.
   13701      */
   13702     public void dispatchWindowFocusChanged(boolean hasFocus) {
   13703         onWindowFocusChanged(hasFocus);
   13704     }
   13705 
   13706     /**
   13707      * Called when the window containing this view gains or loses focus.  Note
   13708      * that this is separate from view focus: to receive key events, both
   13709      * your view and its window must have focus.  If a window is displayed
   13710      * on top of yours that takes input focus, then your own window will lose
   13711      * focus but the view focus will remain unchanged.
   13712      *
   13713      * @param hasWindowFocus True if the window containing this view now has
   13714      *        focus, false otherwise.
   13715      */
   13716     public void onWindowFocusChanged(boolean hasWindowFocus) {
   13717         if (!hasWindowFocus) {
   13718             if (isPressed()) {
   13719                 setPressed(false);
   13720             }
   13721             mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
   13722             if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
   13723                 notifyFocusChangeToInputMethodManager(false /* hasFocus */);
   13724             }
   13725             removeLongPressCallback();
   13726             removeTapCallback();
   13727             onFocusLost();
   13728         } else if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
   13729             notifyFocusChangeToInputMethodManager(true /* hasFocus */);
   13730         }
   13731 
   13732         refreshDrawableState();
   13733     }
   13734 
   13735     /**
   13736      * Returns true if this view is in a window that currently has window focus.
   13737      * Note that this is not the same as the view itself having focus.
   13738      *
   13739      * @return True if this view is in a window that currently has window focus.
   13740      */
   13741     public boolean hasWindowFocus() {
   13742         return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
   13743     }
   13744 
   13745     /**
   13746      * Dispatch a view visibility change down the view hierarchy.
   13747      * ViewGroups should override to route to their children.
   13748      * @param changedView The view whose visibility changed. Could be 'this' or
   13749      * an ancestor view.
   13750      * @param visibility The new visibility of changedView: {@link #VISIBLE},
   13751      * {@link #INVISIBLE} or {@link #GONE}.
   13752      */
   13753     protected void dispatchVisibilityChanged(@NonNull View changedView,
   13754             @Visibility int visibility) {
   13755         onVisibilityChanged(changedView, visibility);
   13756     }
   13757 
   13758     /**
   13759      * Called when the visibility of the view or an ancestor of the view has
   13760      * changed.
   13761      *
   13762      * @param changedView The view whose visibility changed. May be
   13763      *                    {@code this} or an ancestor view.
   13764      * @param visibility The new visibility, one of {@link #VISIBLE},
   13765      *                   {@link #INVISIBLE} or {@link #GONE}.
   13766      */
   13767     protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
   13768     }
   13769 
   13770     /**
   13771      * Dispatch a hint about whether this view is displayed. For instance, when
   13772      * a View moves out of the screen, it might receives a display hint indicating
   13773      * the view is not displayed. Applications should not <em>rely</em> on this hint
   13774      * as there is no guarantee that they will receive one.
   13775      *
   13776      * @param hint A hint about whether or not this view is displayed:
   13777      * {@link #VISIBLE} or {@link #INVISIBLE}.
   13778      */
   13779     public void dispatchDisplayHint(@Visibility int hint) {
   13780         onDisplayHint(hint);
   13781     }
   13782 
   13783     /**
   13784      * Gives this view a hint about whether is displayed or not. For instance, when
   13785      * a View moves out of the screen, it might receives a display hint indicating
   13786      * the view is not displayed. Applications should not <em>rely</em> on this hint
   13787      * as there is no guarantee that they will receive one.
   13788      *
   13789      * @param hint A hint about whether or not this view is displayed:
   13790      * {@link #VISIBLE} or {@link #INVISIBLE}.
   13791      */
   13792     protected void onDisplayHint(@Visibility int hint) {
   13793     }
   13794 
   13795     /**
   13796      * Dispatch a window visibility change down the view hierarchy.
   13797      * ViewGroups should override to route to their children.
   13798      *
   13799      * @param visibility The new visibility of the window.
   13800      *
   13801      * @see #onWindowVisibilityChanged(int)
   13802      */
   13803     public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
   13804         onWindowVisibilityChanged(visibility);
   13805     }
   13806 
   13807     /**
   13808      * Called when the window containing has change its visibility
   13809      * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
   13810      * that this tells you whether or not your window is being made visible
   13811      * to the window manager; this does <em>not</em> tell you whether or not
   13812      * your window is obscured by other windows on the screen, even if it
   13813      * is itself visible.
   13814      *
   13815      * @param visibility The new visibility of the window.
   13816      */
   13817     protected void onWindowVisibilityChanged(@Visibility int visibility) {
   13818         if (visibility == VISIBLE) {
   13819             initialAwakenScrollBars();
   13820         }
   13821     }
   13822 
   13823     /**
   13824      * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
   13825      * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
   13826      * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
   13827      *
   13828      * @param isVisible true if this view's visibility to the user is uninterrupted by its
   13829      *                  ancestors or by window visibility
   13830      * @return true if this view is visible to the user, not counting clipping or overlapping
   13831      */
   13832     boolean dispatchVisibilityAggregated(boolean isVisible) {
   13833         final boolean thisVisible = getVisibility() == VISIBLE;
   13834         // If we're not visible but something is telling us we are, ignore it.
   13835         if (thisVisible || !isVisible) {
   13836             onVisibilityAggregated(isVisible);
   13837         }
   13838         return thisVisible && isVisible;
   13839     }
   13840 
   13841     /**
   13842      * Called when the user-visibility of this View is potentially affected by a change
   13843      * to this view itself, an ancestor view or the window this view is attached to.
   13844      *
   13845      * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
   13846      *                  and this view's window is also visible
   13847      */
   13848     @CallSuper
   13849     public void onVisibilityAggregated(boolean isVisible) {
   13850         // Update our internal visibility tracking so we can detect changes
   13851         boolean oldVisible = (mPrivateFlags3 & PFLAG3_AGGREGATED_VISIBLE) != 0;
   13852         mPrivateFlags3 = isVisible ? (mPrivateFlags3 | PFLAG3_AGGREGATED_VISIBLE)
   13853                 : (mPrivateFlags3 & ~PFLAG3_AGGREGATED_VISIBLE);
   13854         if (isVisible && mAttachInfo != null) {
   13855             initialAwakenScrollBars();
   13856         }
   13857 
   13858         final Drawable dr = mBackground;
   13859         if (dr != null && isVisible != dr.isVisible()) {
   13860             dr.setVisible(isVisible, false);
   13861         }
   13862         final Drawable hl = mDefaultFocusHighlight;
   13863         if (hl != null && isVisible != hl.isVisible()) {
   13864             hl.setVisible(isVisible, false);
   13865         }
   13866         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
   13867         if (fg != null && isVisible != fg.isVisible()) {
   13868             fg.setVisible(isVisible, false);
   13869         }
   13870 
   13871         if (isAutofillable()) {
   13872             AutofillManager afm = getAutofillManager();
   13873 
   13874             if (afm != null && getAutofillViewId() > LAST_APP_AUTOFILL_ID) {
   13875                 if (mVisibilityChangeForAutofillHandler != null) {
   13876                     mVisibilityChangeForAutofillHandler.removeMessages(0);
   13877                 }
   13878 
   13879                 // If the view is in the background but still part of the hierarchy this is called
   13880                 // with isVisible=false. Hence visibility==false requires further checks
   13881                 if (isVisible) {
   13882                     afm.notifyViewVisibilityChanged(this, true);
   13883                 } else {
   13884                     if (mVisibilityChangeForAutofillHandler == null) {
   13885                         mVisibilityChangeForAutofillHandler =
   13886                                 new VisibilityChangeForAutofillHandler(afm, this);
   13887                     }
   13888                     // Let current operation (e.g. removal of the view from the hierarchy)
   13889                     // finish before checking state
   13890                     mVisibilityChangeForAutofillHandler.obtainMessage(0, this).sendToTarget();
   13891                 }
   13892             }
   13893         }
   13894         if (isAccessibilityPane()) {
   13895             if (isVisible != oldVisible) {
   13896                 notifyViewAccessibilityStateChangedIfNeeded(isVisible
   13897                         ? AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_APPEARED
   13898                         : AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED);
   13899             }
   13900         }
   13901     }
   13902 
   13903     /**
   13904      * Returns the current visibility of the window this view is attached to
   13905      * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
   13906      *
   13907      * @return Returns the current visibility of the view's window.
   13908      */
   13909     @Visibility
   13910     public int getWindowVisibility() {
   13911         return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
   13912     }
   13913 
   13914     /**
   13915      * Retrieve the overall visible display size in which the window this view is
   13916      * attached to has been positioned in.  This takes into account screen
   13917      * decorations above the window, for both cases where the window itself
   13918      * is being position inside of them or the window is being placed under
   13919      * then and covered insets are used for the window to position its content
   13920      * inside.  In effect, this tells you the available area where content can
   13921      * be placed and remain visible to users.
   13922      *
   13923      * <p>This function requires an IPC back to the window manager to retrieve
   13924      * the requested information, so should not be used in performance critical
   13925      * code like drawing.
   13926      *
   13927      * @param outRect Filled in with the visible display frame.  If the view
   13928      * is not attached to a window, this is simply the raw display size.
   13929      */
   13930     public void getWindowVisibleDisplayFrame(Rect outRect) {
   13931         if (mAttachInfo != null) {
   13932             try {
   13933                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
   13934             } catch (RemoteException e) {
   13935                 return;
   13936             }
   13937             // XXX This is really broken, and probably all needs to be done
   13938             // in the window manager, and we need to know more about whether
   13939             // we want the area behind or in front of the IME.
   13940             final Rect insets = mAttachInfo.mVisibleInsets;
   13941             outRect.left += insets.left;
   13942             outRect.top += insets.top;
   13943             outRect.right -= insets.right;
   13944             outRect.bottom -= insets.bottom;
   13945             return;
   13946         }
   13947         // The view is not attached to a display so we don't have a context.
   13948         // Make a best guess about the display size.
   13949         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
   13950         d.getRectSize(outRect);
   13951     }
   13952 
   13953     /**
   13954      * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
   13955      * is currently in without any insets.
   13956      *
   13957      * @hide
   13958      */
   13959     @UnsupportedAppUsage
   13960     public void getWindowDisplayFrame(Rect outRect) {
   13961         if (mAttachInfo != null) {
   13962             try {
   13963                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
   13964             } catch (RemoteException e) {
   13965                 return;
   13966             }
   13967             return;
   13968         }
   13969         // The view is not attached to a display so we don't have a context.
   13970         // Make a best guess about the display size.
   13971         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
   13972         d.getRectSize(outRect);
   13973     }
   13974 
   13975     /**
   13976      * Dispatch a notification about a resource configuration change down
   13977      * the view hierarchy.
   13978      * ViewGroups should override to route to their children.
   13979      *
   13980      * @param newConfig The new resource configuration.
   13981      *
   13982      * @see #onConfigurationChanged(android.content.res.Configuration)
   13983      */
   13984     public void dispatchConfigurationChanged(Configuration newConfig) {
   13985         onConfigurationChanged(newConfig);
   13986     }
   13987 
   13988     /**
   13989      * Called when the current configuration of the resources being used
   13990      * by the application have changed.  You can use this to decide when
   13991      * to reload resources that can changed based on orientation and other
   13992      * configuration characteristics.  You only need to use this if you are
   13993      * not relying on the normal {@link android.app.Activity} mechanism of
   13994      * recreating the activity instance upon a configuration change.
   13995      *
   13996      * @param newConfig The new resource configuration.
   13997      */
   13998     protected void onConfigurationChanged(Configuration newConfig) {
   13999     }
   14000 
   14001     /**
   14002      * Private function to aggregate all per-view attributes in to the view
   14003      * root.
   14004      */
   14005     void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
   14006         performCollectViewAttributes(attachInfo, visibility);
   14007     }
   14008 
   14009     void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
   14010         if ((visibility & VISIBILITY_MASK) == VISIBLE) {
   14011             if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
   14012                 attachInfo.mKeepScreenOn = true;
   14013             }
   14014             attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
   14015             ListenerInfo li = mListenerInfo;
   14016             if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
   14017                 attachInfo.mHasSystemUiListeners = true;
   14018             }
   14019         }
   14020     }
   14021 
   14022     void needGlobalAttributesUpdate(boolean force) {
   14023         final AttachInfo ai = mAttachInfo;
   14024         if (ai != null && !ai.mRecomputeGlobalAttributes) {
   14025             if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
   14026                     || ai.mHasSystemUiListeners) {
   14027                 ai.mRecomputeGlobalAttributes = true;
   14028             }
   14029         }
   14030     }
   14031 
   14032     /**
   14033      * Returns whether the device is currently in touch mode.  Touch mode is entered
   14034      * once the user begins interacting with the device by touch, and affects various
   14035      * things like whether focus is always visible to the user.
   14036      *
   14037      * @return Whether the device is in touch mode.
   14038      */
   14039     @ViewDebug.ExportedProperty
   14040     public boolean isInTouchMode() {
   14041         if (mAttachInfo != null) {
   14042             return mAttachInfo.mInTouchMode;
   14043         } else {
   14044             return ViewRootImpl.isInTouchMode();
   14045         }
   14046     }
   14047 
   14048     /**
   14049      * Returns the context the view is running in, through which it can
   14050      * access the current theme, resources, etc.
   14051      *
   14052      * @return The view's Context.
   14053      */
   14054     @ViewDebug.CapturedViewProperty
   14055     public final Context getContext() {
   14056         return mContext;
   14057     }
   14058 
   14059     /**
   14060      * Handle a key event before it is processed by any input method
   14061      * associated with the view hierarchy.  This can be used to intercept
   14062      * key events in special situations before the IME consumes them; a
   14063      * typical example would be handling the BACK key to update the application's
   14064      * UI instead of allowing the IME to see it and close itself.
   14065      *
   14066      * @param keyCode The value in event.getKeyCode().
   14067      * @param event Description of the key event.
   14068      * @return If you handled the event, return true. If you want to allow the
   14069      *         event to be handled by the next receiver, return false.
   14070      */
   14071     public boolean onKeyPreIme(int keyCode, KeyEvent event) {
   14072         return false;
   14073     }
   14074 
   14075     /**
   14076      * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
   14077      * KeyEvent.Callback.onKeyDown()}: perform press of the view
   14078      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
   14079      * is released, if the view is enabled and clickable.
   14080      * <p>
   14081      * Key presses in software keyboards will generally NOT trigger this
   14082      * listener, although some may elect to do so in some situations. Do not
   14083      * rely on this to catch software key presses.
   14084      *
   14085      * @param keyCode a key code that represents the button pressed, from
   14086      *                {@link android.view.KeyEvent}
   14087      * @param event the KeyEvent object that defines the button action
   14088      */
   14089     public boolean onKeyDown(int keyCode, KeyEvent event) {
   14090         if (KeyEvent.isConfirmKey(keyCode)) {
   14091             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
   14092                 return true;
   14093             }
   14094 
   14095             if (event.getRepeatCount() == 0) {
   14096                 // Long clickable items don't necessarily have to be clickable.
   14097                 final boolean clickable = (mViewFlags & CLICKABLE) == CLICKABLE
   14098                         || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
   14099                 if (clickable || (mViewFlags & TOOLTIP) == TOOLTIP) {
   14100                     // For the purposes of menu anchoring and drawable hotspots,
   14101                     // key events are considered to be at the center of the view.
   14102                     final float x = getWidth() / 2f;
   14103                     final float y = getHeight() / 2f;
   14104                     if (clickable) {
   14105                         setPressed(true, x, y);
   14106                     }
   14107                     checkForLongClick(
   14108                             ViewConfiguration.getLongPressTimeout(),
   14109                             x,
   14110                             y,
   14111                             // This is not a touch gesture -- do not classify it as one.
   14112                             TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION);
   14113                     return true;
   14114                 }
   14115             }
   14116         }
   14117 
   14118         return false;
   14119     }
   14120 
   14121     /**
   14122      * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
   14123      * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
   14124      * the event).
   14125      * <p>Key presses in software keyboards will generally NOT trigger this listener,
   14126      * although some may elect to do so in some situations. Do not rely on this to
   14127      * catch software key presses.
   14128      */
   14129     public boolean onKeyLongPress(int keyCode, KeyEvent event) {
   14130         return false;
   14131     }
   14132 
   14133     /**
   14134      * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
   14135      * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
   14136      * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
   14137      * or {@link KeyEvent#KEYCODE_SPACE} is released.
   14138      * <p>Key presses in software keyboards will generally NOT trigger this listener,
   14139      * although some may elect to do so in some situations. Do not rely on this to
   14140      * catch software key presses.
   14141      *
   14142      * @param keyCode A key code that represents the button pressed, from
   14143      *                {@link android.view.KeyEvent}.
   14144      * @param event   The KeyEvent object that defines the button action.
   14145      */
   14146     public boolean onKeyUp(int keyCode, KeyEvent event) {
   14147         if (KeyEvent.isConfirmKey(keyCode)) {
   14148             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
   14149                 return true;
   14150             }
   14151             if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
   14152                 setPressed(false);
   14153 
   14154                 if (!mHasPerformedLongPress) {
   14155                     // This is a tap, so remove the longpress check
   14156                     removeLongPressCallback();
   14157                     if (!event.isCanceled()) {
   14158                         return performClickInternal();
   14159                     }
   14160                 }
   14161             }
   14162         }
   14163         return false;
   14164     }
   14165 
   14166     /**
   14167      * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
   14168      * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
   14169      * the event).
   14170      * <p>Key presses in software keyboards will generally NOT trigger this listener,
   14171      * although some may elect to do so in some situations. Do not rely on this to
   14172      * catch software key presses.
   14173      *
   14174      * @param keyCode     A key code that represents the button pressed, from
   14175      *                    {@link android.view.KeyEvent}.
   14176      * @param repeatCount The number of times the action was made.
   14177      * @param event       The KeyEvent object that defines the button action.
   14178      */
   14179     public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
   14180         return false;
   14181     }
   14182 
   14183     /**
   14184      * Called on the focused view when a key shortcut event is not handled.
   14185      * Override this method to implement local key shortcuts for the View.
   14186      * Key shortcuts can also be implemented by setting the
   14187      * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
   14188      *
   14189      * @param keyCode The value in event.getKeyCode().
   14190      * @param event Description of the key event.
   14191      * @return If you handled the event, return true. If you want to allow the
   14192      *         event to be handled by the next receiver, return false.
   14193      */
   14194     public boolean onKeyShortcut(int keyCode, KeyEvent event) {
   14195         return false;
   14196     }
   14197 
   14198     /**
   14199      * Check whether the called view is a text editor, in which case it
   14200      * would make sense to automatically display a soft input window for
   14201      * it.  Subclasses should override this if they implement
   14202      * {@link #onCreateInputConnection(EditorInfo)} to return true if
   14203      * a call on that method would return a non-null InputConnection, and
   14204      * they are really a first-class editor that the user would normally
   14205      * start typing on when the go into a window containing your view.
   14206      *
   14207      * <p>The default implementation always returns false.  This does
   14208      * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
   14209      * will not be called or the user can not otherwise perform edits on your
   14210      * view; it is just a hint to the system that this is not the primary
   14211      * purpose of this view.
   14212      *
   14213      * @return Returns true if this view is a text editor, else false.
   14214      */
   14215     public boolean onCheckIsTextEditor() {
   14216         return false;
   14217     }
   14218 
   14219     /**
   14220      * Create a new InputConnection for an InputMethod to interact
   14221      * with the view.  The default implementation returns null, since it doesn't
   14222      * support input methods.  You can override this to implement such support.
   14223      * This is only needed for views that take focus and text input.
   14224      *
   14225      * <p>When implementing this, you probably also want to implement
   14226      * {@link #onCheckIsTextEditor()} to indicate you will return a
   14227      * non-null InputConnection.</p>
   14228      *
   14229      * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
   14230      * object correctly and in its entirety, so that the connected IME can rely
   14231      * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
   14232      * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
   14233      * must be filled in with the correct cursor position for IMEs to work correctly
   14234      * with your application.</p>
   14235      *
   14236      * @param outAttrs Fill in with attribute information about the connection.
   14237      */
   14238     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
   14239         return null;
   14240     }
   14241 
   14242     /**
   14243      * Called by the {@link android.view.inputmethod.InputMethodManager}
   14244      * when a view who is not the current
   14245      * input connection target is trying to make a call on the manager.  The
   14246      * default implementation returns false; you can override this to return
   14247      * true for certain views if you are performing InputConnection proxying
   14248      * to them.
   14249      * @param view The View that is making the InputMethodManager call.
   14250      * @return Return true to allow the call, false to reject.
   14251      */
   14252     public boolean checkInputConnectionProxy(View view) {
   14253         return false;
   14254     }
   14255 
   14256     /**
   14257      * Show the context menu for this view. It is not safe to hold on to the
   14258      * menu after returning from this method.
   14259      *
   14260      * You should normally not overload this method. Overload
   14261      * {@link #onCreateContextMenu(ContextMenu)} or define an
   14262      * {@link OnCreateContextMenuListener} to add items to the context menu.
   14263      *
   14264      * @param menu The context menu to populate
   14265      */
   14266     public void createContextMenu(ContextMenu menu) {
   14267         ContextMenuInfo menuInfo = getContextMenuInfo();
   14268 
   14269         // Sets the current menu info so all items added to menu will have
   14270         // my extra info set.
   14271         ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
   14272 
   14273         onCreateContextMenu(menu);
   14274         ListenerInfo li = mListenerInfo;
   14275         if (li != null && li.mOnCreateContextMenuListener != null) {
   14276             li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
   14277         }
   14278 
   14279         // Clear the extra information so subsequent items that aren't mine don't
   14280         // have my extra info.
   14281         ((MenuBuilder)menu).setCurrentMenuInfo(null);
   14282 
   14283         if (mParent != null) {
   14284             mParent.createContextMenu(menu);
   14285         }
   14286     }
   14287 
   14288     /**
   14289      * Views should implement this if they have extra information to associate
   14290      * with the context menu. The return result is supplied as a parameter to
   14291      * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
   14292      * callback.
   14293      *
   14294      * @return Extra information about the item for which the context menu
   14295      *         should be shown. This information will vary across different
   14296      *         subclasses of View.
   14297      */
   14298     protected ContextMenuInfo getContextMenuInfo() {
   14299         return null;
   14300     }
   14301 
   14302     /**
   14303      * Views should implement this if the view itself is going to add items to
   14304      * the context menu.
   14305      *
   14306      * @param menu the context menu to populate
   14307      */
   14308     protected void onCreateContextMenu(ContextMenu menu) {
   14309     }
   14310 
   14311     /**
   14312      * Implement this method to handle trackball motion events.  The
   14313      * <em>relative</em> movement of the trackball since the last event
   14314      * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
   14315      * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
   14316      * that a movement of 1 corresponds to the user pressing one DPAD key (so
   14317      * they will often be fractional values, representing the more fine-grained
   14318      * movement information available from a trackball).
   14319      *
   14320      * @param event The motion event.
   14321      * @return True if the event was handled, false otherwise.
   14322      */
   14323     public boolean onTrackballEvent(MotionEvent event) {
   14324         return false;
   14325     }
   14326 
   14327     /**
   14328      * Implement this method to handle generic motion events.
   14329      * <p>
   14330      * Generic motion events describe joystick movements, mouse hovers, track pad
   14331      * touches, scroll wheel movements and other input events.  The
   14332      * {@link MotionEvent#getSource() source} of the motion event specifies
   14333      * the class of input that was received.  Implementations of this method
   14334      * must examine the bits in the source before processing the event.
   14335      * The following code example shows how this is done.
   14336      * </p><p>
   14337      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
   14338      * are delivered to the view under the pointer.  All other generic motion events are
   14339      * delivered to the focused view.
   14340      * </p>
   14341      * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
   14342      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
   14343      *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
   14344      *             // process the joystick movement...
   14345      *             return true;
   14346      *         }
   14347      *     }
   14348      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
   14349      *         switch (event.getAction()) {
   14350      *             case MotionEvent.ACTION_HOVER_MOVE:
   14351      *                 // process the mouse hover movement...
   14352      *                 return true;
   14353      *             case MotionEvent.ACTION_SCROLL:
   14354      *                 // process the scroll wheel movement...
   14355      *                 return true;
   14356      *         }
   14357      *     }
   14358      *     return super.onGenericMotionEvent(event);
   14359      * }</pre>
   14360      *
   14361      * @param event The generic motion event being processed.
   14362      * @return True if the event was handled, false otherwise.
   14363      */
   14364     public boolean onGenericMotionEvent(MotionEvent event) {
   14365         return false;
   14366     }
   14367 
   14368     /**
   14369      * Dispatching hover events to {@link TouchDelegate} to improve accessibility.
   14370      * <p>
   14371      * This method is dispatching hover events to the delegate target to support explore by touch.
   14372      * Similar to {@link ViewGroup#dispatchTouchEvent}, this method send proper hover events to
   14373      * the delegate target according to the pointer and the touch area of the delegate while touch
   14374      * exploration enabled.
   14375      * </p>
   14376      *
   14377      * @param event The motion event dispatch to the delegate target.
   14378      * @return True if the event was handled, false otherwise.
   14379      *
   14380      * @see #onHoverEvent
   14381      */
   14382     private boolean dispatchTouchExplorationHoverEvent(MotionEvent event) {
   14383         final AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
   14384         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
   14385             return false;
   14386         }
   14387 
   14388         final boolean oldHoveringTouchDelegate = mHoveringTouchDelegate;
   14389         final int action = event.getActionMasked();
   14390         boolean pointInDelegateRegion = false;
   14391         boolean handled = false;
   14392 
   14393         final AccessibilityNodeInfo.TouchDelegateInfo info = mTouchDelegate.getTouchDelegateInfo();
   14394         for (int i = 0; i < info.getRegionCount(); i++) {
   14395             Region r = info.getRegionAt(i);
   14396             if (r.contains((int) event.getX(), (int) event.getY())) {
   14397                 pointInDelegateRegion = true;
   14398             }
   14399         }
   14400 
   14401         // Explore by touch should dispatch events to children under the pointer first if any
   14402         // before dispatching to TouchDelegate. For non-hoverable views that do not consume
   14403         // hover events but receive accessibility focus, it should also not delegate to these
   14404         // views when hovered.
   14405         if (!oldHoveringTouchDelegate) {
   14406             if ((action == MotionEvent.ACTION_HOVER_ENTER
   14407                     || action == MotionEvent.ACTION_HOVER_MOVE)
   14408                     && !pointInHoveredChild(event)
   14409                     && pointInDelegateRegion) {
   14410                 mHoveringTouchDelegate = true;
   14411             }
   14412         } else {
   14413             if (action == MotionEvent.ACTION_HOVER_EXIT
   14414                     || (action == MotionEvent.ACTION_HOVER_MOVE
   14415                         && (pointInHoveredChild(event) || !pointInDelegateRegion))) {
   14416                 mHoveringTouchDelegate = false;
   14417             }
   14418         }
   14419         switch (action) {
   14420             case MotionEvent.ACTION_HOVER_MOVE:
   14421                 if (oldHoveringTouchDelegate && mHoveringTouchDelegate) {
   14422                     // Inside bounds, dispatch as is.
   14423                     handled = mTouchDelegate.onTouchExplorationHoverEvent(event);
   14424                 } else if (!oldHoveringTouchDelegate && mHoveringTouchDelegate) {
   14425                     // Moving inbound, synthesize hover enter.
   14426                     MotionEvent eventNoHistory = (event.getHistorySize() == 0)
   14427                             ? event : MotionEvent.obtainNoHistory(event);
   14428                     eventNoHistory.setAction(MotionEvent.ACTION_HOVER_ENTER);
   14429                     handled = mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
   14430                     eventNoHistory.setAction(action);
   14431                     handled |= mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
   14432                 } else if (oldHoveringTouchDelegate && !mHoveringTouchDelegate) {
   14433                     // Moving outbound, synthesize hover exit.
   14434                     final boolean hoverExitPending = event.isHoverExitPending();
   14435                     event.setHoverExitPending(true);
   14436                     mTouchDelegate.onTouchExplorationHoverEvent(event);
   14437                     MotionEvent eventNoHistory = (event.getHistorySize() == 0)
   14438                             ? event : MotionEvent.obtainNoHistory(event);
   14439                     eventNoHistory.setHoverExitPending(hoverExitPending);
   14440                     eventNoHistory.setAction(MotionEvent.ACTION_HOVER_EXIT);
   14441                     mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
   14442                 }  // else: outside bounds, do nothing.
   14443                 break;
   14444             case MotionEvent.ACTION_HOVER_ENTER:
   14445                 if (!oldHoveringTouchDelegate && mHoveringTouchDelegate) {
   14446                     handled = mTouchDelegate.onTouchExplorationHoverEvent(event);
   14447                 }
   14448                 break;
   14449             case MotionEvent.ACTION_HOVER_EXIT:
   14450                 if (oldHoveringTouchDelegate) {
   14451                     mTouchDelegate.onTouchExplorationHoverEvent(event);
   14452                 }
   14453                 break;
   14454         }
   14455         return handled;
   14456     }
   14457 
   14458     /**
   14459      * Implement this method to handle hover events.
   14460      * <p>
   14461      * This method is called whenever a pointer is hovering into, over, or out of the
   14462      * bounds of a view and the view is not currently being touched.
   14463      * Hover events are represented as pointer events with action
   14464      * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
   14465      * or {@link MotionEvent#ACTION_HOVER_EXIT}.
   14466      * </p>
   14467      * <ul>
   14468      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
   14469      * when the pointer enters the bounds of the view.</li>
   14470      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
   14471      * when the pointer has already entered the bounds of the view and has moved.</li>
   14472      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
   14473      * when the pointer has exited the bounds of the view or when the pointer is
   14474      * about to go down due to a button click, tap, or similar user action that
   14475      * causes the view to be touched.</li>
   14476      * </ul>
   14477      * <p>
   14478      * The view should implement this method to return true to indicate that it is
   14479      * handling the hover event, such as by changing its drawable state.
   14480      * </p><p>
   14481      * The default implementation calls {@link #setHovered} to update the hovered state
   14482      * of the view when a hover enter or hover exit event is received, if the view
   14483      * is enabled and is clickable.  The default implementation also sends hover
   14484      * accessibility events.
   14485      * </p>
   14486      *
   14487      * @param event The motion event that describes the hover.
   14488      * @return True if the view handled the hover event.
   14489      *
   14490      * @see #isHovered
   14491      * @see #setHovered
   14492      * @see #onHoverChanged
   14493      */
   14494     public boolean onHoverEvent(MotionEvent event) {
   14495         if (mTouchDelegate != null && dispatchTouchExplorationHoverEvent(event)) {
   14496             return true;
   14497         }
   14498 
   14499         // The root view may receive hover (or touch) events that are outside the bounds of
   14500         // the window.  This code ensures that we only send accessibility events for
   14501         // hovers that are actually within the bounds of the root view.
   14502         final int action = event.getActionMasked();
   14503         if (!mSendingHoverAccessibilityEvents) {
   14504             if ((action == MotionEvent.ACTION_HOVER_ENTER
   14505                     || action == MotionEvent.ACTION_HOVER_MOVE)
   14506                     && !hasHoveredChild()
   14507                     && pointInView(event.getX(), event.getY())) {
   14508                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
   14509                 mSendingHoverAccessibilityEvents = true;
   14510             }
   14511         } else {
   14512             if (action == MotionEvent.ACTION_HOVER_EXIT
   14513                     || (action == MotionEvent.ACTION_HOVER_MOVE
   14514                             && !pointInView(event.getX(), event.getY()))) {
   14515                 mSendingHoverAccessibilityEvents = false;
   14516                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
   14517             }
   14518         }
   14519 
   14520         if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
   14521                 && event.isFromSource(InputDevice.SOURCE_MOUSE)
   14522                 && isOnScrollbar(event.getX(), event.getY())) {
   14523             awakenScrollBars();
   14524         }
   14525 
   14526         // If we consider ourself hoverable, or if we we're already hovered,
   14527         // handle changing state in response to ENTER and EXIT events.
   14528         if (isHoverable() || isHovered()) {
   14529             switch (action) {
   14530                 case MotionEvent.ACTION_HOVER_ENTER:
   14531                     setHovered(true);
   14532                     break;
   14533                 case MotionEvent.ACTION_HOVER_EXIT:
   14534                     setHovered(false);
   14535                     break;
   14536             }
   14537 
   14538             // Dispatch the event to onGenericMotionEvent before returning true.
   14539             // This is to provide compatibility with existing applications that
   14540             // handled HOVER_MOVE events in onGenericMotionEvent and that would
   14541             // break because of the new default handling for hoverable views
   14542             // in onHoverEvent.
   14543             // Note that onGenericMotionEvent will be called by default when
   14544             // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
   14545             dispatchGenericMotionEventInternal(event);
   14546             // The event was already handled by calling setHovered(), so always
   14547             // return true.
   14548             return true;
   14549         }
   14550 
   14551         return false;
   14552     }
   14553 
   14554     /**
   14555      * Returns true if the view should handle {@link #onHoverEvent}
   14556      * by calling {@link #setHovered} to change its hovered state.
   14557      *
   14558      * @return True if the view is hoverable.
   14559      */
   14560     private boolean isHoverable() {
   14561         final int viewFlags = mViewFlags;
   14562         if ((viewFlags & ENABLED_MASK) == DISABLED) {
   14563             return false;
   14564         }
   14565 
   14566         return (viewFlags & CLICKABLE) == CLICKABLE
   14567                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
   14568                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
   14569     }
   14570 
   14571     /**
   14572      * Returns true if the view is currently hovered.
   14573      *
   14574      * @return True if the view is currently hovered.
   14575      *
   14576      * @see #setHovered
   14577      * @see #onHoverChanged
   14578      */
   14579     @ViewDebug.ExportedProperty
   14580     public boolean isHovered() {
   14581         return (mPrivateFlags & PFLAG_HOVERED) != 0;
   14582     }
   14583 
   14584     /**
   14585      * Sets whether the view is currently hovered.
   14586      * <p>
   14587      * Calling this method also changes the drawable state of the view.  This
   14588      * enables the view to react to hover by using different drawable resources
   14589      * to change its appearance.
   14590      * </p><p>
   14591      * The {@link #onHoverChanged} method is called when the hovered state changes.
   14592      * </p>
   14593      *
   14594      * @param hovered True if the view is hovered.
   14595      *
   14596      * @see #isHovered
   14597      * @see #onHoverChanged
   14598      */
   14599     public void setHovered(boolean hovered) {
   14600         if (hovered) {
   14601             if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
   14602                 mPrivateFlags |= PFLAG_HOVERED;
   14603                 refreshDrawableState();
   14604                 onHoverChanged(true);
   14605             }
   14606         } else {
   14607             if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
   14608                 mPrivateFlags &= ~PFLAG_HOVERED;
   14609                 refreshDrawableState();
   14610                 onHoverChanged(false);
   14611             }
   14612         }
   14613     }
   14614 
   14615     /**
   14616      * Implement this method to handle hover state changes.
   14617      * <p>
   14618      * This method is called whenever the hover state changes as a result of a
   14619      * call to {@link #setHovered}.
   14620      * </p>
   14621      *
   14622      * @param hovered The current hover state, as returned by {@link #isHovered}.
   14623      *
   14624      * @see #isHovered
   14625      * @see #setHovered
   14626      */
   14627     public void onHoverChanged(boolean hovered) {
   14628     }
   14629 
   14630     /**
   14631      * Handles scroll bar dragging by mouse input.
   14632      *
   14633      * @hide
   14634      * @param event The motion event.
   14635      *
   14636      * @return true if the event was handled as a scroll bar dragging, false otherwise.
   14637      */
   14638     protected boolean handleScrollBarDragging(MotionEvent event) {
   14639         if (mScrollCache == null) {
   14640             return false;
   14641         }
   14642         final float x = event.getX();
   14643         final float y = event.getY();
   14644         final int action = event.getAction();
   14645         if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
   14646                 && action != MotionEvent.ACTION_DOWN)
   14647                     || !event.isFromSource(InputDevice.SOURCE_MOUSE)
   14648                     || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
   14649             mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
   14650             return false;
   14651         }
   14652 
   14653         switch (action) {
   14654             case MotionEvent.ACTION_MOVE:
   14655                 if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
   14656                     return false;
   14657                 }
   14658                 if (mScrollCache.mScrollBarDraggingState
   14659                         == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
   14660                     final Rect bounds = mScrollCache.mScrollBarBounds;
   14661                     getVerticalScrollBarBounds(bounds, null);
   14662                     final int range = computeVerticalScrollRange();
   14663                     final int offset = computeVerticalScrollOffset();
   14664                     final int extent = computeVerticalScrollExtent();
   14665 
   14666                     final int thumbLength = ScrollBarUtils.getThumbLength(
   14667                             bounds.height(), bounds.width(), extent, range);
   14668                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
   14669                             bounds.height(), thumbLength, extent, range, offset);
   14670 
   14671                     final float diff = y - mScrollCache.mScrollBarDraggingPos;
   14672                     final float maxThumbOffset = bounds.height() - thumbLength;
   14673                     final float newThumbOffset =
   14674                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
   14675                     final int height = getHeight();
   14676                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
   14677                             && height > 0 && extent > 0) {
   14678                         final int newY = Math.round((range - extent)
   14679                                 / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
   14680                         if (newY != getScrollY()) {
   14681                             mScrollCache.mScrollBarDraggingPos = y;
   14682                             setScrollY(newY);
   14683                         }
   14684                     }
   14685                     return true;
   14686                 }
   14687                 if (mScrollCache.mScrollBarDraggingState
   14688                         == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
   14689                     final Rect bounds = mScrollCache.mScrollBarBounds;
   14690                     getHorizontalScrollBarBounds(bounds, null);
   14691                     final int range = computeHorizontalScrollRange();
   14692                     final int offset = computeHorizontalScrollOffset();
   14693                     final int extent = computeHorizontalScrollExtent();
   14694 
   14695                     final int thumbLength = ScrollBarUtils.getThumbLength(
   14696                             bounds.width(), bounds.height(), extent, range);
   14697                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
   14698                             bounds.width(), thumbLength, extent, range, offset);
   14699 
   14700                     final float diff = x - mScrollCache.mScrollBarDraggingPos;
   14701                     final float maxThumbOffset = bounds.width() - thumbLength;
   14702                     final float newThumbOffset =
   14703                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
   14704                     final int width = getWidth();
   14705                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
   14706                             && width > 0 && extent > 0) {
   14707                         final int newX = Math.round((range - extent)
   14708                                 / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
   14709                         if (newX != getScrollX()) {
   14710                             mScrollCache.mScrollBarDraggingPos = x;
   14711                             setScrollX(newX);
   14712                         }
   14713                     }
   14714                     return true;
   14715                 }
   14716             case MotionEvent.ACTION_DOWN:
   14717                 if (mScrollCache.state == ScrollabilityCache.OFF) {
   14718                     return false;
   14719                 }
   14720                 if (isOnVerticalScrollbarThumb(x, y)) {
   14721                     mScrollCache.mScrollBarDraggingState =
   14722                             ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
   14723                     mScrollCache.mScrollBarDraggingPos = y;
   14724                     return true;
   14725                 }
   14726                 if (isOnHorizontalScrollbarThumb(x, y)) {
   14727                     mScrollCache.mScrollBarDraggingState =
   14728                             ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
   14729                     mScrollCache.mScrollBarDraggingPos = x;
   14730                     return true;
   14731                 }
   14732         }
   14733         mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
   14734         return false;
   14735     }
   14736 
   14737     /**
   14738      * Implement this method to handle touch screen motion events.
   14739      * <p>
   14740      * If this method is used to detect click actions, it is recommended that
   14741      * the actions be performed by implementing and calling
   14742      * {@link #performClick()}. This will ensure consistent system behavior,
   14743      * including:
   14744      * <ul>
   14745      * <li>obeying click sound preferences
   14746      * <li>dispatching OnClickListener calls
   14747      * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
   14748      * accessibility features are enabled
   14749      * </ul>
   14750      *
   14751      * @param event The motion event.
   14752      * @return True if the event was handled, false otherwise.
   14753      */
   14754     public boolean onTouchEvent(MotionEvent event) {
   14755         final float x = event.getX();
   14756         final float y = event.getY();
   14757         final int viewFlags = mViewFlags;
   14758         final int action = event.getAction();
   14759 
   14760         final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE
   14761                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
   14762                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
   14763 
   14764         if ((viewFlags & ENABLED_MASK) == DISABLED) {
   14765             if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
   14766                 setPressed(false);
   14767             }
   14768             mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
   14769             // A disabled view that is clickable still consumes the touch
   14770             // events, it just doesn't respond to them.
   14771             return clickable;
   14772         }
   14773         if (mTouchDelegate != null) {
   14774             if (mTouchDelegate.onTouchEvent(event)) {
   14775                 return true;
   14776             }
   14777         }
   14778 
   14779         if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
   14780             switch (action) {
   14781                 case MotionEvent.ACTION_UP:
   14782                     mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
   14783                     if ((viewFlags & TOOLTIP) == TOOLTIP) {
   14784                         handleTooltipUp();
   14785                     }
   14786                     if (!clickable) {
   14787                         removeTapCallback();
   14788                         removeLongPressCallback();
   14789                         mInContextButtonPress = false;
   14790                         mHasPerformedLongPress = false;
   14791                         mIgnoreNextUpEvent = false;
   14792                         break;
   14793                     }
   14794                     boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
   14795                     if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
   14796                         // take focus if we don't have it already and we should in
   14797                         // touch mode.
   14798                         boolean focusTaken = false;
   14799                         if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
   14800                             focusTaken = requestFocus();
   14801                         }
   14802 
   14803                         if (prepressed) {
   14804                             // The button is being released before we actually
   14805                             // showed it as pressed.  Make it show the pressed
   14806                             // state now (before scheduling the click) to ensure
   14807                             // the user sees it.
   14808                             setPressed(true, x, y);
   14809                         }
   14810 
   14811                         if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
   14812                             // This is a tap, so remove the longpress check
   14813                             removeLongPressCallback();
   14814 
   14815                             // Only perform take click actions if we were in the pressed state
   14816                             if (!focusTaken) {
   14817                                 // Use a Runnable and post this rather than calling
   14818                                 // performClick directly. This lets other visual state
   14819                                 // of the view update before click actions start.
   14820                                 if (mPerformClick == null) {
   14821                                     mPerformClick = new PerformClick();
   14822                                 }
   14823                                 if (!post(mPerformClick)) {
   14824                                     performClickInternal();
   14825                                 }
   14826                             }
   14827                         }
   14828 
   14829                         if (mUnsetPressedState == null) {
   14830                             mUnsetPressedState = new UnsetPressedState();
   14831                         }
   14832 
   14833                         if (prepressed) {
   14834                             postDelayed(mUnsetPressedState,
   14835                                     ViewConfiguration.getPressedStateDuration());
   14836                         } else if (!post(mUnsetPressedState)) {
   14837                             // If the post failed, unpress right now
   14838                             mUnsetPressedState.run();
   14839                         }
   14840 
   14841                         removeTapCallback();
   14842                     }
   14843                     mIgnoreNextUpEvent = false;
   14844                     break;
   14845 
   14846                 case MotionEvent.ACTION_DOWN:
   14847                     if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
   14848                         mPrivateFlags3 |= PFLAG3_FINGER_DOWN;
   14849                     }
   14850                     mHasPerformedLongPress = false;
   14851 
   14852                     if (!clickable) {
   14853                         checkForLongClick(
   14854                                 ViewConfiguration.getLongPressTimeout(),
   14855                                 x,
   14856                                 y,
   14857                                 TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
   14858                         break;
   14859                     }
   14860 
   14861                     if (performButtonActionOnTouchDown(event)) {
   14862                         break;
   14863                     }
   14864 
   14865                     // Walk up the hierarchy to determine if we're inside a scrolling container.
   14866                     boolean isInScrollingContainer = isInScrollingContainer();
   14867 
   14868                     // For views inside a scrolling container, delay the pressed feedback for
   14869                     // a short period in case this is a scroll.
   14870                     if (isInScrollingContainer) {
   14871                         mPrivateFlags |= PFLAG_PREPRESSED;
   14872                         if (mPendingCheckForTap == null) {
   14873                             mPendingCheckForTap = new CheckForTap();
   14874                         }
   14875                         mPendingCheckForTap.x = event.getX();
   14876                         mPendingCheckForTap.y = event.getY();
   14877                         postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
   14878                     } else {
   14879                         // Not inside a scrolling container, so show the feedback right away
   14880                         setPressed(true, x, y);
   14881                         checkForLongClick(
   14882                                 ViewConfiguration.getLongPressTimeout(),
   14883                                 x,
   14884                                 y,
   14885                                 TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
   14886                     }
   14887                     break;
   14888 
   14889                 case MotionEvent.ACTION_CANCEL:
   14890                     if (clickable) {
   14891                         setPressed(false);
   14892                     }
   14893                     removeTapCallback();
   14894                     removeLongPressCallback();
   14895                     mInContextButtonPress = false;
   14896                     mHasPerformedLongPress = false;
   14897                     mIgnoreNextUpEvent = false;
   14898                     mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
   14899                     break;
   14900 
   14901                 case MotionEvent.ACTION_MOVE:
   14902                     if (clickable) {
   14903                         drawableHotspotChanged(x, y);
   14904                     }
   14905 
   14906                     final int motionClassification = event.getClassification();
   14907                     final boolean ambiguousGesture =
   14908                             motionClassification == MotionEvent.CLASSIFICATION_AMBIGUOUS_GESTURE;
   14909                     int touchSlop = mTouchSlop;
   14910                     if (ambiguousGesture && hasPendingLongPressCallback()) {
   14911                         final float ambiguousMultiplier =
   14912                                 ViewConfiguration.getAmbiguousGestureMultiplier();
   14913                         if (!pointInView(x, y, touchSlop)) {
   14914                             // The default action here is to cancel long press. But instead, we
   14915                             // just extend the timeout here, in case the classification
   14916                             // stays ambiguous.
   14917                             removeLongPressCallback();
   14918                             long delay = (long) (ViewConfiguration.getLongPressTimeout()
   14919                                     * ambiguousMultiplier);
   14920                             // Subtract the time already spent
   14921                             delay -= event.getEventTime() - event.getDownTime();
   14922                             checkForLongClick(
   14923                                     delay,
   14924                                     x,
   14925                                     y,
   14926                                     TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
   14927                         }
   14928                         touchSlop *= ambiguousMultiplier;
   14929                     }
   14930 
   14931                     // Be lenient about moving outside of buttons
   14932                     if (!pointInView(x, y, touchSlop)) {
   14933                         // Outside button
   14934                         // Remove any future long press/tap checks
   14935                         removeTapCallback();
   14936                         removeLongPressCallback();
   14937                         if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
   14938                             setPressed(false);
   14939                         }
   14940                         mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
   14941                     }
   14942 
   14943                     final boolean deepPress =
   14944                             motionClassification == MotionEvent.CLASSIFICATION_DEEP_PRESS;
   14945                     if (deepPress && hasPendingLongPressCallback()) {
   14946                         // process the long click action immediately
   14947                         removeLongPressCallback();
   14948                         checkForLongClick(
   14949                                 0 /* send immediately */,
   14950                                 x,
   14951                                 y,
   14952                                 TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS);
   14953                     }
   14954 
   14955                     break;
   14956             }
   14957 
   14958             return true;
   14959         }
   14960 
   14961         return false;
   14962     }
   14963 
   14964     /**
   14965      * @hide
   14966      */
   14967     @UnsupportedAppUsage
   14968     public boolean isInScrollingContainer() {
   14969         ViewParent p = getParent();
   14970         while (p != null && p instanceof ViewGroup) {
   14971             if (((ViewGroup) p).shouldDelayChildPressedState()) {
   14972                 return true;
   14973             }
   14974             p = p.getParent();
   14975         }
   14976         return false;
   14977     }
   14978 
   14979     /**
   14980      * Remove the longpress detection timer.
   14981      */
   14982     private void removeLongPressCallback() {
   14983         if (mPendingCheckForLongPress != null) {
   14984             removeCallbacks(mPendingCheckForLongPress);
   14985         }
   14986     }
   14987 
   14988     /**
   14989      * Return true if the long press callback is scheduled to run sometime in the future.
   14990      * Return false if there is no scheduled long press callback at the moment.
   14991      */
   14992     private boolean hasPendingLongPressCallback() {
   14993         if (mPendingCheckForLongPress == null) {
   14994             return false;
   14995         }
   14996         final AttachInfo attachInfo = mAttachInfo;
   14997         if (attachInfo == null) {
   14998             return false;
   14999         }
   15000         return attachInfo.mHandler.hasCallbacks(mPendingCheckForLongPress);
   15001     }
   15002 
   15003    /**
   15004      * Remove the pending click action
   15005      */
   15006     @UnsupportedAppUsage
   15007     private void removePerformClickCallback() {
   15008         if (mPerformClick != null) {
   15009             removeCallbacks(mPerformClick);
   15010         }
   15011     }
   15012 
   15013     /**
   15014      * Remove the prepress detection timer.
   15015      */
   15016     private void removeUnsetPressCallback() {
   15017         if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
   15018             setPressed(false);
   15019             removeCallbacks(mUnsetPressedState);
   15020         }
   15021     }
   15022 
   15023     /**
   15024      * Remove the tap detection timer.
   15025      */
   15026     private void removeTapCallback() {
   15027         if (mPendingCheckForTap != null) {
   15028             mPrivateFlags &= ~PFLAG_PREPRESSED;
   15029             removeCallbacks(mPendingCheckForTap);
   15030         }
   15031     }
   15032 
   15033     /**
   15034      * Cancels a pending long press.  Your subclass can use this if you
   15035      * want the context menu to come up if the user presses and holds
   15036      * at the same place, but you don't want it to come up if they press
   15037      * and then move around enough to cause scrolling.
   15038      */
   15039     public void cancelLongPress() {
   15040         removeLongPressCallback();
   15041 
   15042         /*
   15043          * The prepressed state handled by the tap callback is a display
   15044          * construct, but the tap callback will post a long press callback
   15045          * less its own timeout. Remove it here.
   15046          */
   15047         removeTapCallback();
   15048     }
   15049 
   15050     /**
   15051      * Sets the TouchDelegate for this View.
   15052      */
   15053     public void setTouchDelegate(TouchDelegate delegate) {
   15054         mTouchDelegate = delegate;
   15055     }
   15056 
   15057     /**
   15058      * Gets the TouchDelegate for this View.
   15059      */
   15060     public TouchDelegate getTouchDelegate() {
   15061         return mTouchDelegate;
   15062     }
   15063 
   15064     /**
   15065      * Request unbuffered dispatch of the given stream of MotionEvents to this View.
   15066      *
   15067      * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
   15068      * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
   15069      * available. This method should only be called for touch events.
   15070      *
   15071      * <p class="note">This api is not intended for most applications. Buffered dispatch
   15072      * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
   15073      * streams will not improve your input latency. Side effects include: increased latency,
   15074      * jittery scrolls and inability to take advantage of system resampling. Talk to your input
   15075      * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
   15076      * you.</p>
   15077      */
   15078     public final void requestUnbufferedDispatch(MotionEvent event) {
   15079         final int action = event.getAction();
   15080         if (mAttachInfo == null
   15081                 || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
   15082                 || !event.isTouchEvent()) {
   15083             return;
   15084         }
   15085         mAttachInfo.mUnbufferedDispatchRequested = true;
   15086     }
   15087 
   15088     private boolean hasSize() {
   15089         return (mBottom > mTop) && (mRight > mLeft);
   15090     }
   15091 
   15092     private boolean canTakeFocus() {
   15093         return ((mViewFlags & VISIBILITY_MASK) == VISIBLE)
   15094                 && ((mViewFlags & FOCUSABLE) == FOCUSABLE)
   15095                 && ((mViewFlags & ENABLED_MASK) == ENABLED)
   15096                 && (sCanFocusZeroSized || !isLayoutValid() || hasSize());
   15097     }
   15098 
   15099     /**
   15100      * Set flags controlling behavior of this view.
   15101      *
   15102      * @param flags Constant indicating the value which should be set
   15103      * @param mask Constant indicating the bit range that should be changed
   15104      */
   15105     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
   15106     void setFlags(int flags, int mask) {
   15107         final boolean accessibilityEnabled =
   15108                 AccessibilityManager.getInstance(mContext).isEnabled();
   15109         final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
   15110 
   15111         int old = mViewFlags;
   15112         mViewFlags = (mViewFlags & ~mask) | (flags & mask);
   15113 
   15114         int changed = mViewFlags ^ old;
   15115         if (changed == 0) {
   15116             return;
   15117         }
   15118         int privateFlags = mPrivateFlags;
   15119         boolean shouldNotifyFocusableAvailable = false;
   15120 
   15121         // If focusable is auto, update the FOCUSABLE bit.
   15122         int focusableChangedByAuto = 0;
   15123         if (((mViewFlags & FOCUSABLE_AUTO) != 0)
   15124                 && (changed & (FOCUSABLE_MASK | CLICKABLE)) != 0) {
   15125             // Heuristic only takes into account whether view is clickable.
   15126             final int newFocus;
   15127             if ((mViewFlags & CLICKABLE) != 0) {
   15128                 newFocus = FOCUSABLE;
   15129             } else {
   15130                 newFocus = NOT_FOCUSABLE;
   15131             }
   15132             mViewFlags = (mViewFlags & ~FOCUSABLE) | newFocus;
   15133             focusableChangedByAuto = (old & FOCUSABLE) ^ (newFocus & FOCUSABLE);
   15134             changed = (changed & ~FOCUSABLE) | focusableChangedByAuto;
   15135         }
   15136 
   15137         /* Check if the FOCUSABLE bit has changed */
   15138         if (((changed & FOCUSABLE) != 0) && ((privateFlags & PFLAG_HAS_BOUNDS) != 0)) {
   15139             if (((old & FOCUSABLE) == FOCUSABLE)
   15140                     && ((privateFlags & PFLAG_FOCUSED) != 0)) {
   15141                 /* Give up focus if we are no longer focusable */
   15142                 clearFocus();
   15143                 if (mParent instanceof ViewGroup) {
   15144                     ((ViewGroup) mParent).clearFocusedInCluster();
   15145                 }
   15146             } else if (((old & FOCUSABLE) == NOT_FOCUSABLE)
   15147                     && ((privateFlags & PFLAG_FOCUSED) == 0)) {
   15148                 /*
   15149                  * Tell the view system that we are now available to take focus
   15150                  * if no one else already has it.
   15151                  */
   15152                 if (mParent != null) {
   15153                     ViewRootImpl viewRootImpl = getViewRootImpl();
   15154                     if (!sAutoFocusableOffUIThreadWontNotifyParents
   15155                             || focusableChangedByAuto == 0
   15156                             || viewRootImpl == null
   15157                             || viewRootImpl.mThread == Thread.currentThread()) {
   15158                         shouldNotifyFocusableAvailable = canTakeFocus();
   15159                     }
   15160                 }
   15161             }
   15162         }
   15163 
   15164         final int newVisibility = flags & VISIBILITY_MASK;
   15165         if (newVisibility == VISIBLE) {
   15166             if ((changed & VISIBILITY_MASK) != 0) {
   15167                 /*
   15168                  * If this view is becoming visible, invalidate it in case it changed while
   15169                  * it was not visible. Marking it drawn ensures that the invalidation will
   15170                  * go through.
   15171                  */
   15172                 mPrivateFlags |= PFLAG_DRAWN;
   15173                 invalidate(true);
   15174 
   15175                 needGlobalAttributesUpdate(true);
   15176 
   15177                 // a view becoming visible is worth notifying the parent about in case nothing has
   15178                 // focus. Even if this specific view isn't focusable, it may contain something that
   15179                 // is, so let the root view try to give this focus if nothing else does.
   15180                 shouldNotifyFocusableAvailable = hasSize();
   15181             }
   15182         }
   15183 
   15184         if ((changed & ENABLED_MASK) != 0) {
   15185             if ((mViewFlags & ENABLED_MASK) == ENABLED) {
   15186                 // a view becoming enabled should notify the parent as long as the view is also
   15187                 // visible and the parent wasn't already notified by becoming visible during this
   15188                 // setFlags invocation.
   15189                 shouldNotifyFocusableAvailable = canTakeFocus();
   15190             } else {
   15191                 if (isFocused()) clearFocus();
   15192             }
   15193         }
   15194 
   15195         if (shouldNotifyFocusableAvailable && mParent != null) {
   15196             mParent.focusableViewAvailable(this);
   15197         }
   15198 
   15199         /* Check if the GONE bit has changed */
   15200         if ((changed & GONE) != 0) {
   15201             needGlobalAttributesUpdate(false);
   15202             requestLayout();
   15203 
   15204             if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
   15205                 if (hasFocus()) {
   15206                     clearFocus();
   15207                     if (mParent instanceof ViewGroup) {
   15208                         ((ViewGroup) mParent).clearFocusedInCluster();
   15209                     }
   15210                 }
   15211                 clearAccessibilityFocus();
   15212                 destroyDrawingCache();
   15213                 if (mParent instanceof View) {
   15214                     // GONE views noop invalidation, so invalidate the parent
   15215                     ((View) mParent).invalidate(true);
   15216                 }
   15217                 // Mark the view drawn to ensure that it gets invalidated properly the next
   15218                 // time it is visible and gets invalidated
   15219                 mPrivateFlags |= PFLAG_DRAWN;
   15220             }
   15221             if (mAttachInfo != null) {
   15222                 mAttachInfo.mViewVisibilityChanged = true;
   15223             }
   15224         }
   15225 
   15226         /* Check if the VISIBLE bit has changed */
   15227         if ((changed & INVISIBLE) != 0) {
   15228             needGlobalAttributesUpdate(false);
   15229             /*
   15230              * If this view is becoming invisible, set the DRAWN flag so that
   15231              * the next invalidate() will not be skipped.
   15232              */
   15233             mPrivateFlags |= PFLAG_DRAWN;
   15234 
   15235             if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
   15236                 // root view becoming invisible shouldn't clear focus and accessibility focus
   15237                 if (getRootView() != this) {
   15238                     if (hasFocus()) {
   15239                         clearFocus();
   15240                         if (mParent instanceof ViewGroup) {
   15241                             ((ViewGroup) mParent).clearFocusedInCluster();
   15242                         }
   15243                     }
   15244                     clearAccessibilityFocus();
   15245                 }
   15246             }
   15247             if (mAttachInfo != null) {
   15248                 mAttachInfo.mViewVisibilityChanged = true;
   15249             }
   15250         }
   15251 
   15252         if ((changed & VISIBILITY_MASK) != 0) {
   15253             // If the view is invisible, cleanup its display list to free up resources
   15254             if (newVisibility != VISIBLE && mAttachInfo != null) {
   15255                 cleanupDraw();
   15256             }
   15257 
   15258             if (mParent instanceof ViewGroup) {
   15259                 ViewGroup parent = (ViewGroup) mParent;
   15260                 parent.onChildVisibilityChanged(this, (changed & VISIBILITY_MASK),
   15261                         newVisibility);
   15262                 parent.invalidate(true);
   15263             } else if (mParent != null) {
   15264                 mParent.invalidateChild(this, null);
   15265             }
   15266 
   15267             if (mAttachInfo != null) {
   15268                 dispatchVisibilityChanged(this, newVisibility);
   15269 
   15270                 // Aggregated visibility changes are dispatched to attached views
   15271                 // in visible windows where the parent is currently shown/drawn
   15272                 // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
   15273                 // discounting clipping or overlapping. This makes it a good place
   15274                 // to change animation states.
   15275                 if (mParent != null && getWindowVisibility() == VISIBLE &&
   15276                         ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
   15277                     dispatchVisibilityAggregated(newVisibility == VISIBLE);
   15278                 }
   15279                 notifySubtreeAccessibilityStateChangedIfNeeded();
   15280             }
   15281         }
   15282 
   15283         if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
   15284             destroyDrawingCache();
   15285         }
   15286 
   15287         if ((changed & DRAWING_CACHE_ENABLED) != 0) {
   15288             destroyDrawingCache();
   15289             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
   15290             invalidateParentCaches();
   15291         }
   15292 
   15293         if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
   15294             destroyDrawingCache();
   15295             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
   15296         }
   15297 
   15298         if ((changed & DRAW_MASK) != 0) {
   15299             if ((mViewFlags & WILL_NOT_DRAW) != 0) {
   15300                 if (mBackground != null
   15301                         || mDefaultFocusHighlight != null
   15302                         || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
   15303                     mPrivateFlags &= ~PFLAG_SKIP_DRAW;
   15304                 } else {
   15305                     mPrivateFlags |= PFLAG_SKIP_DRAW;
   15306                 }
   15307             } else {
   15308                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
   15309             }
   15310             requestLayout();
   15311             invalidate(true);
   15312         }
   15313 
   15314         if ((changed & KEEP_SCREEN_ON) != 0) {
   15315             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
   15316                 mParent.recomputeViewAttributes(this);
   15317             }
   15318         }
   15319 
   15320         if (accessibilityEnabled) {
   15321             // If we're an accessibility pane and the visibility changed, we already have sent
   15322             // a state change, so we really don't need to report other changes.
   15323             if (isAccessibilityPane()) {
   15324                 changed &= ~VISIBILITY_MASK;
   15325             }
   15326             if ((changed & FOCUSABLE) != 0 || (changed & VISIBILITY_MASK) != 0
   15327                     || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
   15328                     || (changed & CONTEXT_CLICKABLE) != 0) {
   15329                 if (oldIncludeForAccessibility != includeForAccessibility()) {
   15330                     notifySubtreeAccessibilityStateChangedIfNeeded();
   15331                 } else {
   15332                     notifyViewAccessibilityStateChangedIfNeeded(
   15333                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   15334                 }
   15335             } else if ((changed & ENABLED_MASK) != 0) {
   15336                 notifyViewAccessibilityStateChangedIfNeeded(
   15337                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   15338             }
   15339         }
   15340     }
   15341 
   15342     /**
   15343      * Change the view's z order in the tree, so it's on top of other sibling
   15344      * views. This ordering change may affect layout, if the parent container
   15345      * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
   15346      * to {@link android.os.Build.VERSION_CODES#KITKAT} this
   15347      * method should be followed by calls to {@link #requestLayout()} and
   15348      * {@link View#invalidate()} on the view's parent to force the parent to redraw
   15349      * with the new child ordering.
   15350      *
   15351      * @see ViewGroup#bringChildToFront(View)
   15352      */
   15353     public void bringToFront() {
   15354         if (mParent != null) {
   15355             mParent.bringChildToFront(this);
   15356         }
   15357     }
   15358 
   15359     /**
   15360      * This is called in response to an internal scroll in this view (i.e., the
   15361      * view scrolled its own contents). This is typically as a result of
   15362      * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
   15363      * called.
   15364      *
   15365      * @param l Current horizontal scroll origin.
   15366      * @param t Current vertical scroll origin.
   15367      * @param oldl Previous horizontal scroll origin.
   15368      * @param oldt Previous vertical scroll origin.
   15369      */
   15370     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
   15371         notifySubtreeAccessibilityStateChangedIfNeeded();
   15372 
   15373         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
   15374             postSendViewScrolledAccessibilityEventCallback(l - oldl, t - oldt);
   15375         }
   15376 
   15377         mBackgroundSizeChanged = true;
   15378         mDefaultFocusHighlightSizeChanged = true;
   15379         if (mForegroundInfo != null) {
   15380             mForegroundInfo.mBoundsChanged = true;
   15381         }
   15382 
   15383         final AttachInfo ai = mAttachInfo;
   15384         if (ai != null) {
   15385             ai.mViewScrollChanged = true;
   15386         }
   15387 
   15388         if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
   15389             mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
   15390         }
   15391     }
   15392 
   15393     /**
   15394      * Interface definition for a callback to be invoked when the scroll
   15395      * X or Y positions of a view change.
   15396      * <p>
   15397      * <b>Note:</b> Some views handle scrolling independently from View and may
   15398      * have their own separate listeners for scroll-type events. For example,
   15399      * {@link android.widget.ListView ListView} allows clients to register an
   15400      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
   15401      * to listen for changes in list scroll position.
   15402      *
   15403      * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
   15404      */
   15405     public interface OnScrollChangeListener {
   15406         /**
   15407          * Called when the scroll position of a view changes.
   15408          *
   15409          * @param v The view whose scroll position has changed.
   15410          * @param scrollX Current horizontal scroll origin.
   15411          * @param scrollY Current vertical scroll origin.
   15412          * @param oldScrollX Previous horizontal scroll origin.
   15413          * @param oldScrollY Previous vertical scroll origin.
   15414          */
   15415         void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
   15416     }
   15417 
   15418     /**
   15419      * Interface definition for a callback to be invoked when the layout bounds of a view
   15420      * changes due to layout processing.
   15421      */
   15422     public interface OnLayoutChangeListener {
   15423         /**
   15424          * Called when the layout bounds of a view changes due to layout processing.
   15425          *
   15426          * @param v The view whose bounds have changed.
   15427          * @param left The new value of the view's left property.
   15428          * @param top The new value of the view's top property.
   15429          * @param right The new value of the view's right property.
   15430          * @param bottom The new value of the view's bottom property.
   15431          * @param oldLeft The previous value of the view's left property.
   15432          * @param oldTop The previous value of the view's top property.
   15433          * @param oldRight The previous value of the view's right property.
   15434          * @param oldBottom The previous value of the view's bottom property.
   15435          */
   15436         void onLayoutChange(View v, int left, int top, int right, int bottom,
   15437             int oldLeft, int oldTop, int oldRight, int oldBottom);
   15438     }
   15439 
   15440     /**
   15441      * This is called during layout when the size of this view has changed. If
   15442      * you were just added to the view hierarchy, you're called with the old
   15443      * values of 0.
   15444      *
   15445      * @param w Current width of this view.
   15446      * @param h Current height of this view.
   15447      * @param oldw Old width of this view.
   15448      * @param oldh Old height of this view.
   15449      */
   15450     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
   15451     }
   15452 
   15453     /**
   15454      * Called by draw to draw the child views. This may be overridden
   15455      * by derived classes to gain control just before its children are drawn
   15456      * (but after its own view has been drawn).
   15457      * @param canvas the canvas on which to draw the view
   15458      */
   15459     protected void dispatchDraw(Canvas canvas) {
   15460 
   15461     }
   15462 
   15463     /**
   15464      * Gets the parent of this view. Note that the parent is a
   15465      * ViewParent and not necessarily a View.
   15466      *
   15467      * @return Parent of this view.
   15468      */
   15469     public final ViewParent getParent() {
   15470         return mParent;
   15471     }
   15472 
   15473     /**
   15474      * Set the horizontal scrolled position of your view. This will cause a call to
   15475      * {@link #onScrollChanged(int, int, int, int)} and the view will be
   15476      * invalidated.
   15477      * @param value the x position to scroll to
   15478      */
   15479     public void setScrollX(int value) {
   15480         scrollTo(value, mScrollY);
   15481     }
   15482 
   15483     /**
   15484      * Set the vertical scrolled position of your view. This will cause a call to
   15485      * {@link #onScrollChanged(int, int, int, int)} and the view will be
   15486      * invalidated.
   15487      * @param value the y position to scroll to
   15488      */
   15489     public void setScrollY(int value) {
   15490         scrollTo(mScrollX, value);
   15491     }
   15492 
   15493     /**
   15494      * Return the scrolled left position of this view. This is the left edge of
   15495      * the displayed part of your view. You do not need to draw any pixels
   15496      * farther left, since those are outside of the frame of your view on
   15497      * screen.
   15498      *
   15499      * @return The left edge of the displayed part of your view, in pixels.
   15500      */
   15501     @InspectableProperty
   15502     public final int getScrollX() {
   15503         return mScrollX;
   15504     }
   15505 
   15506     /**
   15507      * Return the scrolled top position of this view. This is the top edge of
   15508      * the displayed part of your view. You do not need to draw any pixels above
   15509      * it, since those are outside of the frame of your view on screen.
   15510      *
   15511      * @return The top edge of the displayed part of your view, in pixels.
   15512      */
   15513     @InspectableProperty
   15514     public final int getScrollY() {
   15515         return mScrollY;
   15516     }
   15517 
   15518     /**
   15519      * Return the width of your view.
   15520      *
   15521      * @return The width of your view, in pixels.
   15522      */
   15523     @ViewDebug.ExportedProperty(category = "layout")
   15524     public final int getWidth() {
   15525         return mRight - mLeft;
   15526     }
   15527 
   15528     /**
   15529      * Return the height of your view.
   15530      *
   15531      * @return The height of your view, in pixels.
   15532      */
   15533     @ViewDebug.ExportedProperty(category = "layout")
   15534     public final int getHeight() {
   15535         return mBottom - mTop;
   15536     }
   15537 
   15538     /**
   15539      * Return the visible drawing bounds of your view. Fills in the output
   15540      * rectangle with the values from getScrollX(), getScrollY(),
   15541      * getWidth(), and getHeight(). These bounds do not account for any
   15542      * transformation properties currently set on the view, such as
   15543      * {@link #setScaleX(float)} or {@link #setRotation(float)}.
   15544      *
   15545      * @param outRect The (scrolled) drawing bounds of the view.
   15546      */
   15547     public void getDrawingRect(Rect outRect) {
   15548         outRect.left = mScrollX;
   15549         outRect.top = mScrollY;
   15550         outRect.right = mScrollX + (mRight - mLeft);
   15551         outRect.bottom = mScrollY + (mBottom - mTop);
   15552     }
   15553 
   15554     /**
   15555      * Like {@link #getMeasuredWidthAndState()}, but only returns the
   15556      * raw width component (that is the result is masked by
   15557      * {@link #MEASURED_SIZE_MASK}).
   15558      *
   15559      * @return The raw measured width of this view.
   15560      */
   15561     public final int getMeasuredWidth() {
   15562         return mMeasuredWidth & MEASURED_SIZE_MASK;
   15563     }
   15564 
   15565     /**
   15566      * Return the full width measurement information for this view as computed
   15567      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
   15568      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
   15569      * This should be used during measurement and layout calculations only. Use
   15570      * {@link #getWidth()} to see how wide a view is after layout.
   15571      *
   15572      * @return The measured width of this view as a bit mask.
   15573      */
   15574     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
   15575             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
   15576                     name = "MEASURED_STATE_TOO_SMALL"),
   15577     })
   15578     public final int getMeasuredWidthAndState() {
   15579         return mMeasuredWidth;
   15580     }
   15581 
   15582     /**
   15583      * Like {@link #getMeasuredHeightAndState()}, but only returns the
   15584      * raw height component (that is the result is masked by
   15585      * {@link #MEASURED_SIZE_MASK}).
   15586      *
   15587      * @return The raw measured height of this view.
   15588      */
   15589     public final int getMeasuredHeight() {
   15590         return mMeasuredHeight & MEASURED_SIZE_MASK;
   15591     }
   15592 
   15593     /**
   15594      * Return the full height measurement information for this view as computed
   15595      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
   15596      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
   15597      * This should be used during measurement and layout calculations only. Use
   15598      * {@link #getHeight()} to see how wide a view is after layout.
   15599      *
   15600      * @return The measured height of this view as a bit mask.
   15601      */
   15602     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
   15603             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
   15604                     name = "MEASURED_STATE_TOO_SMALL"),
   15605     })
   15606     public final int getMeasuredHeightAndState() {
   15607         return mMeasuredHeight;
   15608     }
   15609 
   15610     /**
   15611      * Return only the state bits of {@link #getMeasuredWidthAndState()}
   15612      * and {@link #getMeasuredHeightAndState()}, combined into one integer.
   15613      * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
   15614      * and the height component is at the shifted bits
   15615      * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
   15616      */
   15617     public final int getMeasuredState() {
   15618         return (mMeasuredWidth&MEASURED_STATE_MASK)
   15619                 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
   15620                         & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
   15621     }
   15622 
   15623     /**
   15624      * The transform matrix of this view, which is calculated based on the current
   15625      * rotation, scale, and pivot properties.
   15626      *
   15627      * @see #getRotation()
   15628      * @see #getScaleX()
   15629      * @see #getScaleY()
   15630      * @see #getPivotX()
   15631      * @see #getPivotY()
   15632      * @return The current transform matrix for the view
   15633      */
   15634     public Matrix getMatrix() {
   15635         ensureTransformationInfo();
   15636         final Matrix matrix = mTransformationInfo.mMatrix;
   15637         mRenderNode.getMatrix(matrix);
   15638         return matrix;
   15639     }
   15640 
   15641     /**
   15642      * Returns true if the transform matrix is the identity matrix.
   15643      * Recomputes the matrix if necessary.
   15644      *
   15645      * @return True if the transform matrix is the identity matrix, false otherwise.
   15646      * @hide
   15647      */
   15648     @UnsupportedAppUsage
   15649     public final boolean hasIdentityMatrix() {
   15650         return mRenderNode.hasIdentityMatrix();
   15651     }
   15652 
   15653     @UnsupportedAppUsage
   15654     void ensureTransformationInfo() {
   15655         if (mTransformationInfo == null) {
   15656             mTransformationInfo = new TransformationInfo();
   15657         }
   15658     }
   15659 
   15660     /**
   15661      * Utility method to retrieve the inverse of the current mMatrix property.
   15662      * We cache the matrix to avoid recalculating it when transform properties
   15663      * have not changed.
   15664      *
   15665      * @return The inverse of the current matrix of this view.
   15666      * @hide
   15667      */
   15668     @UnsupportedAppUsage
   15669     public final Matrix getInverseMatrix() {
   15670         ensureTransformationInfo();
   15671         if (mTransformationInfo.mInverseMatrix == null) {
   15672             mTransformationInfo.mInverseMatrix = new Matrix();
   15673         }
   15674         final Matrix matrix = mTransformationInfo.mInverseMatrix;
   15675         mRenderNode.getInverseMatrix(matrix);
   15676         return matrix;
   15677     }
   15678 
   15679     /**
   15680      * Gets the distance along the Z axis from the camera to this view.
   15681      *
   15682      * @see #setCameraDistance(float)
   15683      *
   15684      * @return The distance along the Z axis.
   15685      */
   15686     public float getCameraDistance() {
   15687         final float dpi = mResources.getDisplayMetrics().densityDpi;
   15688         return mRenderNode.getCameraDistance() * dpi;
   15689     }
   15690 
   15691     /**
   15692      * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
   15693      * views are drawn) from the camera to this view. The camera's distance
   15694      * affects 3D transformations, for instance rotations around the X and Y
   15695      * axis. If the rotationX or rotationY properties are changed and this view is
   15696      * large (more than half the size of the screen), it is recommended to always
   15697      * use a camera distance that's greater than the height (X axis rotation) or
   15698      * the width (Y axis rotation) of this view.</p>
   15699      *
   15700      * <p>The distance of the camera from the view plane can have an affect on the
   15701      * perspective distortion of the view when it is rotated around the x or y axis.
   15702      * For example, a large distance will result in a large viewing angle, and there
   15703      * will not be much perspective distortion of the view as it rotates. A short
   15704      * distance may cause much more perspective distortion upon rotation, and can
   15705      * also result in some drawing artifacts if the rotated view ends up partially
   15706      * behind the camera (which is why the recommendation is to use a distance at
   15707      * least as far as the size of the view, if the view is to be rotated.)</p>
   15708      *
   15709      * <p>The distance is expressed in "depth pixels." The default distance depends
   15710      * on the screen density. For instance, on a medium density display, the
   15711      * default distance is 1280. On a high density display, the default distance
   15712      * is 1920.</p>
   15713      *
   15714      * <p>If you want to specify a distance that leads to visually consistent
   15715      * results across various densities, use the following formula:</p>
   15716      * <pre>
   15717      * float scale = context.getResources().getDisplayMetrics().density;
   15718      * view.setCameraDistance(distance * scale);
   15719      * </pre>
   15720      *
   15721      * <p>The density scale factor of a high density display is 1.5,
   15722      * and 1920 = 1280 * 1.5.</p>
   15723      *
   15724      * @param distance The distance in "depth pixels", if negative the opposite
   15725      *        value is used
   15726      *
   15727      * @see #setRotationX(float)
   15728      * @see #setRotationY(float)
   15729      */
   15730     public void setCameraDistance(float distance) {
   15731         final float dpi = mResources.getDisplayMetrics().densityDpi;
   15732 
   15733         invalidateViewProperty(true, false);
   15734         mRenderNode.setCameraDistance(Math.abs(distance) / dpi);
   15735         invalidateViewProperty(false, false);
   15736 
   15737         invalidateParentIfNeededAndWasQuickRejected();
   15738     }
   15739 
   15740     /**
   15741      * The degrees that the view is rotated around the pivot point.
   15742      *
   15743      * @see #setRotation(float)
   15744      * @see #getPivotX()
   15745      * @see #getPivotY()
   15746      *
   15747      * @return The degrees of rotation.
   15748      */
   15749     @ViewDebug.ExportedProperty(category = "drawing")
   15750     @InspectableProperty
   15751     public float getRotation() {
   15752         return mRenderNode.getRotationZ();
   15753     }
   15754 
   15755     /**
   15756      * Sets the degrees that the view is rotated around the pivot point. Increasing values
   15757      * result in clockwise rotation.
   15758      *
   15759      * @param rotation The degrees of rotation.
   15760      *
   15761      * @see #getRotation()
   15762      * @see #getPivotX()
   15763      * @see #getPivotY()
   15764      * @see #setRotationX(float)
   15765      * @see #setRotationY(float)
   15766      *
   15767      * @attr ref android.R.styleable#View_rotation
   15768      */
   15769     public void setRotation(float rotation) {
   15770         if (rotation != getRotation()) {
   15771             // Double-invalidation is necessary to capture view's old and new areas
   15772             invalidateViewProperty(true, false);
   15773             mRenderNode.setRotationZ(rotation);
   15774             invalidateViewProperty(false, true);
   15775 
   15776             invalidateParentIfNeededAndWasQuickRejected();
   15777             notifySubtreeAccessibilityStateChangedIfNeeded();
   15778         }
   15779     }
   15780 
   15781     /**
   15782      * The degrees that the view is rotated around the vertical axis through the pivot point.
   15783      *
   15784      * @see #getPivotX()
   15785      * @see #getPivotY()
   15786      * @see #setRotationY(float)
   15787      *
   15788      * @return The degrees of Y rotation.
   15789      */
   15790     @ViewDebug.ExportedProperty(category = "drawing")
   15791     @InspectableProperty
   15792     public float getRotationY() {
   15793         return mRenderNode.getRotationY();
   15794     }
   15795 
   15796     /**
   15797      * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
   15798      * Increasing values result in counter-clockwise rotation from the viewpoint of looking
   15799      * down the y axis.
   15800      *
   15801      * When rotating large views, it is recommended to adjust the camera distance
   15802      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
   15803      *
   15804      * @param rotationY The degrees of Y rotation.
   15805      *
   15806      * @see #getRotationY()
   15807      * @see #getPivotX()
   15808      * @see #getPivotY()
   15809      * @see #setRotation(float)
   15810      * @see #setRotationX(float)
   15811      * @see #setCameraDistance(float)
   15812      *
   15813      * @attr ref android.R.styleable#View_rotationY
   15814      */
   15815     public void setRotationY(float rotationY) {
   15816         if (rotationY != getRotationY()) {
   15817             invalidateViewProperty(true, false);
   15818             mRenderNode.setRotationY(rotationY);
   15819             invalidateViewProperty(false, true);
   15820 
   15821             invalidateParentIfNeededAndWasQuickRejected();
   15822             notifySubtreeAccessibilityStateChangedIfNeeded();
   15823         }
   15824     }
   15825 
   15826     /**
   15827      * The degrees that the view is rotated around the horizontal axis through the pivot point.
   15828      *
   15829      * @see #getPivotX()
   15830      * @see #getPivotY()
   15831      * @see #setRotationX(float)
   15832      *
   15833      * @return The degrees of X rotation.
   15834      */
   15835     @ViewDebug.ExportedProperty(category = "drawing")
   15836     @InspectableProperty
   15837     public float getRotationX() {
   15838         return mRenderNode.getRotationX();
   15839     }
   15840 
   15841     /**
   15842      * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
   15843      * Increasing values result in clockwise rotation from the viewpoint of looking down the
   15844      * x axis.
   15845      *
   15846      * When rotating large views, it is recommended to adjust the camera distance
   15847      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
   15848      *
   15849      * @param rotationX The degrees of X rotation.
   15850      *
   15851      * @see #getRotationX()
   15852      * @see #getPivotX()
   15853      * @see #getPivotY()
   15854      * @see #setRotation(float)
   15855      * @see #setRotationY(float)
   15856      * @see #setCameraDistance(float)
   15857      *
   15858      * @attr ref android.R.styleable#View_rotationX
   15859      */
   15860     public void setRotationX(float rotationX) {
   15861         if (rotationX != getRotationX()) {
   15862             invalidateViewProperty(true, false);
   15863             mRenderNode.setRotationX(rotationX);
   15864             invalidateViewProperty(false, true);
   15865 
   15866             invalidateParentIfNeededAndWasQuickRejected();
   15867             notifySubtreeAccessibilityStateChangedIfNeeded();
   15868         }
   15869     }
   15870 
   15871     /**
   15872      * The amount that the view is scaled in x around the pivot point, as a proportion of
   15873      * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
   15874      *
   15875      * <p>By default, this is 1.0f.
   15876      *
   15877      * @see #getPivotX()
   15878      * @see #getPivotY()
   15879      * @return The scaling factor.
   15880      */
   15881     @ViewDebug.ExportedProperty(category = "drawing")
   15882     @InspectableProperty
   15883     public float getScaleX() {
   15884         return mRenderNode.getScaleX();
   15885     }
   15886 
   15887     /**
   15888      * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
   15889      * the view's unscaled width. A value of 1 means that no scaling is applied.
   15890      *
   15891      * @param scaleX The scaling factor.
   15892      * @see #getPivotX()
   15893      * @see #getPivotY()
   15894      *
   15895      * @attr ref android.R.styleable#View_scaleX
   15896      */
   15897     public void setScaleX(float scaleX) {
   15898         if (scaleX != getScaleX()) {
   15899             scaleX = sanitizeFloatPropertyValue(scaleX, "scaleX");
   15900             invalidateViewProperty(true, false);
   15901             mRenderNode.setScaleX(scaleX);
   15902             invalidateViewProperty(false, true);
   15903 
   15904             invalidateParentIfNeededAndWasQuickRejected();
   15905             notifySubtreeAccessibilityStateChangedIfNeeded();
   15906         }
   15907     }
   15908 
   15909     /**
   15910      * The amount that the view is scaled in y around the pivot point, as a proportion of
   15911      * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
   15912      *
   15913      * <p>By default, this is 1.0f.
   15914      *
   15915      * @see #getPivotX()
   15916      * @see #getPivotY()
   15917      * @return The scaling factor.
   15918      */
   15919     @ViewDebug.ExportedProperty(category = "drawing")
   15920     @InspectableProperty
   15921     public float getScaleY() {
   15922         return mRenderNode.getScaleY();
   15923     }
   15924 
   15925     /**
   15926      * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
   15927      * the view's unscaled width. A value of 1 means that no scaling is applied.
   15928      *
   15929      * @param scaleY The scaling factor.
   15930      * @see #getPivotX()
   15931      * @see #getPivotY()
   15932      *
   15933      * @attr ref android.R.styleable#View_scaleY
   15934      */
   15935     public void setScaleY(float scaleY) {
   15936         if (scaleY != getScaleY()) {
   15937             scaleY = sanitizeFloatPropertyValue(scaleY, "scaleY");
   15938             invalidateViewProperty(true, false);
   15939             mRenderNode.setScaleY(scaleY);
   15940             invalidateViewProperty(false, true);
   15941 
   15942             invalidateParentIfNeededAndWasQuickRejected();
   15943             notifySubtreeAccessibilityStateChangedIfNeeded();
   15944         }
   15945     }
   15946 
   15947     /**
   15948      * The x location of the point around which the view is {@link #setRotation(float) rotated}
   15949      * and {@link #setScaleX(float) scaled}.
   15950      *
   15951      * @see #getRotation()
   15952      * @see #getScaleX()
   15953      * @see #getScaleY()
   15954      * @see #getPivotY()
   15955      * @return The x location of the pivot point.
   15956      *
   15957      * @attr ref android.R.styleable#View_transformPivotX
   15958      */
   15959     @ViewDebug.ExportedProperty(category = "drawing")
   15960     @InspectableProperty(name = "transformPivotX")
   15961     public float getPivotX() {
   15962         return mRenderNode.getPivotX();
   15963     }
   15964 
   15965     /**
   15966      * Sets the x location of the point around which the view is
   15967      * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
   15968      * By default, the pivot point is centered on the object.
   15969      * Setting this property disables this behavior and causes the view to use only the
   15970      * explicitly set pivotX and pivotY values.
   15971      *
   15972      * @param pivotX The x location of the pivot point.
   15973      * @see #getRotation()
   15974      * @see #getScaleX()
   15975      * @see #getScaleY()
   15976      * @see #getPivotY()
   15977      *
   15978      * @attr ref android.R.styleable#View_transformPivotX
   15979      */
   15980     public void setPivotX(float pivotX) {
   15981         if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
   15982             invalidateViewProperty(true, false);
   15983             mRenderNode.setPivotX(pivotX);
   15984             invalidateViewProperty(false, true);
   15985 
   15986             invalidateParentIfNeededAndWasQuickRejected();
   15987         }
   15988     }
   15989 
   15990     /**
   15991      * The y location of the point around which the view is {@link #setRotation(float) rotated}
   15992      * and {@link #setScaleY(float) scaled}.
   15993      *
   15994      * @see #getRotation()
   15995      * @see #getScaleX()
   15996      * @see #getScaleY()
   15997      * @see #getPivotY()
   15998      * @return The y location of the pivot point.
   15999      *
   16000      * @attr ref android.R.styleable#View_transformPivotY
   16001      */
   16002     @ViewDebug.ExportedProperty(category = "drawing")
   16003     @InspectableProperty(name = "transformPivotY")
   16004     public float getPivotY() {
   16005         return mRenderNode.getPivotY();
   16006     }
   16007 
   16008     /**
   16009      * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
   16010      * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
   16011      * Setting this property disables this behavior and causes the view to use only the
   16012      * explicitly set pivotX and pivotY values.
   16013      *
   16014      * @param pivotY The y location of the pivot point.
   16015      * @see #getRotation()
   16016      * @see #getScaleX()
   16017      * @see #getScaleY()
   16018      * @see #getPivotY()
   16019      *
   16020      * @attr ref android.R.styleable#View_transformPivotY
   16021      */
   16022     public void setPivotY(float pivotY) {
   16023         if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
   16024             invalidateViewProperty(true, false);
   16025             mRenderNode.setPivotY(pivotY);
   16026             invalidateViewProperty(false, true);
   16027 
   16028             invalidateParentIfNeededAndWasQuickRejected();
   16029         }
   16030     }
   16031 
   16032     /**
   16033      * Returns whether or not a pivot has been set by a call to {@link #setPivotX(float)} or
   16034      * {@link #setPivotY(float)}. If no pivot has been set then the pivot will be the center
   16035      * of the view.
   16036      *
   16037      * @return True if a pivot has been set, false if the default pivot is being used
   16038      */
   16039     public boolean isPivotSet() {
   16040         return mRenderNode.isPivotExplicitlySet();
   16041     }
   16042 
   16043     /**
   16044      * Clears any pivot previously set by a call to  {@link #setPivotX(float)} or
   16045      * {@link #setPivotY(float)}. After calling this {@link #isPivotSet()} will be false
   16046      * and the pivot used for rotation will return to default of being centered on the view.
   16047      */
   16048     public void resetPivot() {
   16049         if (mRenderNode.resetPivot()) {
   16050             invalidateViewProperty(false, false);
   16051         }
   16052     }
   16053 
   16054     /**
   16055      * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
   16056      * completely transparent and 1 means the view is completely opaque.
   16057      *
   16058      * <p>By default this is 1.0f.
   16059      * @return The opacity of the view.
   16060      */
   16061     @ViewDebug.ExportedProperty(category = "drawing")
   16062     @InspectableProperty
   16063     public float getAlpha() {
   16064         return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
   16065     }
   16066 
   16067     /**
   16068      * Sets the behavior for overlapping rendering for this view (see {@link
   16069      * #hasOverlappingRendering()} for more details on this behavior). Calling this method
   16070      * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
   16071      * providing the value which is then used internally. That is, when {@link
   16072      * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
   16073      * #hasOverlappingRendering()} is ignored and the value passed into this method is used
   16074      * instead.
   16075      *
   16076      * @param hasOverlappingRendering The value for overlapping rendering to be used internally
   16077      * instead of that returned by {@link #hasOverlappingRendering()}.
   16078      *
   16079      * @attr ref android.R.styleable#View_forceHasOverlappingRendering
   16080      */
   16081     public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
   16082         mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
   16083         if (hasOverlappingRendering) {
   16084             mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
   16085         } else {
   16086             mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
   16087         }
   16088     }
   16089 
   16090     /**
   16091      * Returns the value for overlapping rendering that is used internally. This is either
   16092      * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
   16093      * the return value of {@link #hasOverlappingRendering()}, otherwise.
   16094      *
   16095      * @return The value for overlapping rendering being used internally.
   16096      */
   16097     public final boolean getHasOverlappingRendering() {
   16098         return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
   16099                 (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
   16100                 hasOverlappingRendering();
   16101     }
   16102 
   16103     /**
   16104      * Returns whether this View has content which overlaps.
   16105      *
   16106      * <p>This function, intended to be overridden by specific View types, is an optimization when
   16107      * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
   16108      * an offscreen buffer and then composited into place, which can be expensive. If the view has
   16109      * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
   16110      * directly. An example of overlapping rendering is a TextView with a background image, such as
   16111      * a Button. An example of non-overlapping rendering is a TextView with no background, or an
   16112      * ImageView with only the foreground image. The default implementation returns true; subclasses
   16113      * should override if they have cases which can be optimized.</p>
   16114      *
   16115      * <p><strong>Note:</strong> The return value of this method is ignored if {@link
   16116      * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
   16117      *
   16118      * @return true if the content in this view might overlap, false otherwise.
   16119      */
   16120     @ViewDebug.ExportedProperty(category = "drawing")
   16121     public boolean hasOverlappingRendering() {
   16122         return true;
   16123     }
   16124 
   16125     /**
   16126      * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
   16127      * completely transparent and 1 means the view is completely opaque.
   16128      *
   16129      * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
   16130      * can have significant performance implications, especially for large views. It is best to use
   16131      * the alpha property sparingly and transiently, as in the case of fading animations.</p>
   16132      *
   16133      * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
   16134      * strongly recommended for performance reasons to either override
   16135      * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
   16136      * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
   16137      * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
   16138      * the default path for rendering an unlayered View with alpha could add multiple milliseconds
   16139      * of rendering cost, even for simple or small views. Starting with
   16140      * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
   16141      * applied to the view at the rendering level.</p>
   16142      *
   16143      * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
   16144      * responsible for applying the opacity itself.</p>
   16145      *
   16146      * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
   16147      * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
   16148      * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
   16149      * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
   16150      *
   16151      * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
   16152      * value will clip a View to its bounds, unless the View returns <code>false</code> from
   16153      * {@link #hasOverlappingRendering}.</p>
   16154      *
   16155      * @param alpha The opacity of the view.
   16156      *
   16157      * @see #hasOverlappingRendering()
   16158      * @see #setLayerType(int, android.graphics.Paint)
   16159      *
   16160      * @attr ref android.R.styleable#View_alpha
   16161      */
   16162     public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
   16163         ensureTransformationInfo();
   16164         if (mTransformationInfo.mAlpha != alpha) {
   16165             setAlphaInternal(alpha);
   16166             if (onSetAlpha((int) (alpha * 255))) {
   16167                 mPrivateFlags |= PFLAG_ALPHA_SET;
   16168                 // subclass is handling alpha - don't optimize rendering cache invalidation
   16169                 invalidateParentCaches();
   16170                 invalidate(true);
   16171             } else {
   16172                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
   16173                 invalidateViewProperty(true, false);
   16174                 mRenderNode.setAlpha(getFinalAlpha());
   16175             }
   16176         }
   16177     }
   16178 
   16179     /**
   16180      * Faster version of setAlpha() which performs the same steps except there are
   16181      * no calls to invalidate(). The caller of this function should perform proper invalidation
   16182      * on the parent and this object. The return value indicates whether the subclass handles
   16183      * alpha (the return value for onSetAlpha()).
   16184      *
   16185      * @param alpha The new value for the alpha property
   16186      * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
   16187      *         the new value for the alpha property is different from the old value
   16188      */
   16189     @UnsupportedAppUsage(maxTargetSdk  = Build.VERSION_CODES.P, trackingBug = 123768435)
   16190     boolean setAlphaNoInvalidation(float alpha) {
   16191         ensureTransformationInfo();
   16192         if (mTransformationInfo.mAlpha != alpha) {
   16193             setAlphaInternal(alpha);
   16194             boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
   16195             if (subclassHandlesAlpha) {
   16196                 mPrivateFlags |= PFLAG_ALPHA_SET;
   16197                 return true;
   16198             } else {
   16199                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
   16200                 mRenderNode.setAlpha(getFinalAlpha());
   16201             }
   16202         }
   16203         return false;
   16204     }
   16205 
   16206     void setAlphaInternal(float alpha) {
   16207         float oldAlpha = mTransformationInfo.mAlpha;
   16208         mTransformationInfo.mAlpha = alpha;
   16209         // Report visibility changes, which can affect children, to accessibility
   16210         if ((alpha == 0) ^ (oldAlpha == 0)) {
   16211             notifySubtreeAccessibilityStateChangedIfNeeded();
   16212         }
   16213     }
   16214 
   16215     /**
   16216      * This property is intended only for use by the Fade transition, which animates it
   16217      * to produce a visual translucency that does not side-effect (or get affected by)
   16218      * the real alpha property. This value is composited with the other alpha value
   16219      * (and the AlphaAnimation value, when that is present) to produce a final visual
   16220      * translucency result, which is what is passed into the DisplayList.
   16221      */
   16222     public void setTransitionAlpha(float alpha) {
   16223         ensureTransformationInfo();
   16224         if (mTransformationInfo.mTransitionAlpha != alpha) {
   16225             mTransformationInfo.mTransitionAlpha = alpha;
   16226             mPrivateFlags &= ~PFLAG_ALPHA_SET;
   16227             invalidateViewProperty(true, false);
   16228             mRenderNode.setAlpha(getFinalAlpha());
   16229         }
   16230     }
   16231 
   16232     /**
   16233      * Calculates the visual alpha of this view, which is a combination of the actual
   16234      * alpha value and the transitionAlpha value (if set).
   16235      */
   16236     private float getFinalAlpha() {
   16237         if (mTransformationInfo != null) {
   16238             return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
   16239         }
   16240         return 1;
   16241     }
   16242 
   16243     /**
   16244      * This property is intended only for use by the Fade transition, which animates
   16245      * it to produce a visual translucency that does not side-effect (or get affected
   16246      * by) the real alpha property. This value is composited with the other alpha
   16247      * value (and the AlphaAnimation value, when that is present) to produce a final
   16248      * visual translucency result, which is what is passed into the DisplayList.
   16249      */
   16250     @ViewDebug.ExportedProperty(category = "drawing")
   16251     public float getTransitionAlpha() {
   16252         return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
   16253     }
   16254 
   16255     /**
   16256      * Sets whether or not to allow force dark to apply to this view.
   16257      *
   16258      * Setting this to false will disable the auto-dark feature on everything this view
   16259      * draws, including any descendants.
   16260      *
   16261      * Setting this to true will allow this view to be automatically made dark, however
   16262      * a value of 'true' will not override any 'false' value in its parent chain nor will
   16263      * it prevent any 'false' in any of its children.
   16264      *
   16265      * The default behavior of force dark is also influenced by the Theme's
   16266      * {@link android.R.styleable#Theme_isLightTheme isLightTheme} attribute.
   16267      * If a theme is isLightTheme="false", then force dark is globally disabled for that theme.
   16268      *
   16269      * @param allow Whether or not to allow force dark.
   16270      */
   16271     public void setForceDarkAllowed(boolean allow) {
   16272         if (mRenderNode.setForceDarkAllowed(allow)) {
   16273             // Currently toggling force-dark requires a new display list push to apply
   16274             // TODO: Make it not clobber the display list so this is just a damageSelf() instead
   16275             invalidate();
   16276         }
   16277     }
   16278 
   16279     /**
   16280      * See {@link #setForceDarkAllowed(boolean)}
   16281      *
   16282      * @return true if force dark is allowed (default), false if it is disabled
   16283      */
   16284     @ViewDebug.ExportedProperty(category = "drawing")
   16285     @InspectableProperty
   16286     public boolean isForceDarkAllowed() {
   16287         return mRenderNode.isForceDarkAllowed();
   16288     }
   16289 
   16290     /**
   16291      * Top position of this view relative to its parent.
   16292      *
   16293      * @return The top of this view, in pixels.
   16294      */
   16295     @ViewDebug.CapturedViewProperty
   16296     public final int getTop() {
   16297         return mTop;
   16298     }
   16299 
   16300     /**
   16301      * Sets the top position of this view relative to its parent. This method is meant to be called
   16302      * by the layout system and should not generally be called otherwise, because the property
   16303      * may be changed at any time by the layout.
   16304      *
   16305      * @param top The top of this view, in pixels.
   16306      */
   16307     public final void setTop(int top) {
   16308         if (top != mTop) {
   16309             final boolean matrixIsIdentity = hasIdentityMatrix();
   16310             if (matrixIsIdentity) {
   16311                 if (mAttachInfo != null) {
   16312                     int minTop;
   16313                     int yLoc;
   16314                     if (top < mTop) {
   16315                         minTop = top;
   16316                         yLoc = top - mTop;
   16317                     } else {
   16318                         minTop = mTop;
   16319                         yLoc = 0;
   16320                     }
   16321                     invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
   16322                 }
   16323             } else {
   16324                 // Double-invalidation is necessary to capture view's old and new areas
   16325                 invalidate(true);
   16326             }
   16327 
   16328             int width = mRight - mLeft;
   16329             int oldHeight = mBottom - mTop;
   16330 
   16331             mTop = top;
   16332             mRenderNode.setTop(mTop);
   16333 
   16334             sizeChange(width, mBottom - mTop, width, oldHeight);
   16335 
   16336             if (!matrixIsIdentity) {
   16337                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
   16338                 invalidate(true);
   16339             }
   16340             mBackgroundSizeChanged = true;
   16341             mDefaultFocusHighlightSizeChanged = true;
   16342             if (mForegroundInfo != null) {
   16343                 mForegroundInfo.mBoundsChanged = true;
   16344             }
   16345             invalidateParentIfNeeded();
   16346             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
   16347                 // View was rejected last time it was drawn by its parent; this may have changed
   16348                 invalidateParentIfNeeded();
   16349             }
   16350         }
   16351     }
   16352 
   16353     /**
   16354      * Bottom position of this view relative to its parent.
   16355      *
   16356      * @return The bottom of this view, in pixels.
   16357      */
   16358     @ViewDebug.CapturedViewProperty
   16359     public final int getBottom() {
   16360         return mBottom;
   16361     }
   16362 
   16363     /**
   16364      * True if this view has changed since the last time being drawn.
   16365      *
   16366      * @return The dirty state of this view.
   16367      */
   16368     public boolean isDirty() {
   16369         return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
   16370     }
   16371 
   16372     /**
   16373      * Sets the bottom position of this view relative to its parent. This method is meant to be
   16374      * called by the layout system and should not generally be called otherwise, because the
   16375      * property may be changed at any time by the layout.
   16376      *
   16377      * @param bottom The bottom of this view, in pixels.
   16378      */
   16379     public final void setBottom(int bottom) {
   16380         if (bottom != mBottom) {
   16381             final boolean matrixIsIdentity = hasIdentityMatrix();
   16382             if (matrixIsIdentity) {
   16383                 if (mAttachInfo != null) {
   16384                     int maxBottom;
   16385                     if (bottom < mBottom) {
   16386                         maxBottom = mBottom;
   16387                     } else {
   16388                         maxBottom = bottom;
   16389                     }
   16390                     invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
   16391                 }
   16392             } else {
   16393                 // Double-invalidation is necessary to capture view's old and new areas
   16394                 invalidate(true);
   16395             }
   16396 
   16397             int width = mRight - mLeft;
   16398             int oldHeight = mBottom - mTop;
   16399 
   16400             mBottom = bottom;
   16401             mRenderNode.setBottom(mBottom);
   16402 
   16403             sizeChange(width, mBottom - mTop, width, oldHeight);
   16404 
   16405             if (!matrixIsIdentity) {
   16406                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
   16407                 invalidate(true);
   16408             }
   16409             mBackgroundSizeChanged = true;
   16410             mDefaultFocusHighlightSizeChanged = true;
   16411             if (mForegroundInfo != null) {
   16412                 mForegroundInfo.mBoundsChanged = true;
   16413             }
   16414             invalidateParentIfNeeded();
   16415             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
   16416                 // View was rejected last time it was drawn by its parent; this may have changed
   16417                 invalidateParentIfNeeded();
   16418             }
   16419         }
   16420     }
   16421 
   16422     /**
   16423      * Left position of this view relative to its parent.
   16424      *
   16425      * @return The left edge of this view, in pixels.
   16426      */
   16427     @ViewDebug.CapturedViewProperty
   16428     public final int getLeft() {
   16429         return mLeft;
   16430     }
   16431 
   16432     /**
   16433      * Sets the left position of this view relative to its parent. This method is meant to be called
   16434      * by the layout system and should not generally be called otherwise, because the property
   16435      * may be changed at any time by the layout.
   16436      *
   16437      * @param left The left of this view, in pixels.
   16438      */
   16439     public final void setLeft(int left) {
   16440         if (left != mLeft) {
   16441             final boolean matrixIsIdentity = hasIdentityMatrix();
   16442             if (matrixIsIdentity) {
   16443                 if (mAttachInfo != null) {
   16444                     int minLeft;
   16445                     int xLoc;
   16446                     if (left < mLeft) {
   16447                         minLeft = left;
   16448                         xLoc = left - mLeft;
   16449                     } else {
   16450                         minLeft = mLeft;
   16451                         xLoc = 0;
   16452                     }
   16453                     invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
   16454                 }
   16455             } else {
   16456                 // Double-invalidation is necessary to capture view's old and new areas
   16457                 invalidate(true);
   16458             }
   16459 
   16460             int oldWidth = mRight - mLeft;
   16461             int height = mBottom - mTop;
   16462 
   16463             mLeft = left;
   16464             mRenderNode.setLeft(left);
   16465 
   16466             sizeChange(mRight - mLeft, height, oldWidth, height);
   16467 
   16468             if (!matrixIsIdentity) {
   16469                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
   16470                 invalidate(true);
   16471             }
   16472             mBackgroundSizeChanged = true;
   16473             mDefaultFocusHighlightSizeChanged = true;
   16474             if (mForegroundInfo != null) {
   16475                 mForegroundInfo.mBoundsChanged = true;
   16476             }
   16477             invalidateParentIfNeeded();
   16478             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
   16479                 // View was rejected last time it was drawn by its parent; this may have changed
   16480                 invalidateParentIfNeeded();
   16481             }
   16482         }
   16483     }
   16484 
   16485     /**
   16486      * Right position of this view relative to its parent.
   16487      *
   16488      * @return The right edge of this view, in pixels.
   16489      */
   16490     @ViewDebug.CapturedViewProperty
   16491     public final int getRight() {
   16492         return mRight;
   16493     }
   16494 
   16495     /**
   16496      * Sets the right position of this view relative to its parent. This method is meant to be called
   16497      * by the layout system and should not generally be called otherwise, because the property
   16498      * may be changed at any time by the layout.
   16499      *
   16500      * @param right The right of this view, in pixels.
   16501      */
   16502     public final void setRight(int right) {
   16503         if (right != mRight) {
   16504             final boolean matrixIsIdentity = hasIdentityMatrix();
   16505             if (matrixIsIdentity) {
   16506                 if (mAttachInfo != null) {
   16507                     int maxRight;
   16508                     if (right < mRight) {
   16509                         maxRight = mRight;
   16510                     } else {
   16511                         maxRight = right;
   16512                     }
   16513                     invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
   16514                 }
   16515             } else {
   16516                 // Double-invalidation is necessary to capture view's old and new areas
   16517                 invalidate(true);
   16518             }
   16519 
   16520             int oldWidth = mRight - mLeft;
   16521             int height = mBottom - mTop;
   16522 
   16523             mRight = right;
   16524             mRenderNode.setRight(mRight);
   16525 
   16526             sizeChange(mRight - mLeft, height, oldWidth, height);
   16527 
   16528             if (!matrixIsIdentity) {
   16529                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
   16530                 invalidate(true);
   16531             }
   16532             mBackgroundSizeChanged = true;
   16533             mDefaultFocusHighlightSizeChanged = true;
   16534             if (mForegroundInfo != null) {
   16535                 mForegroundInfo.mBoundsChanged = true;
   16536             }
   16537             invalidateParentIfNeeded();
   16538             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
   16539                 // View was rejected last time it was drawn by its parent; this may have changed
   16540                 invalidateParentIfNeeded();
   16541             }
   16542         }
   16543     }
   16544 
   16545     private static float sanitizeFloatPropertyValue(float value, String propertyName) {
   16546         return sanitizeFloatPropertyValue(value, propertyName, -Float.MAX_VALUE, Float.MAX_VALUE);
   16547     }
   16548 
   16549     private static float sanitizeFloatPropertyValue(float value, String propertyName,
   16550             float min, float max) {
   16551         // The expected "nothing bad happened" path
   16552         if (value >= min && value <= max) return value;
   16553 
   16554         if (value < min || value == Float.NEGATIVE_INFINITY) {
   16555             if (sThrowOnInvalidFloatProperties) {
   16556                 throw new IllegalArgumentException("Cannot set '" + propertyName + "' to "
   16557                         + value + ", the value must be >= " + min);
   16558             }
   16559             return min;
   16560         }
   16561 
   16562         if (value > max || value == Float.POSITIVE_INFINITY) {
   16563             if (sThrowOnInvalidFloatProperties) {
   16564                 throw new IllegalArgumentException("Cannot set '" + propertyName + "' to "
   16565                         + value + ", the value must be <= " + max);
   16566             }
   16567             return max;
   16568         }
   16569 
   16570         if (Float.isNaN(value)) {
   16571             if (sThrowOnInvalidFloatProperties) {
   16572                 throw new IllegalArgumentException(
   16573                         "Cannot set '" + propertyName + "' to Float.NaN");
   16574             }
   16575             return 0; // Unclear which direction this NaN went so... 0?
   16576         }
   16577 
   16578         // Shouldn't be possible to reach this.
   16579         throw new IllegalStateException("How do you get here?? " + value);
   16580     }
   16581 
   16582     /**
   16583      * The visual x position of this view, in pixels. This is equivalent to the
   16584      * {@link #setTranslationX(float) translationX} property plus the current
   16585      * {@link #getLeft() left} property.
   16586      *
   16587      * @return The visual x position of this view, in pixels.
   16588      */
   16589     @ViewDebug.ExportedProperty(category = "drawing")
   16590     public float getX() {
   16591         return mLeft + getTranslationX();
   16592     }
   16593 
   16594     /**
   16595      * Sets the visual x position of this view, in pixels. This is equivalent to setting the
   16596      * {@link #setTranslationX(float) translationX} property to be the difference between
   16597      * the x value passed in and the current {@link #getLeft() left} property.
   16598      *
   16599      * @param x The visual x position of this view, in pixels.
   16600      */
   16601     public void setX(float x) {
   16602         setTranslationX(x - mLeft);
   16603     }
   16604 
   16605     /**
   16606      * The visual y position of this view, in pixels. This is equivalent to the
   16607      * {@link #setTranslationY(float) translationY} property plus the current
   16608      * {@link #getTop() top} property.
   16609      *
   16610      * @return The visual y position of this view, in pixels.
   16611      */
   16612     @ViewDebug.ExportedProperty(category = "drawing")
   16613     public float getY() {
   16614         return mTop + getTranslationY();
   16615     }
   16616 
   16617     /**
   16618      * Sets the visual y position of this view, in pixels. This is equivalent to setting the
   16619      * {@link #setTranslationY(float) translationY} property to be the difference between
   16620      * the y value passed in and the current {@link #getTop() top} property.
   16621      *
   16622      * @param y The visual y position of this view, in pixels.
   16623      */
   16624     public void setY(float y) {
   16625         setTranslationY(y - mTop);
   16626     }
   16627 
   16628     /**
   16629      * The visual z position of this view, in pixels. This is equivalent to the
   16630      * {@link #setTranslationZ(float) translationZ} property plus the current
   16631      * {@link #getElevation() elevation} property.
   16632      *
   16633      * @return The visual z position of this view, in pixels.
   16634      */
   16635     @ViewDebug.ExportedProperty(category = "drawing")
   16636     public float getZ() {
   16637         return getElevation() + getTranslationZ();
   16638     }
   16639 
   16640     /**
   16641      * Sets the visual z position of this view, in pixels. This is equivalent to setting the
   16642      * {@link #setTranslationZ(float) translationZ} property to be the difference between
   16643      * the z value passed in and the current {@link #getElevation() elevation} property.
   16644      *
   16645      * @param z The visual z position of this view, in pixels.
   16646      */
   16647     public void setZ(float z) {
   16648         setTranslationZ(z - getElevation());
   16649     }
   16650 
   16651     /**
   16652      * The base elevation of this view relative to its parent, in pixels.
   16653      *
   16654      * @return The base depth position of the view, in pixels.
   16655      */
   16656     @ViewDebug.ExportedProperty(category = "drawing")
   16657     @InspectableProperty
   16658     public float getElevation() {
   16659         return mRenderNode.getElevation();
   16660     }
   16661 
   16662     /**
   16663      * Sets the base elevation of this view, in pixels.
   16664      *
   16665      * @attr ref android.R.styleable#View_elevation
   16666      */
   16667     public void setElevation(float elevation) {
   16668         if (elevation != getElevation()) {
   16669             elevation = sanitizeFloatPropertyValue(elevation, "elevation");
   16670             invalidateViewProperty(true, false);
   16671             mRenderNode.setElevation(elevation);
   16672             invalidateViewProperty(false, true);
   16673 
   16674             invalidateParentIfNeededAndWasQuickRejected();
   16675         }
   16676     }
   16677 
   16678     /**
   16679      * The horizontal location of this view relative to its {@link #getLeft() left} position.
   16680      * This position is post-layout, in addition to wherever the object's
   16681      * layout placed it.
   16682      *
   16683      * @return The horizontal position of this view relative to its left position, in pixels.
   16684      */
   16685     @ViewDebug.ExportedProperty(category = "drawing")
   16686     @InspectableProperty
   16687     public float getTranslationX() {
   16688         return mRenderNode.getTranslationX();
   16689     }
   16690 
   16691     /**
   16692      * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
   16693      * This effectively positions the object post-layout, in addition to wherever the object's
   16694      * layout placed it.
   16695      *
   16696      * @param translationX The horizontal position of this view relative to its left position,
   16697      * in pixels.
   16698      *
   16699      * @attr ref android.R.styleable#View_translationX
   16700      */
   16701     public void setTranslationX(float translationX) {
   16702         if (translationX != getTranslationX()) {
   16703             invalidateViewProperty(true, false);
   16704             mRenderNode.setTranslationX(translationX);
   16705             invalidateViewProperty(false, true);
   16706 
   16707             invalidateParentIfNeededAndWasQuickRejected();
   16708             notifySubtreeAccessibilityStateChangedIfNeeded();
   16709         }
   16710     }
   16711 
   16712     /**
   16713      * The vertical location of this view relative to its {@link #getTop() top} position.
   16714      * This position is post-layout, in addition to wherever the object's
   16715      * layout placed it.
   16716      *
   16717      * @return The vertical position of this view relative to its top position,
   16718      * in pixels.
   16719      */
   16720     @ViewDebug.ExportedProperty(category = "drawing")
   16721     @InspectableProperty
   16722     public float getTranslationY() {
   16723         return mRenderNode.getTranslationY();
   16724     }
   16725 
   16726     /**
   16727      * Sets the vertical location of this view relative to its {@link #getTop() top} position.
   16728      * This effectively positions the object post-layout, in addition to wherever the object's
   16729      * layout placed it.
   16730      *
   16731      * @param translationY The vertical position of this view relative to its top position,
   16732      * in pixels.
   16733      *
   16734      * @attr ref android.R.styleable#View_translationY
   16735      */
   16736     public void setTranslationY(float translationY) {
   16737         if (translationY != getTranslationY()) {
   16738             invalidateViewProperty(true, false);
   16739             mRenderNode.setTranslationY(translationY);
   16740             invalidateViewProperty(false, true);
   16741 
   16742             invalidateParentIfNeededAndWasQuickRejected();
   16743             notifySubtreeAccessibilityStateChangedIfNeeded();
   16744         }
   16745     }
   16746 
   16747     /**
   16748      * The depth location of this view relative to its {@link #getElevation() elevation}.
   16749      *
   16750      * @return The depth of this view relative to its elevation.
   16751      */
   16752     @ViewDebug.ExportedProperty(category = "drawing")
   16753     @InspectableProperty
   16754     public float getTranslationZ() {
   16755         return mRenderNode.getTranslationZ();
   16756     }
   16757 
   16758     /**
   16759      * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
   16760      *
   16761      * @attr ref android.R.styleable#View_translationZ
   16762      */
   16763     public void setTranslationZ(float translationZ) {
   16764         if (translationZ != getTranslationZ()) {
   16765             translationZ = sanitizeFloatPropertyValue(translationZ, "translationZ");
   16766             invalidateViewProperty(true, false);
   16767             mRenderNode.setTranslationZ(translationZ);
   16768             invalidateViewProperty(false, true);
   16769 
   16770             invalidateParentIfNeededAndWasQuickRejected();
   16771         }
   16772     }
   16773 
   16774     /**
   16775      * Changes the transformation matrix on the view. This is used in animation frameworks,
   16776      * such as {@link android.transition.Transition}. When the animation finishes, the matrix
   16777      * should be cleared by calling this method with <code>null</code> as the matrix parameter.
   16778      * Application developers should use transformation methods like {@link #setRotation(float)},
   16779      * {@link #setScaleX(float)}, {@link #setScaleX(float)}, {@link #setTranslationX(float)}}
   16780      * and {@link #setTranslationY(float)} (float)}} instead.
   16781      *
   16782      * @param matrix The matrix, null indicates that the matrix should be cleared.
   16783      * @see #getAnimationMatrix()
   16784      */
   16785     public void setAnimationMatrix(@Nullable Matrix matrix) {
   16786         invalidateViewProperty(true, false);
   16787         mRenderNode.setAnimationMatrix(matrix);
   16788         invalidateViewProperty(false, true);
   16789 
   16790         invalidateParentIfNeededAndWasQuickRejected();
   16791     }
   16792 
   16793     /**
   16794      * Return the current transformation matrix of the view. This is used in animation frameworks,
   16795      * such as {@link android.transition.Transition}. Returns <code>null</code> when there is no
   16796      * transformation provided by {@link #setAnimationMatrix(Matrix)}.
   16797      * Application developers should use transformation methods like {@link #setRotation(float)},
   16798      * {@link #setScaleX(float)}, {@link #setScaleX(float)}, {@link #setTranslationX(float)}}
   16799      * and {@link #setTranslationY(float)} (float)}} instead.
   16800      *
   16801      * @return the Matrix, null indicates there is no transformation
   16802      * @see #setAnimationMatrix(Matrix)
   16803      */
   16804     @Nullable
   16805     public Matrix getAnimationMatrix() {
   16806         return mRenderNode.getAnimationMatrix();
   16807     }
   16808 
   16809     /**
   16810      * Returns the current StateListAnimator if exists.
   16811      *
   16812      * @return StateListAnimator or null if it does not exists
   16813      * @see    #setStateListAnimator(android.animation.StateListAnimator)
   16814      */
   16815     @InspectableProperty
   16816     public StateListAnimator getStateListAnimator() {
   16817         return mStateListAnimator;
   16818     }
   16819 
   16820     /**
   16821      * Attaches the provided StateListAnimator to this View.
   16822      * <p>
   16823      * Any previously attached StateListAnimator will be detached.
   16824      *
   16825      * @param stateListAnimator The StateListAnimator to update the view
   16826      * @see android.animation.StateListAnimator
   16827      */
   16828     public void setStateListAnimator(StateListAnimator stateListAnimator) {
   16829         if (mStateListAnimator == stateListAnimator) {
   16830             return;
   16831         }
   16832         if (mStateListAnimator != null) {
   16833             mStateListAnimator.setTarget(null);
   16834         }
   16835         mStateListAnimator = stateListAnimator;
   16836         if (stateListAnimator != null) {
   16837             stateListAnimator.setTarget(this);
   16838             if (isAttachedToWindow()) {
   16839                 stateListAnimator.setState(getDrawableState());
   16840             }
   16841         }
   16842     }
   16843 
   16844     /**
   16845      * Returns whether the Outline should be used to clip the contents of the View.
   16846      * <p>
   16847      * Note that this flag will only be respected if the View's Outline returns true from
   16848      * {@link Outline#canClip()}.
   16849      *
   16850      * @see #setOutlineProvider(ViewOutlineProvider)
   16851      * @see #setClipToOutline(boolean)
   16852      */
   16853     public final boolean getClipToOutline() {
   16854         return mRenderNode.getClipToOutline();
   16855     }
   16856 
   16857     /**
   16858      * Sets whether the View's Outline should be used to clip the contents of the View.
   16859      * <p>
   16860      * Only a single non-rectangular clip can be applied on a View at any time.
   16861      * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
   16862      * circular reveal} animation take priority over Outline clipping, and
   16863      * child Outline clipping takes priority over Outline clipping done by a
   16864      * parent.
   16865      * <p>
   16866      * Note that this flag will only be respected if the View's Outline returns true from
   16867      * {@link Outline#canClip()}.
   16868      *
   16869      * @see #setOutlineProvider(ViewOutlineProvider)
   16870      * @see #getClipToOutline()
   16871      */
   16872     public void setClipToOutline(boolean clipToOutline) {
   16873         damageInParent();
   16874         if (getClipToOutline() != clipToOutline) {
   16875             mRenderNode.setClipToOutline(clipToOutline);
   16876         }
   16877     }
   16878 
   16879     // correspond to the enum values of View_outlineProvider
   16880     private static final int PROVIDER_BACKGROUND = 0;
   16881     private static final int PROVIDER_NONE = 1;
   16882     private static final int PROVIDER_BOUNDS = 2;
   16883     private static final int PROVIDER_PADDED_BOUNDS = 3;
   16884     private void setOutlineProviderFromAttribute(int providerInt) {
   16885         switch (providerInt) {
   16886             case PROVIDER_BACKGROUND:
   16887                 setOutlineProvider(ViewOutlineProvider.BACKGROUND);
   16888                 break;
   16889             case PROVIDER_NONE:
   16890                 setOutlineProvider(null);
   16891                 break;
   16892             case PROVIDER_BOUNDS:
   16893                 setOutlineProvider(ViewOutlineProvider.BOUNDS);
   16894                 break;
   16895             case PROVIDER_PADDED_BOUNDS:
   16896                 setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
   16897                 break;
   16898         }
   16899     }
   16900 
   16901     /**
   16902      * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
   16903      * the shape of the shadow it casts, and enables outline clipping.
   16904      * <p>
   16905      * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
   16906      * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
   16907      * outline provider with this method allows this behavior to be overridden.
   16908      * <p>
   16909      * If the ViewOutlineProvider is null, if querying it for an outline returns false,
   16910      * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
   16911      * <p>
   16912      * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
   16913      *
   16914      * @see #setClipToOutline(boolean)
   16915      * @see #getClipToOutline()
   16916      * @see #getOutlineProvider()
   16917      */
   16918     public void setOutlineProvider(ViewOutlineProvider provider) {
   16919         mOutlineProvider = provider;
   16920         invalidateOutline();
   16921     }
   16922 
   16923     /**
   16924      * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
   16925      * that defines the shape of the shadow it casts, and enables outline clipping.
   16926      *
   16927      * @see #setOutlineProvider(ViewOutlineProvider)
   16928      */
   16929     @InspectableProperty
   16930     public ViewOutlineProvider getOutlineProvider() {
   16931         return mOutlineProvider;
   16932     }
   16933 
   16934     /**
   16935      * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
   16936      *
   16937      * @see #setOutlineProvider(ViewOutlineProvider)
   16938      */
   16939     public void invalidateOutline() {
   16940         rebuildOutline();
   16941 
   16942         notifySubtreeAccessibilityStateChangedIfNeeded();
   16943         invalidateViewProperty(false, false);
   16944     }
   16945 
   16946     /**
   16947      * Internal version of {@link #invalidateOutline()} which invalidates the
   16948      * outline without invalidating the view itself. This is intended to be called from
   16949      * within methods in the View class itself which are the result of the view being
   16950      * invalidated already. For example, when we are drawing the background of a View,
   16951      * we invalidate the outline in case it changed in the meantime, but we do not
   16952      * need to invalidate the view because we're already drawing the background as part
   16953      * of drawing the view in response to an earlier invalidation of the view.
   16954      */
   16955     private void rebuildOutline() {
   16956         // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
   16957         if (mAttachInfo == null) return;
   16958 
   16959         if (mOutlineProvider == null) {
   16960             // no provider, remove outline
   16961             mRenderNode.setOutline(null);
   16962         } else {
   16963             final Outline outline = mAttachInfo.mTmpOutline;
   16964             outline.setEmpty();
   16965             outline.setAlpha(1.0f);
   16966 
   16967             mOutlineProvider.getOutline(this, outline);
   16968             mRenderNode.setOutline(outline);
   16969         }
   16970     }
   16971 
   16972     /**
   16973      * HierarchyViewer only
   16974      *
   16975      * @hide
   16976      */
   16977     @ViewDebug.ExportedProperty(category = "drawing")
   16978     public boolean hasShadow() {
   16979         return mRenderNode.hasShadow();
   16980     }
   16981 
   16982     /**
   16983      * Sets the color of the spot shadow that is drawn when the view has a positive Z or
   16984      * elevation value.
   16985      * <p>
   16986      * By default the shadow color is black. Generally, this color will be opaque so the intensity
   16987      * of the shadow is consistent between different views with different colors.
   16988      * <p>
   16989      * The opacity of the final spot shadow is a function of the shadow caster height, the
   16990      * alpha channel of the outlineSpotShadowColor (typically opaque), and the
   16991      * {@link android.R.attr#spotShadowAlpha} theme attribute.
   16992      *
   16993      * @attr ref android.R.styleable#View_outlineSpotShadowColor
   16994      * @param color The color this View will cast for its elevation spot shadow.
   16995      */
   16996     public void setOutlineSpotShadowColor(@ColorInt int color) {
   16997         if (mRenderNode.setSpotShadowColor(color)) {
   16998             invalidateViewProperty(true, true);
   16999         }
   17000     }
   17001 
   17002     /**
   17003      * @return The shadow color set by {@link #setOutlineSpotShadowColor(int)}, or black if nothing
   17004      * was set
   17005      */
   17006     @InspectableProperty
   17007     public @ColorInt int getOutlineSpotShadowColor() {
   17008         return mRenderNode.getSpotShadowColor();
   17009     }
   17010 
   17011     /**
   17012      * Sets the color of the ambient shadow that is drawn when the view has a positive Z or
   17013      * elevation value.
   17014      * <p>
   17015      * By default the shadow color is black. Generally, this color will be opaque so the intensity
   17016      * of the shadow is consistent between different views with different colors.
   17017      * <p>
   17018      * The opacity of the final ambient shadow is a function of the shadow caster height, the
   17019      * alpha channel of the outlineAmbientShadowColor (typically opaque), and the
   17020      * {@link android.R.attr#ambientShadowAlpha} theme attribute.
   17021      *
   17022      * @attr ref android.R.styleable#View_outlineAmbientShadowColor
   17023      * @param color The color this View will cast for its elevation shadow.
   17024      */
   17025     public void setOutlineAmbientShadowColor(@ColorInt int color) {
   17026         if (mRenderNode.setAmbientShadowColor(color)) {
   17027             invalidateViewProperty(true, true);
   17028         }
   17029     }
   17030 
   17031     /**
   17032      * @return The shadow color set by {@link #setOutlineAmbientShadowColor(int)}, or black if
   17033      * nothing was set
   17034      */
   17035     @InspectableProperty
   17036     public @ColorInt int getOutlineAmbientShadowColor() {
   17037         return mRenderNode.getAmbientShadowColor();
   17038     }
   17039 
   17040 
   17041     /** @hide */
   17042     public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
   17043         mRenderNode.setRevealClip(shouldClip, x, y, radius);
   17044         invalidateViewProperty(false, false);
   17045     }
   17046 
   17047     /**
   17048      * Hit rectangle in parent's coordinates
   17049      *
   17050      * @param outRect The hit rectangle of the view.
   17051      */
   17052     public void getHitRect(Rect outRect) {
   17053         if (hasIdentityMatrix() || mAttachInfo == null) {
   17054             outRect.set(mLeft, mTop, mRight, mBottom);
   17055         } else {
   17056             final RectF tmpRect = mAttachInfo.mTmpTransformRect;
   17057             tmpRect.set(0, 0, getWidth(), getHeight());
   17058             getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
   17059             outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
   17060                     (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
   17061         }
   17062     }
   17063 
   17064     /**
   17065      * Determines whether the given point, in local coordinates is inside the view.
   17066      */
   17067     /*package*/ final boolean pointInView(float localX, float localY) {
   17068         return pointInView(localX, localY, 0);
   17069     }
   17070 
   17071     /**
   17072      * Utility method to determine whether the given point, in local coordinates,
   17073      * is inside the view, where the area of the view is expanded by the slop factor.
   17074      * This method is called while processing touch-move events to determine if the event
   17075      * is still within the view.
   17076      *
   17077      * @hide
   17078      */
   17079     @UnsupportedAppUsage
   17080     public boolean pointInView(float localX, float localY, float slop) {
   17081         return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
   17082                 localY < ((mBottom - mTop) + slop);
   17083     }
   17084 
   17085     /**
   17086      * When a view has focus and the user navigates away from it, the next view is searched for
   17087      * starting from the rectangle filled in by this method.
   17088      *
   17089      * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
   17090      * of the view.  However, if your view maintains some idea of internal selection,
   17091      * such as a cursor, or a selected row or column, you should override this method and
   17092      * fill in a more specific rectangle.
   17093      *
   17094      * @param r The rectangle to fill in, in this view's coordinates.
   17095      */
   17096     public void getFocusedRect(Rect r) {
   17097         getDrawingRect(r);
   17098     }
   17099 
   17100     /**
   17101      * If some part of this view is not clipped by any of its parents, then
   17102      * return that area in r in global (root) coordinates. To convert r to local
   17103      * coordinates (without taking possible View rotations into account), offset
   17104      * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
   17105      * If the view is completely clipped or translated out, return false.
   17106      *
   17107      * @param r If true is returned, r holds the global coordinates of the
   17108      *        visible portion of this view.
   17109      * @param globalOffset If true is returned, globalOffset holds the dx,dy
   17110      *        between this view and its root. globalOffet may be null.
   17111      * @return true if r is non-empty (i.e. part of the view is visible at the
   17112      *         root level.
   17113      */
   17114     public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
   17115         int width = mRight - mLeft;
   17116         int height = mBottom - mTop;
   17117         if (width > 0 && height > 0) {
   17118             r.set(0, 0, width, height);
   17119             if (globalOffset != null) {
   17120                 globalOffset.set(-mScrollX, -mScrollY);
   17121             }
   17122             return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
   17123         }
   17124         return false;
   17125     }
   17126 
   17127     public final boolean getGlobalVisibleRect(Rect r) {
   17128         return getGlobalVisibleRect(r, null);
   17129     }
   17130 
   17131     public final boolean getLocalVisibleRect(Rect r) {
   17132         final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
   17133         if (getGlobalVisibleRect(r, offset)) {
   17134             r.offset(-offset.x, -offset.y); // make r local
   17135             return true;
   17136         }
   17137         return false;
   17138     }
   17139 
   17140     /**
   17141      * Offset this view's vertical location by the specified number of pixels.
   17142      *
   17143      * @param offset the number of pixels to offset the view by
   17144      */
   17145     public void offsetTopAndBottom(int offset) {
   17146         if (offset != 0) {
   17147             final boolean matrixIsIdentity = hasIdentityMatrix();
   17148             if (matrixIsIdentity) {
   17149                 if (isHardwareAccelerated()) {
   17150                     invalidateViewProperty(false, false);
   17151                 } else {
   17152                     final ViewParent p = mParent;
   17153                     if (p != null && mAttachInfo != null) {
   17154                         final Rect r = mAttachInfo.mTmpInvalRect;
   17155                         int minTop;
   17156                         int maxBottom;
   17157                         int yLoc;
   17158                         if (offset < 0) {
   17159                             minTop = mTop + offset;
   17160                             maxBottom = mBottom;
   17161                             yLoc = offset;
   17162                         } else {
   17163                             minTop = mTop;
   17164                             maxBottom = mBottom + offset;
   17165                             yLoc = 0;
   17166                         }
   17167                         r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
   17168                         p.invalidateChild(this, r);
   17169                     }
   17170                 }
   17171             } else {
   17172                 invalidateViewProperty(false, false);
   17173             }
   17174 
   17175             mTop += offset;
   17176             mBottom += offset;
   17177             mRenderNode.offsetTopAndBottom(offset);
   17178             if (isHardwareAccelerated()) {
   17179                 invalidateViewProperty(false, false);
   17180                 invalidateParentIfNeededAndWasQuickRejected();
   17181             } else {
   17182                 if (!matrixIsIdentity) {
   17183                     invalidateViewProperty(false, true);
   17184                 }
   17185                 invalidateParentIfNeeded();
   17186             }
   17187             notifySubtreeAccessibilityStateChangedIfNeeded();
   17188         }
   17189     }
   17190 
   17191     /**
   17192      * Offset this view's horizontal location by the specified amount of pixels.
   17193      *
   17194      * @param offset the number of pixels to offset the view by
   17195      */
   17196     public void offsetLeftAndRight(int offset) {
   17197         if (offset != 0) {
   17198             final boolean matrixIsIdentity = hasIdentityMatrix();
   17199             if (matrixIsIdentity) {
   17200                 if (isHardwareAccelerated()) {
   17201                     invalidateViewProperty(false, false);
   17202                 } else {
   17203                     final ViewParent p = mParent;
   17204                     if (p != null && mAttachInfo != null) {
   17205                         final Rect r = mAttachInfo.mTmpInvalRect;
   17206                         int minLeft;
   17207                         int maxRight;
   17208                         if (offset < 0) {
   17209                             minLeft = mLeft + offset;
   17210                             maxRight = mRight;
   17211                         } else {
   17212                             minLeft = mLeft;
   17213                             maxRight = mRight + offset;
   17214                         }
   17215                         r.set(0, 0, maxRight - minLeft, mBottom - mTop);
   17216                         p.invalidateChild(this, r);
   17217                     }
   17218                 }
   17219             } else {
   17220                 invalidateViewProperty(false, false);
   17221             }
   17222 
   17223             mLeft += offset;
   17224             mRight += offset;
   17225             mRenderNode.offsetLeftAndRight(offset);
   17226             if (isHardwareAccelerated()) {
   17227                 invalidateViewProperty(false, false);
   17228                 invalidateParentIfNeededAndWasQuickRejected();
   17229             } else {
   17230                 if (!matrixIsIdentity) {
   17231                     invalidateViewProperty(false, true);
   17232                 }
   17233                 invalidateParentIfNeeded();
   17234             }
   17235             notifySubtreeAccessibilityStateChangedIfNeeded();
   17236         }
   17237     }
   17238 
   17239     /**
   17240      * Get the LayoutParams associated with this view. All views should have
   17241      * layout parameters. These supply parameters to the <i>parent</i> of this
   17242      * view specifying how it should be arranged. There are many subclasses of
   17243      * ViewGroup.LayoutParams, and these correspond to the different subclasses
   17244      * of ViewGroup that are responsible for arranging their children.
   17245      *
   17246      * This method may return null if this View is not attached to a parent
   17247      * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
   17248      * was not invoked successfully. When a View is attached to a parent
   17249      * ViewGroup, this method must not return null.
   17250      *
   17251      * @return The LayoutParams associated with this view, or null if no
   17252      *         parameters have been set yet
   17253      */
   17254     @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
   17255     public ViewGroup.LayoutParams getLayoutParams() {
   17256         return mLayoutParams;
   17257     }
   17258 
   17259     /**
   17260      * Set the layout parameters associated with this view. These supply
   17261      * parameters to the <i>parent</i> of this view specifying how it should be
   17262      * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
   17263      * correspond to the different subclasses of ViewGroup that are responsible
   17264      * for arranging their children.
   17265      *
   17266      * @param params The layout parameters for this view, cannot be null
   17267      */
   17268     public void setLayoutParams(ViewGroup.LayoutParams params) {
   17269         if (params == null) {
   17270             throw new NullPointerException("Layout parameters cannot be null");
   17271         }
   17272         mLayoutParams = params;
   17273         resolveLayoutParams();
   17274         if (mParent instanceof ViewGroup) {
   17275             ((ViewGroup) mParent).onSetLayoutParams(this, params);
   17276         }
   17277         requestLayout();
   17278     }
   17279 
   17280     /**
   17281      * Resolve the layout parameters depending on the resolved layout direction
   17282      *
   17283      * @hide
   17284      */
   17285     public void resolveLayoutParams() {
   17286         if (mLayoutParams != null) {
   17287             mLayoutParams.resolveLayoutDirection(getLayoutDirection());
   17288         }
   17289     }
   17290 
   17291     /**
   17292      * Set the scrolled position of your view. This will cause a call to
   17293      * {@link #onScrollChanged(int, int, int, int)} and the view will be
   17294      * invalidated.
   17295      * @param x the x position to scroll to
   17296      * @param y the y position to scroll to
   17297      */
   17298     public void scrollTo(int x, int y) {
   17299         if (mScrollX != x || mScrollY != y) {
   17300             int oldX = mScrollX;
   17301             int oldY = mScrollY;
   17302             mScrollX = x;
   17303             mScrollY = y;
   17304             invalidateParentCaches();
   17305             onScrollChanged(mScrollX, mScrollY, oldX, oldY);
   17306             if (!awakenScrollBars()) {
   17307                 postInvalidateOnAnimation();
   17308             }
   17309         }
   17310     }
   17311 
   17312     /**
   17313      * Move the scrolled position of your view. This will cause a call to
   17314      * {@link #onScrollChanged(int, int, int, int)} and the view will be
   17315      * invalidated.
   17316      * @param x the amount of pixels to scroll by horizontally
   17317      * @param y the amount of pixels to scroll by vertically
   17318      */
   17319     public void scrollBy(int x, int y) {
   17320         scrollTo(mScrollX + x, mScrollY + y);
   17321     }
   17322 
   17323     /**
   17324      * <p>Trigger the scrollbars to draw. When invoked this method starts an
   17325      * animation to fade the scrollbars out after a default delay. If a subclass
   17326      * provides animated scrolling, the start delay should equal the duration
   17327      * of the scrolling animation.</p>
   17328      *
   17329      * <p>The animation starts only if at least one of the scrollbars is
   17330      * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
   17331      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
   17332      * this method returns true, and false otherwise. If the animation is
   17333      * started, this method calls {@link #invalidate()}; in that case the
   17334      * caller should not call {@link #invalidate()}.</p>
   17335      *
   17336      * <p>This method should be invoked every time a subclass directly updates
   17337      * the scroll parameters.</p>
   17338      *
   17339      * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
   17340      * and {@link #scrollTo(int, int)}.</p>
   17341      *
   17342      * @return true if the animation is played, false otherwise
   17343      *
   17344      * @see #awakenScrollBars(int)
   17345      * @see #scrollBy(int, int)
   17346      * @see #scrollTo(int, int)
   17347      * @see #isHorizontalScrollBarEnabled()
   17348      * @see #isVerticalScrollBarEnabled()
   17349      * @see #setHorizontalScrollBarEnabled(boolean)
   17350      * @see #setVerticalScrollBarEnabled(boolean)
   17351      */
   17352     protected boolean awakenScrollBars() {
   17353         return mScrollCache != null &&
   17354                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
   17355     }
   17356 
   17357     /**
   17358      * Trigger the scrollbars to draw.
   17359      * This method differs from awakenScrollBars() only in its default duration.
   17360      * initialAwakenScrollBars() will show the scroll bars for longer than
   17361      * usual to give the user more of a chance to notice them.
   17362      *
   17363      * @return true if the animation is played, false otherwise.
   17364      */
   17365     private boolean initialAwakenScrollBars() {
   17366         return mScrollCache != null &&
   17367                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
   17368     }
   17369 
   17370     /**
   17371      * <p>
   17372      * Trigger the scrollbars to draw. When invoked this method starts an
   17373      * animation to fade the scrollbars out after a fixed delay. If a subclass
   17374      * provides animated scrolling, the start delay should equal the duration of
   17375      * the scrolling animation.
   17376      * </p>
   17377      *
   17378      * <p>
   17379      * The animation starts only if at least one of the scrollbars is enabled,
   17380      * as specified by {@link #isHorizontalScrollBarEnabled()} and
   17381      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
   17382      * this method returns true, and false otherwise. If the animation is
   17383      * started, this method calls {@link #invalidate()}; in that case the caller
   17384      * should not call {@link #invalidate()}.
   17385      * </p>
   17386      *
   17387      * <p>
   17388      * This method should be invoked every time a subclass directly updates the
   17389      * scroll parameters.
   17390      * </p>
   17391      *
   17392      * @param startDelay the delay, in milliseconds, after which the animation
   17393      *        should start; when the delay is 0, the animation starts
   17394      *        immediately
   17395      * @return true if the animation is played, false otherwise
   17396      *
   17397      * @see #scrollBy(int, int)
   17398      * @see #scrollTo(int, int)
   17399      * @see #isHorizontalScrollBarEnabled()
   17400      * @see #isVerticalScrollBarEnabled()
   17401      * @see #setHorizontalScrollBarEnabled(boolean)
   17402      * @see #setVerticalScrollBarEnabled(boolean)
   17403      */
   17404     protected boolean awakenScrollBars(int startDelay) {
   17405         return awakenScrollBars(startDelay, true);
   17406     }
   17407 
   17408     /**
   17409      * <p>
   17410      * Trigger the scrollbars to draw. When invoked this method starts an
   17411      * animation to fade the scrollbars out after a fixed delay. If a subclass
   17412      * provides animated scrolling, the start delay should equal the duration of
   17413      * the scrolling animation.
   17414      * </p>
   17415      *
   17416      * <p>
   17417      * The animation starts only if at least one of the scrollbars is enabled,
   17418      * as specified by {@link #isHorizontalScrollBarEnabled()} and
   17419      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
   17420      * this method returns true, and false otherwise. If the animation is
   17421      * started, this method calls {@link #invalidate()} if the invalidate parameter
   17422      * is set to true; in that case the caller
   17423      * should not call {@link #invalidate()}.
   17424      * </p>
   17425      *
   17426      * <p>
   17427      * This method should be invoked every time a subclass directly updates the
   17428      * scroll parameters.
   17429      * </p>
   17430      *
   17431      * @param startDelay the delay, in milliseconds, after which the animation
   17432      *        should start; when the delay is 0, the animation starts
   17433      *        immediately
   17434      *
   17435      * @param invalidate Whether this method should call invalidate
   17436      *
   17437      * @return true if the animation is played, false otherwise
   17438      *
   17439      * @see #scrollBy(int, int)
   17440      * @see #scrollTo(int, int)
   17441      * @see #isHorizontalScrollBarEnabled()
   17442      * @see #isVerticalScrollBarEnabled()
   17443      * @see #setHorizontalScrollBarEnabled(boolean)
   17444      * @see #setVerticalScrollBarEnabled(boolean)
   17445      */
   17446     protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
   17447         final ScrollabilityCache scrollCache = mScrollCache;
   17448 
   17449         if (scrollCache == null || !scrollCache.fadeScrollBars) {
   17450             return false;
   17451         }
   17452 
   17453         if (scrollCache.scrollBar == null) {
   17454             scrollCache.scrollBar = new ScrollBarDrawable();
   17455             scrollCache.scrollBar.setState(getDrawableState());
   17456             scrollCache.scrollBar.setCallback(this);
   17457         }
   17458 
   17459         if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
   17460 
   17461             if (invalidate) {
   17462                 // Invalidate to show the scrollbars
   17463                 postInvalidateOnAnimation();
   17464             }
   17465 
   17466             if (scrollCache.state == ScrollabilityCache.OFF) {
   17467                 // FIXME: this is copied from WindowManagerService.
   17468                 // We should get this value from the system when it
   17469                 // is possible to do so.
   17470                 final int KEY_REPEAT_FIRST_DELAY = 750;
   17471                 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
   17472             }
   17473 
   17474             // Tell mScrollCache when we should start fading. This may
   17475             // extend the fade start time if one was already scheduled
   17476             long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
   17477             scrollCache.fadeStartTime = fadeStartTime;
   17478             scrollCache.state = ScrollabilityCache.ON;
   17479 
   17480             // Schedule our fader to run, unscheduling any old ones first
   17481             if (mAttachInfo != null) {
   17482                 mAttachInfo.mHandler.removeCallbacks(scrollCache);
   17483                 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
   17484             }
   17485 
   17486             return true;
   17487         }
   17488 
   17489         return false;
   17490     }
   17491 
   17492     /**
   17493      * Do not invalidate views which are not visible and which are not running an animation. They
   17494      * will not get drawn and they should not set dirty flags as if they will be drawn
   17495      */
   17496     private boolean skipInvalidate() {
   17497         return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
   17498                 (!(mParent instanceof ViewGroup) ||
   17499                         !((ViewGroup) mParent).isViewTransitioning(this));
   17500     }
   17501 
   17502     /**
   17503      * Mark the area defined by dirty as needing to be drawn. If the view is
   17504      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
   17505      * point in the future.
   17506      * <p>
   17507      * This must be called from a UI thread. To call from a non-UI thread, call
   17508      * {@link #postInvalidate()}.
   17509      * <p>
   17510      * <b>WARNING:</b> In API 19 and below, this method may be destructive to
   17511      * {@code dirty}.
   17512      *
   17513      * @param dirty the rectangle representing the bounds of the dirty region
   17514      *
   17515      * @deprecated The switch to hardware accelerated rendering in API 14 reduced
   17516      * the importance of the dirty rectangle. In API 21 the given rectangle is
   17517      * ignored entirely in favor of an internally-calculated area instead.
   17518      * Because of this, clients are encouraged to just call {@link #invalidate()}.
   17519      */
   17520     @Deprecated
   17521     public void invalidate(Rect dirty) {
   17522         final int scrollX = mScrollX;
   17523         final int scrollY = mScrollY;
   17524         invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
   17525                 dirty.right - scrollX, dirty.bottom - scrollY, true, false);
   17526     }
   17527 
   17528     /**
   17529      * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
   17530      * coordinates of the dirty rect are relative to the view. If the view is
   17531      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
   17532      * point in the future.
   17533      * <p>
   17534      * This must be called from a UI thread. To call from a non-UI thread, call
   17535      * {@link #postInvalidate()}.
   17536      *
   17537      * @param l the left position of the dirty region
   17538      * @param t the top position of the dirty region
   17539      * @param r the right position of the dirty region
   17540      * @param b the bottom position of the dirty region
   17541      *
   17542      * @deprecated The switch to hardware accelerated rendering in API 14 reduced
   17543      * the importance of the dirty rectangle. In API 21 the given rectangle is
   17544      * ignored entirely in favor of an internally-calculated area instead.
   17545      * Because of this, clients are encouraged to just call {@link #invalidate()}.
   17546      */
   17547     @Deprecated
   17548     public void invalidate(int l, int t, int r, int b) {
   17549         final int scrollX = mScrollX;
   17550         final int scrollY = mScrollY;
   17551         invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
   17552     }
   17553 
   17554     /**
   17555      * Invalidate the whole view. If the view is visible,
   17556      * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
   17557      * the future.
   17558      * <p>
   17559      * This must be called from a UI thread. To call from a non-UI thread, call
   17560      * {@link #postInvalidate()}.
   17561      */
   17562     public void invalidate() {
   17563         invalidate(true);
   17564     }
   17565 
   17566     /**
   17567      * This is where the invalidate() work actually happens. A full invalidate()
   17568      * causes the drawing cache to be invalidated, but this function can be
   17569      * called with invalidateCache set to false to skip that invalidation step
   17570      * for cases that do not need it (for example, a component that remains at
   17571      * the same dimensions with the same content).
   17572      *
   17573      * @param invalidateCache Whether the drawing cache for this view should be
   17574      *            invalidated as well. This is usually true for a full
   17575      *            invalidate, but may be set to false if the View's contents or
   17576      *            dimensions have not changed.
   17577      * @hide
   17578      */
   17579     @UnsupportedAppUsage
   17580     public void invalidate(boolean invalidateCache) {
   17581         invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
   17582     }
   17583 
   17584     void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
   17585             boolean fullInvalidate) {
   17586         if (mGhostView != null) {
   17587             mGhostView.invalidate(true);
   17588             return;
   17589         }
   17590 
   17591         if (skipInvalidate()) {
   17592             return;
   17593         }
   17594 
   17595         // Reset content capture caches
   17596         mCachedContentCaptureSession = null;
   17597 
   17598         if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
   17599                 || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
   17600                 || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
   17601                 || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
   17602             if (fullInvalidate) {
   17603                 mLastIsOpaque = isOpaque();
   17604                 mPrivateFlags &= ~PFLAG_DRAWN;
   17605             }
   17606 
   17607             mPrivateFlags |= PFLAG_DIRTY;
   17608 
   17609             if (invalidateCache) {
   17610                 mPrivateFlags |= PFLAG_INVALIDATED;
   17611                 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
   17612             }
   17613 
   17614             // Propagate the damage rectangle to the parent view.
   17615             final AttachInfo ai = mAttachInfo;
   17616             final ViewParent p = mParent;
   17617             if (p != null && ai != null && l < r && t < b) {
   17618                 final Rect damage = ai.mTmpInvalRect;
   17619                 damage.set(l, t, r, b);
   17620                 p.invalidateChild(this, damage);
   17621             }
   17622 
   17623             // Damage the entire projection receiver, if necessary.
   17624             if (mBackground != null && mBackground.isProjected()) {
   17625                 final View receiver = getProjectionReceiver();
   17626                 if (receiver != null) {
   17627                     receiver.damageInParent();
   17628                 }
   17629             }
   17630         }
   17631     }
   17632 
   17633     /**
   17634      * @return this view's projection receiver, or {@code null} if none exists
   17635      */
   17636     private View getProjectionReceiver() {
   17637         ViewParent p = getParent();
   17638         while (p != null && p instanceof View) {
   17639             final View v = (View) p;
   17640             if (v.isProjectionReceiver()) {
   17641                 return v;
   17642             }
   17643             p = p.getParent();
   17644         }
   17645 
   17646         return null;
   17647     }
   17648 
   17649     /**
   17650      * @return whether the view is a projection receiver
   17651      */
   17652     private boolean isProjectionReceiver() {
   17653         return mBackground != null;
   17654     }
   17655 
   17656     /**
   17657      * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
   17658      * set any flags or handle all of the cases handled by the default invalidation methods.
   17659      * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
   17660      * dirty rect. This method calls into fast invalidation methods in ViewGroup that
   17661      * walk up the hierarchy, transforming the dirty rect as necessary.
   17662      *
   17663      * The method also handles normal invalidation logic if display list properties are not
   17664      * being used in this view. The invalidateParent and forceRedraw flags are used by that
   17665      * backup approach, to handle these cases used in the various property-setting methods.
   17666      *
   17667      * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
   17668      * are not being used in this view
   17669      * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
   17670      * list properties are not being used in this view
   17671      */
   17672     @UnsupportedAppUsage
   17673     void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
   17674         if (!isHardwareAccelerated()
   17675                 || !mRenderNode.hasDisplayList()
   17676                 || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
   17677             if (invalidateParent) {
   17678                 invalidateParentCaches();
   17679             }
   17680             if (forceRedraw) {
   17681                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
   17682             }
   17683             invalidate(false);
   17684         } else {
   17685             damageInParent();
   17686         }
   17687     }
   17688 
   17689     /**
   17690      * Tells the parent view to damage this view's bounds.
   17691      *
   17692      * @hide
   17693      */
   17694     protected void damageInParent() {
   17695         if (mParent != null && mAttachInfo != null) {
   17696             mParent.onDescendantInvalidated(this, this);
   17697         }
   17698     }
   17699 
   17700     /**
   17701      * Used to indicate that the parent of this view should clear its caches. This functionality
   17702      * is used to force the parent to rebuild its display list (when hardware-accelerated),
   17703      * which is necessary when various parent-managed properties of the view change, such as
   17704      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
   17705      * clears the parent caches and does not causes an invalidate event.
   17706      *
   17707      * @hide
   17708      */
   17709     @UnsupportedAppUsage
   17710     protected void invalidateParentCaches() {
   17711         if (mParent instanceof View) {
   17712             ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
   17713         }
   17714     }
   17715 
   17716     /**
   17717      * Used to indicate that the parent of this view should be invalidated. This functionality
   17718      * is used to force the parent to rebuild its display list (when hardware-accelerated),
   17719      * which is necessary when various parent-managed properties of the view change, such as
   17720      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
   17721      * an invalidation event to the parent.
   17722      *
   17723      * @hide
   17724      */
   17725     @UnsupportedAppUsage
   17726     protected void invalidateParentIfNeeded() {
   17727         if (isHardwareAccelerated() && mParent instanceof View) {
   17728             ((View) mParent).invalidate(true);
   17729         }
   17730     }
   17731 
   17732     /**
   17733      * @hide
   17734      */
   17735     protected void invalidateParentIfNeededAndWasQuickRejected() {
   17736         if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
   17737             // View was rejected last time it was drawn by its parent; this may have changed
   17738             invalidateParentIfNeeded();
   17739         }
   17740     }
   17741 
   17742     /**
   17743      * Indicates whether this View is opaque. An opaque View guarantees that it will
   17744      * draw all the pixels overlapping its bounds using a fully opaque color.
   17745      *
   17746      * Subclasses of View should override this method whenever possible to indicate
   17747      * whether an instance is opaque. Opaque Views are treated in a special way by
   17748      * the View hierarchy, possibly allowing it to perform optimizations during
   17749      * invalidate/draw passes.
   17750      *
   17751      * @return True if this View is guaranteed to be fully opaque, false otherwise.
   17752      */
   17753     @ViewDebug.ExportedProperty(category = "drawing")
   17754     public boolean isOpaque() {
   17755         return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
   17756                 getFinalAlpha() >= 1.0f;
   17757     }
   17758 
   17759     /**
   17760      * @hide
   17761      */
   17762     @UnsupportedAppUsage
   17763     protected void computeOpaqueFlags() {
   17764         // Opaque if:
   17765         //   - Has a background
   17766         //   - Background is opaque
   17767         //   - Doesn't have scrollbars or scrollbars overlay
   17768 
   17769         if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
   17770             mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
   17771         } else {
   17772             mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
   17773         }
   17774 
   17775         final int flags = mViewFlags;
   17776         if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
   17777                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
   17778                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
   17779             mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
   17780         } else {
   17781             mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
   17782         }
   17783     }
   17784 
   17785     /**
   17786      * @hide
   17787      */
   17788     protected boolean hasOpaqueScrollbars() {
   17789         return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
   17790     }
   17791 
   17792     /**
   17793      * @return A handler associated with the thread running the View. This
   17794      * handler can be used to pump events in the UI events queue.
   17795      */
   17796     public Handler getHandler() {
   17797         final AttachInfo attachInfo = mAttachInfo;
   17798         if (attachInfo != null) {
   17799             return attachInfo.mHandler;
   17800         }
   17801         return null;
   17802     }
   17803 
   17804     /**
   17805      * Returns the queue of runnable for this view.
   17806      *
   17807      * @return the queue of runnables for this view
   17808      */
   17809     private HandlerActionQueue getRunQueue() {
   17810         if (mRunQueue == null) {
   17811             mRunQueue = new HandlerActionQueue();
   17812         }
   17813         return mRunQueue;
   17814     }
   17815 
   17816     /**
   17817      * Gets the view root associated with the View.
   17818      * @return The view root, or null if none.
   17819      * @hide
   17820      */
   17821     @UnsupportedAppUsage
   17822     public ViewRootImpl getViewRootImpl() {
   17823         if (mAttachInfo != null) {
   17824             return mAttachInfo.mViewRootImpl;
   17825         }
   17826         return null;
   17827     }
   17828 
   17829     /**
   17830      * @hide
   17831      */
   17832     @UnsupportedAppUsage
   17833     public ThreadedRenderer getThreadedRenderer() {
   17834         return mAttachInfo != null ? mAttachInfo.mThreadedRenderer : null;
   17835     }
   17836 
   17837     /**
   17838      * <p>Causes the Runnable to be added to the message queue.
   17839      * The runnable will be run on the user interface thread.</p>
   17840      *
   17841      * @param action The Runnable that will be executed.
   17842      *
   17843      * @return Returns true if the Runnable was successfully placed in to the
   17844      *         message queue.  Returns false on failure, usually because the
   17845      *         looper processing the message queue is exiting.
   17846      *
   17847      * @see #postDelayed
   17848      * @see #removeCallbacks
   17849      */
   17850     public boolean post(Runnable action) {
   17851         final AttachInfo attachInfo = mAttachInfo;
   17852         if (attachInfo != null) {
   17853             return attachInfo.mHandler.post(action);
   17854         }
   17855 
   17856         // Postpone the runnable until we know on which thread it needs to run.
   17857         // Assume that the runnable will be successfully placed after attach.
   17858         getRunQueue().post(action);
   17859         return true;
   17860     }
   17861 
   17862     /**
   17863      * <p>Causes the Runnable to be added to the message queue, to be run
   17864      * after the specified amount of time elapses.
   17865      * The runnable will be run on the user interface thread.</p>
   17866      *
   17867      * @param action The Runnable that will be executed.
   17868      * @param delayMillis The delay (in milliseconds) until the Runnable
   17869      *        will be executed.
   17870      *
   17871      * @return true if the Runnable was successfully placed in to the
   17872      *         message queue.  Returns false on failure, usually because the
   17873      *         looper processing the message queue is exiting.  Note that a
   17874      *         result of true does not mean the Runnable will be processed --
   17875      *         if the looper is quit before the delivery time of the message
   17876      *         occurs then the message will be dropped.
   17877      *
   17878      * @see #post
   17879      * @see #removeCallbacks
   17880      */
   17881     public boolean postDelayed(Runnable action, long delayMillis) {
   17882         final AttachInfo attachInfo = mAttachInfo;
   17883         if (attachInfo != null) {
   17884             return attachInfo.mHandler.postDelayed(action, delayMillis);
   17885         }
   17886 
   17887         // Postpone the runnable until we know on which thread it needs to run.
   17888         // Assume that the runnable will be successfully placed after attach.
   17889         getRunQueue().postDelayed(action, delayMillis);
   17890         return true;
   17891     }
   17892 
   17893     /**
   17894      * <p>Causes the Runnable to execute on the next animation time step.
   17895      * The runnable will be run on the user interface thread.</p>
   17896      *
   17897      * @param action The Runnable that will be executed.
   17898      *
   17899      * @see #postOnAnimationDelayed
   17900      * @see #removeCallbacks
   17901      */
   17902     public void postOnAnimation(Runnable action) {
   17903         final AttachInfo attachInfo = mAttachInfo;
   17904         if (attachInfo != null) {
   17905             attachInfo.mViewRootImpl.mChoreographer.postCallback(
   17906                     Choreographer.CALLBACK_ANIMATION, action, null);
   17907         } else {
   17908             // Postpone the runnable until we know
   17909             // on which thread it needs to run.
   17910             getRunQueue().post(action);
   17911         }
   17912     }
   17913 
   17914     /**
   17915      * <p>Causes the Runnable to execute on the next animation time step,
   17916      * after the specified amount of time elapses.
   17917      * The runnable will be run on the user interface thread.</p>
   17918      *
   17919      * @param action The Runnable that will be executed.
   17920      * @param delayMillis The delay (in milliseconds) until the Runnable
   17921      *        will be executed.
   17922      *
   17923      * @see #postOnAnimation
   17924      * @see #removeCallbacks
   17925      */
   17926     public void postOnAnimationDelayed(Runnable action, long delayMillis) {
   17927         final AttachInfo attachInfo = mAttachInfo;
   17928         if (attachInfo != null) {
   17929             attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
   17930                     Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
   17931         } else {
   17932             // Postpone the runnable until we know
   17933             // on which thread it needs to run.
   17934             getRunQueue().postDelayed(action, delayMillis);
   17935         }
   17936     }
   17937 
   17938     /**
   17939      * <p>Removes the specified Runnable from the message queue.</p>
   17940      *
   17941      * @param action The Runnable to remove from the message handling queue
   17942      *
   17943      * @return true if this view could ask the Handler to remove the Runnable,
   17944      *         false otherwise. When the returned value is true, the Runnable
   17945      *         may or may not have been actually removed from the message queue
   17946      *         (for instance, if the Runnable was not in the queue already.)
   17947      *
   17948      * @see #post
   17949      * @see #postDelayed
   17950      * @see #postOnAnimation
   17951      * @see #postOnAnimationDelayed
   17952      */
   17953     public boolean removeCallbacks(Runnable action) {
   17954         if (action != null) {
   17955             final AttachInfo attachInfo = mAttachInfo;
   17956             if (attachInfo != null) {
   17957                 attachInfo.mHandler.removeCallbacks(action);
   17958                 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
   17959                         Choreographer.CALLBACK_ANIMATION, action, null);
   17960             }
   17961             getRunQueue().removeCallbacks(action);
   17962         }
   17963         return true;
   17964     }
   17965 
   17966     /**
   17967      * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
   17968      * Use this to invalidate the View from a non-UI thread.</p>
   17969      *
   17970      * <p>This method can be invoked from outside of the UI thread
   17971      * only when this View is attached to a window.</p>
   17972      *
   17973      * @see #invalidate()
   17974      * @see #postInvalidateDelayed(long)
   17975      */
   17976     public void postInvalidate() {
   17977         postInvalidateDelayed(0);
   17978     }
   17979 
   17980     /**
   17981      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
   17982      * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
   17983      *
   17984      * <p>This method can be invoked from outside of the UI thread
   17985      * only when this View is attached to a window.</p>
   17986      *
   17987      * @param left The left coordinate of the rectangle to invalidate.
   17988      * @param top The top coordinate of the rectangle to invalidate.
   17989      * @param right The right coordinate of the rectangle to invalidate.
   17990      * @param bottom The bottom coordinate of the rectangle to invalidate.
   17991      *
   17992      * @see #invalidate(int, int, int, int)
   17993      * @see #invalidate(Rect)
   17994      * @see #postInvalidateDelayed(long, int, int, int, int)
   17995      */
   17996     public void postInvalidate(int left, int top, int right, int bottom) {
   17997         postInvalidateDelayed(0, left, top, right, bottom);
   17998     }
   17999 
   18000     /**
   18001      * <p>Cause an invalidate to happen on a subsequent cycle through the event
   18002      * loop. Waits for the specified amount of time.</p>
   18003      *
   18004      * <p>This method can be invoked from outside of the UI thread
   18005      * only when this View is attached to a window.</p>
   18006      *
   18007      * @param delayMilliseconds the duration in milliseconds to delay the
   18008      *         invalidation by
   18009      *
   18010      * @see #invalidate()
   18011      * @see #postInvalidate()
   18012      */
   18013     public void postInvalidateDelayed(long delayMilliseconds) {
   18014         // We try only with the AttachInfo because there's no point in invalidating
   18015         // if we are not attached to our window
   18016         final AttachInfo attachInfo = mAttachInfo;
   18017         if (attachInfo != null) {
   18018             attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
   18019         }
   18020     }
   18021 
   18022     /**
   18023      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
   18024      * through the event loop. Waits for the specified amount of time.</p>
   18025      *
   18026      * <p>This method can be invoked from outside of the UI thread
   18027      * only when this View is attached to a window.</p>
   18028      *
   18029      * @param delayMilliseconds the duration in milliseconds to delay the
   18030      *         invalidation by
   18031      * @param left The left coordinate of the rectangle to invalidate.
   18032      * @param top The top coordinate of the rectangle to invalidate.
   18033      * @param right The right coordinate of the rectangle to invalidate.
   18034      * @param bottom The bottom coordinate of the rectangle to invalidate.
   18035      *
   18036      * @see #invalidate(int, int, int, int)
   18037      * @see #invalidate(Rect)
   18038      * @see #postInvalidate(int, int, int, int)
   18039      */
   18040     public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
   18041             int right, int bottom) {
   18042 
   18043         // We try only with the AttachInfo because there's no point in invalidating
   18044         // if we are not attached to our window
   18045         final AttachInfo attachInfo = mAttachInfo;
   18046         if (attachInfo != null) {
   18047             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
   18048             info.target = this;
   18049             info.left = left;
   18050             info.top = top;
   18051             info.right = right;
   18052             info.bottom = bottom;
   18053 
   18054             attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
   18055         }
   18056     }
   18057 
   18058     /**
   18059      * <p>Cause an invalidate to happen on the next animation time step, typically the
   18060      * next display frame.</p>
   18061      *
   18062      * <p>This method can be invoked from outside of the UI thread
   18063      * only when this View is attached to a window.</p>
   18064      *
   18065      * @see #invalidate()
   18066      */
   18067     public void postInvalidateOnAnimation() {
   18068         // We try only with the AttachInfo because there's no point in invalidating
   18069         // if we are not attached to our window
   18070         final AttachInfo attachInfo = mAttachInfo;
   18071         if (attachInfo != null) {
   18072             attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
   18073         }
   18074     }
   18075 
   18076     /**
   18077      * <p>Cause an invalidate of the specified area to happen on the next animation
   18078      * time step, typically the next display frame.</p>
   18079      *
   18080      * <p>This method can be invoked from outside of the UI thread
   18081      * only when this View is attached to a window.</p>
   18082      *
   18083      * @param left The left coordinate of the rectangle to invalidate.
   18084      * @param top The top coordinate of the rectangle to invalidate.
   18085      * @param right The right coordinate of the rectangle to invalidate.
   18086      * @param bottom The bottom coordinate of the rectangle to invalidate.
   18087      *
   18088      * @see #invalidate(int, int, int, int)
   18089      * @see #invalidate(Rect)
   18090      */
   18091     public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
   18092         // We try only with the AttachInfo because there's no point in invalidating
   18093         // if we are not attached to our window
   18094         final AttachInfo attachInfo = mAttachInfo;
   18095         if (attachInfo != null) {
   18096             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
   18097             info.target = this;
   18098             info.left = left;
   18099             info.top = top;
   18100             info.right = right;
   18101             info.bottom = bottom;
   18102 
   18103             attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
   18104         }
   18105     }
   18106 
   18107     /**
   18108      * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
   18109      * This event is sent at most once every
   18110      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
   18111      */
   18112     private void postSendViewScrolledAccessibilityEventCallback(int dx, int dy) {
   18113         if (mSendViewScrolledAccessibilityEvent == null) {
   18114             mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
   18115         }
   18116         mSendViewScrolledAccessibilityEvent.post(dx, dy);
   18117     }
   18118 
   18119     /**
   18120      * Called by a parent to request that a child update its values for mScrollX
   18121      * and mScrollY if necessary. This will typically be done if the child is
   18122      * animating a scroll using a {@link android.widget.Scroller Scroller}
   18123      * object.
   18124      */
   18125     public void computeScroll() {
   18126     }
   18127 
   18128     /**
   18129      * <p>Indicate whether the horizontal edges are faded when the view is
   18130      * scrolled horizontally.</p>
   18131      *
   18132      * @return true if the horizontal edges should are faded on scroll, false
   18133      *         otherwise
   18134      *
   18135      * @see #setHorizontalFadingEdgeEnabled(boolean)
   18136      *
   18137      * @attr ref android.R.styleable#View_requiresFadingEdge
   18138      */
   18139     public boolean isHorizontalFadingEdgeEnabled() {
   18140         return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
   18141     }
   18142 
   18143     /**
   18144      * <p>Define whether the horizontal edges should be faded when this view
   18145      * is scrolled horizontally.</p>
   18146      *
   18147      * @param horizontalFadingEdgeEnabled true if the horizontal edges should
   18148      *                                    be faded when the view is scrolled
   18149      *                                    horizontally
   18150      *
   18151      * @see #isHorizontalFadingEdgeEnabled()
   18152      *
   18153      * @attr ref android.R.styleable#View_requiresFadingEdge
   18154      */
   18155     public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
   18156         if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
   18157             if (horizontalFadingEdgeEnabled) {
   18158                 initScrollCache();
   18159             }
   18160 
   18161             mViewFlags ^= FADING_EDGE_HORIZONTAL;
   18162         }
   18163     }
   18164 
   18165     /**
   18166      * <p>Indicate whether the vertical edges are faded when the view is
   18167      * scrolled horizontally.</p>
   18168      *
   18169      * @return true if the vertical edges should are faded on scroll, false
   18170      *         otherwise
   18171      *
   18172      * @see #setVerticalFadingEdgeEnabled(boolean)
   18173      *
   18174      * @attr ref android.R.styleable#View_requiresFadingEdge
   18175      */
   18176     public boolean isVerticalFadingEdgeEnabled() {
   18177         return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
   18178     }
   18179 
   18180     /**
   18181      * <p>Define whether the vertical edges should be faded when this view
   18182      * is scrolled vertically.</p>
   18183      *
   18184      * @param verticalFadingEdgeEnabled true if the vertical edges should
   18185      *                                  be faded when the view is scrolled
   18186      *                                  vertically
   18187      *
   18188      * @see #isVerticalFadingEdgeEnabled()
   18189      *
   18190      * @attr ref android.R.styleable#View_requiresFadingEdge
   18191      */
   18192     public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
   18193         if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
   18194             if (verticalFadingEdgeEnabled) {
   18195                 initScrollCache();
   18196             }
   18197 
   18198             mViewFlags ^= FADING_EDGE_VERTICAL;
   18199         }
   18200     }
   18201 
   18202     /**
   18203      * Get the fading edge flags, used for inspection.
   18204      *
   18205      * @return One of {@link #FADING_EDGE_NONE}, {@link #FADING_EDGE_VERTICAL},
   18206      *         or {@link #FADING_EDGE_HORIZONTAL}
   18207      * @hide
   18208      */
   18209     @InspectableProperty(name = "requiresFadingEdge", flagMapping = {
   18210             @FlagEntry(target = FADING_EDGE_NONE, mask = FADING_EDGE_MASK, name = "none"),
   18211             @FlagEntry(target = FADING_EDGE_VERTICAL, name = "vertical"),
   18212             @FlagEntry(target = FADING_EDGE_HORIZONTAL, name = "horizontal")
   18213     })
   18214     public int getFadingEdge() {
   18215         return mViewFlags & FADING_EDGE_MASK;
   18216     }
   18217 
   18218     /**
   18219      * Get the fading edge length, used for inspection
   18220      *
   18221      * @return The fading edge length or 0
   18222      * @hide
   18223      */
   18224     @InspectableProperty
   18225     public int getFadingEdgeLength() {
   18226         if (mScrollCache != null && (mViewFlags & FADING_EDGE_MASK) != FADING_EDGE_NONE) {
   18227             return mScrollCache.fadingEdgeLength;
   18228         }
   18229         return 0;
   18230     }
   18231 
   18232     /**
   18233      * Returns the strength, or intensity, of the top faded edge. The strength is
   18234      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
   18235      * returns 0.0 or 1.0 but no value in between.
   18236      *
   18237      * Subclasses should override this method to provide a smoother fade transition
   18238      * when scrolling occurs.
   18239      *
   18240      * @return the intensity of the top fade as a float between 0.0f and 1.0f
   18241      */
   18242     protected float getTopFadingEdgeStrength() {
   18243         return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
   18244     }
   18245 
   18246     /**
   18247      * Returns the strength, or intensity, of the bottom faded edge. The strength is
   18248      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
   18249      * returns 0.0 or 1.0 but no value in between.
   18250      *
   18251      * Subclasses should override this method to provide a smoother fade transition
   18252      * when scrolling occurs.
   18253      *
   18254      * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
   18255      */
   18256     protected float getBottomFadingEdgeStrength() {
   18257         return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
   18258                 computeVerticalScrollRange() ? 1.0f : 0.0f;
   18259     }
   18260 
   18261     /**
   18262      * Returns the strength, or intensity, of the left faded edge. The strength is
   18263      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
   18264      * returns 0.0 or 1.0 but no value in between.
   18265      *
   18266      * Subclasses should override this method to provide a smoother fade transition
   18267      * when scrolling occurs.
   18268      *
   18269      * @return the intensity of the left fade as a float between 0.0f and 1.0f
   18270      */
   18271     protected float getLeftFadingEdgeStrength() {
   18272         return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
   18273     }
   18274 
   18275     /**
   18276      * Returns the strength, or intensity, of the right faded edge. The strength is
   18277      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
   18278      * returns 0.0 or 1.0 but no value in between.
   18279      *
   18280      * Subclasses should override this method to provide a smoother fade transition
   18281      * when scrolling occurs.
   18282      *
   18283      * @return the intensity of the right fade as a float between 0.0f and 1.0f
   18284      */
   18285     protected float getRightFadingEdgeStrength() {
   18286         return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
   18287                 computeHorizontalScrollRange() ? 1.0f : 0.0f;
   18288     }
   18289 
   18290     /**
   18291      * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
   18292      * scrollbar is not drawn by default.</p>
   18293      *
   18294      * @return true if the horizontal scrollbar should be painted, false
   18295      *         otherwise
   18296      *
   18297      * @see #setHorizontalScrollBarEnabled(boolean)
   18298      */
   18299     public boolean isHorizontalScrollBarEnabled() {
   18300         return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
   18301     }
   18302 
   18303     /**
   18304      * <p>Define whether the horizontal scrollbar should be drawn or not. The
   18305      * scrollbar is not drawn by default.</p>
   18306      *
   18307      * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
   18308      *                                   be painted
   18309      *
   18310      * @see #isHorizontalScrollBarEnabled()
   18311      */
   18312     public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
   18313         if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
   18314             mViewFlags ^= SCROLLBARS_HORIZONTAL;
   18315             computeOpaqueFlags();
   18316             resolvePadding();
   18317         }
   18318     }
   18319 
   18320     /**
   18321      * <p>Indicate whether the vertical scrollbar should be drawn or not. The
   18322      * scrollbar is not drawn by default.</p>
   18323      *
   18324      * @return true if the vertical scrollbar should be painted, false
   18325      *         otherwise
   18326      *
   18327      * @see #setVerticalScrollBarEnabled(boolean)
   18328      */
   18329     public boolean isVerticalScrollBarEnabled() {
   18330         return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
   18331     }
   18332 
   18333     /**
   18334      * <p>Define whether the vertical scrollbar should be drawn or not. The
   18335      * scrollbar is not drawn by default.</p>
   18336      *
   18337      * @param verticalScrollBarEnabled true if the vertical scrollbar should
   18338      *                                 be painted
   18339      *
   18340      * @see #isVerticalScrollBarEnabled()
   18341      */
   18342     public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
   18343         if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
   18344             mViewFlags ^= SCROLLBARS_VERTICAL;
   18345             computeOpaqueFlags();
   18346             resolvePadding();
   18347         }
   18348     }
   18349 
   18350     /**
   18351      * @hide
   18352      */
   18353     @UnsupportedAppUsage
   18354     protected void recomputePadding() {
   18355         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
   18356     }
   18357 
   18358     /**
   18359      * Define whether scrollbars will fade when the view is not scrolling.
   18360      *
   18361      * @param fadeScrollbars whether to enable fading
   18362      *
   18363      * @attr ref android.R.styleable#View_fadeScrollbars
   18364      */
   18365     public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
   18366         initScrollCache();
   18367         final ScrollabilityCache scrollabilityCache = mScrollCache;
   18368         scrollabilityCache.fadeScrollBars = fadeScrollbars;
   18369         if (fadeScrollbars) {
   18370             scrollabilityCache.state = ScrollabilityCache.OFF;
   18371         } else {
   18372             scrollabilityCache.state = ScrollabilityCache.ON;
   18373         }
   18374     }
   18375 
   18376     /**
   18377      *
   18378      * Returns true if scrollbars will fade when this view is not scrolling
   18379      *
   18380      * @return true if scrollbar fading is enabled
   18381      *
   18382      * @attr ref android.R.styleable#View_fadeScrollbars
   18383      */
   18384     public boolean isScrollbarFadingEnabled() {
   18385         return mScrollCache != null && mScrollCache.fadeScrollBars;
   18386     }
   18387 
   18388     /**
   18389      *
   18390      * Returns the delay before scrollbars fade.
   18391      *
   18392      * @return the delay before scrollbars fade
   18393      *
   18394      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
   18395      */
   18396     @InspectableProperty(name = "scrollbarDefaultDelayBeforeFade")
   18397     public int getScrollBarDefaultDelayBeforeFade() {
   18398         return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
   18399                 mScrollCache.scrollBarDefaultDelayBeforeFade;
   18400     }
   18401 
   18402     /**
   18403      * Define the delay before scrollbars fade.
   18404      *
   18405      * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
   18406      *
   18407      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
   18408      */
   18409     public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
   18410         getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
   18411     }
   18412 
   18413     /**
   18414      *
   18415      * Returns the scrollbar fade duration.
   18416      *
   18417      * @return the scrollbar fade duration, in milliseconds
   18418      *
   18419      * @attr ref android.R.styleable#View_scrollbarFadeDuration
   18420      */
   18421     @InspectableProperty(name = "scrollbarFadeDuration")
   18422     public int getScrollBarFadeDuration() {
   18423         return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
   18424                 mScrollCache.scrollBarFadeDuration;
   18425     }
   18426 
   18427     /**
   18428      * Define the scrollbar fade duration.
   18429      *
   18430      * @param scrollBarFadeDuration - the scrollbar fade duration, in milliseconds
   18431      *
   18432      * @attr ref android.R.styleable#View_scrollbarFadeDuration
   18433      */
   18434     public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
   18435         getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
   18436     }
   18437 
   18438     /**
   18439      *
   18440      * Returns the scrollbar size.
   18441      *
   18442      * @return the scrollbar size
   18443      *
   18444      * @attr ref android.R.styleable#View_scrollbarSize
   18445      */
   18446     @InspectableProperty(name = "scrollbarSize")
   18447     public int getScrollBarSize() {
   18448         return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
   18449                 mScrollCache.scrollBarSize;
   18450     }
   18451 
   18452     /**
   18453      * Define the scrollbar size.
   18454      *
   18455      * @param scrollBarSize - the scrollbar size
   18456      *
   18457      * @attr ref android.R.styleable#View_scrollbarSize
   18458      */
   18459     public void setScrollBarSize(int scrollBarSize) {
   18460         getScrollCache().scrollBarSize = scrollBarSize;
   18461     }
   18462 
   18463     /**
   18464      * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
   18465      * inset. When inset, they add to the padding of the view. And the scrollbars
   18466      * can be drawn inside the padding area or on the edge of the view. For example,
   18467      * if a view has a background drawable and you want to draw the scrollbars
   18468      * inside the padding specified by the drawable, you can use
   18469      * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
   18470      * appear at the edge of the view, ignoring the padding, then you can use
   18471      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
   18472      * @param style the style of the scrollbars. Should be one of
   18473      * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
   18474      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
   18475      * @see #SCROLLBARS_INSIDE_OVERLAY
   18476      * @see #SCROLLBARS_INSIDE_INSET
   18477      * @see #SCROLLBARS_OUTSIDE_OVERLAY
   18478      * @see #SCROLLBARS_OUTSIDE_INSET
   18479      *
   18480      * @attr ref android.R.styleable#View_scrollbarStyle
   18481      */
   18482     public void setScrollBarStyle(@ScrollBarStyle int style) {
   18483         if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
   18484             mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
   18485             computeOpaqueFlags();
   18486             resolvePadding();
   18487         }
   18488     }
   18489 
   18490     /**
   18491      * <p>Returns the current scrollbar style.</p>
   18492      * @return the current scrollbar style
   18493      * @see #SCROLLBARS_INSIDE_OVERLAY
   18494      * @see #SCROLLBARS_INSIDE_INSET
   18495      * @see #SCROLLBARS_OUTSIDE_OVERLAY
   18496      * @see #SCROLLBARS_OUTSIDE_INSET
   18497      *
   18498      * @attr ref android.R.styleable#View_scrollbarStyle
   18499      */
   18500     @ViewDebug.ExportedProperty(mapping = {
   18501             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
   18502             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
   18503             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
   18504             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
   18505     })
   18506     @InspectableProperty(name = "scrollbarStyle", enumMapping = {
   18507             @EnumEntry(value = SCROLLBARS_INSIDE_OVERLAY, name = "insideOverlay"),
   18508             @EnumEntry(value = SCROLLBARS_INSIDE_INSET, name = "insideInset"),
   18509             @EnumEntry(value = SCROLLBARS_OUTSIDE_OVERLAY, name = "outsideOverlay"),
   18510             @EnumEntry(value = SCROLLBARS_OUTSIDE_INSET, name = "outsideInset")
   18511     })
   18512     @ScrollBarStyle
   18513     public int getScrollBarStyle() {
   18514         return mViewFlags & SCROLLBARS_STYLE_MASK;
   18515     }
   18516 
   18517     /**
   18518      * <p>Compute the horizontal range that the horizontal scrollbar
   18519      * represents.</p>
   18520      *
   18521      * <p>The range is expressed in arbitrary units that must be the same as the
   18522      * units used by {@link #computeHorizontalScrollExtent()} and
   18523      * {@link #computeHorizontalScrollOffset()}.</p>
   18524      *
   18525      * <p>The default range is the drawing width of this view.</p>
   18526      *
   18527      * @return the total horizontal range represented by the horizontal
   18528      *         scrollbar
   18529      *
   18530      * @see #computeHorizontalScrollExtent()
   18531      * @see #computeHorizontalScrollOffset()
   18532      */
   18533     protected int computeHorizontalScrollRange() {
   18534         return getWidth();
   18535     }
   18536 
   18537     /**
   18538      * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
   18539      * within the horizontal range. This value is used to compute the position
   18540      * of the thumb within the scrollbar's track.</p>
   18541      *
   18542      * <p>The range is expressed in arbitrary units that must be the same as the
   18543      * units used by {@link #computeHorizontalScrollRange()} and
   18544      * {@link #computeHorizontalScrollExtent()}.</p>
   18545      *
   18546      * <p>The default offset is the scroll offset of this view.</p>
   18547      *
   18548      * @return the horizontal offset of the scrollbar's thumb
   18549      *
   18550      * @see #computeHorizontalScrollRange()
   18551      * @see #computeHorizontalScrollExtent()
   18552      */
   18553     protected int computeHorizontalScrollOffset() {
   18554         return mScrollX;
   18555     }
   18556 
   18557     /**
   18558      * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
   18559      * within the horizontal range. This value is used to compute the length
   18560      * of the thumb within the scrollbar's track.</p>
   18561      *
   18562      * <p>The range is expressed in arbitrary units that must be the same as the
   18563      * units used by {@link #computeHorizontalScrollRange()} and
   18564      * {@link #computeHorizontalScrollOffset()}.</p>
   18565      *
   18566      * <p>The default extent is the drawing width of this view.</p>
   18567      *
   18568      * @return the horizontal extent of the scrollbar's thumb
   18569      *
   18570      * @see #computeHorizontalScrollRange()
   18571      * @see #computeHorizontalScrollOffset()
   18572      */
   18573     protected int computeHorizontalScrollExtent() {
   18574         return getWidth();
   18575     }
   18576 
   18577     /**
   18578      * <p>Compute the vertical range that the vertical scrollbar represents.</p>
   18579      *
   18580      * <p>The range is expressed in arbitrary units that must be the same as the
   18581      * units used by {@link #computeVerticalScrollExtent()} and
   18582      * {@link #computeVerticalScrollOffset()}.</p>
   18583      *
   18584      * @return the total vertical range represented by the vertical scrollbar
   18585      *
   18586      * <p>The default range is the drawing height of this view.</p>
   18587      *
   18588      * @see #computeVerticalScrollExtent()
   18589      * @see #computeVerticalScrollOffset()
   18590      */
   18591     protected int computeVerticalScrollRange() {
   18592         return getHeight();
   18593     }
   18594 
   18595     /**
   18596      * <p>Compute the vertical offset of the vertical scrollbar's thumb
   18597      * within the horizontal range. This value is used to compute the position
   18598      * of the thumb within the scrollbar's track.</p>
   18599      *
   18600      * <p>The range is expressed in arbitrary units that must be the same as the
   18601      * units used by {@link #computeVerticalScrollRange()} and
   18602      * {@link #computeVerticalScrollExtent()}.</p>
   18603      *
   18604      * <p>The default offset is the scroll offset of this view.</p>
   18605      *
   18606      * @return the vertical offset of the scrollbar's thumb
   18607      *
   18608      * @see #computeVerticalScrollRange()
   18609      * @see #computeVerticalScrollExtent()
   18610      */
   18611     protected int computeVerticalScrollOffset() {
   18612         return mScrollY;
   18613     }
   18614 
   18615     /**
   18616      * <p>Compute the vertical extent of the vertical scrollbar's thumb
   18617      * within the vertical range. This value is used to compute the length
   18618      * of the thumb within the scrollbar's track.</p>
   18619      *
   18620      * <p>The range is expressed in arbitrary units that must be the same as the
   18621      * units used by {@link #computeVerticalScrollRange()} and
   18622      * {@link #computeVerticalScrollOffset()}.</p>
   18623      *
   18624      * <p>The default extent is the drawing height of this view.</p>
   18625      *
   18626      * @return the vertical extent of the scrollbar's thumb
   18627      *
   18628      * @see #computeVerticalScrollRange()
   18629      * @see #computeVerticalScrollOffset()
   18630      */
   18631     protected int computeVerticalScrollExtent() {
   18632         return getHeight();
   18633     }
   18634 
   18635     /**
   18636      * Check if this view can be scrolled horizontally in a certain direction.
   18637      *
   18638      * @param direction Negative to check scrolling left, positive to check scrolling right.
   18639      * @return true if this view can be scrolled in the specified direction, false otherwise.
   18640      */
   18641     public boolean canScrollHorizontally(int direction) {
   18642         final int offset = computeHorizontalScrollOffset();
   18643         final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
   18644         if (range == 0) return false;
   18645         if (direction < 0) {
   18646             return offset > 0;
   18647         } else {
   18648             return offset < range - 1;
   18649         }
   18650     }
   18651 
   18652     /**
   18653      * Check if this view can be scrolled vertically in a certain direction.
   18654      *
   18655      * @param direction Negative to check scrolling up, positive to check scrolling down.
   18656      * @return true if this view can be scrolled in the specified direction, false otherwise.
   18657      */
   18658     public boolean canScrollVertically(int direction) {
   18659         final int offset = computeVerticalScrollOffset();
   18660         final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
   18661         if (range == 0) return false;
   18662         if (direction < 0) {
   18663             return offset > 0;
   18664         } else {
   18665             return offset < range - 1;
   18666         }
   18667     }
   18668 
   18669     void getScrollIndicatorBounds(@NonNull Rect out) {
   18670         out.left = mScrollX;
   18671         out.right = mScrollX + mRight - mLeft;
   18672         out.top = mScrollY;
   18673         out.bottom = mScrollY + mBottom - mTop;
   18674     }
   18675 
   18676     private void onDrawScrollIndicators(Canvas c) {
   18677         if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
   18678             // No scroll indicators enabled.
   18679             return;
   18680         }
   18681 
   18682         final Drawable dr = mScrollIndicatorDrawable;
   18683         if (dr == null) {
   18684             // Scroll indicators aren't supported here.
   18685             return;
   18686         }
   18687 
   18688         final int h = dr.getIntrinsicHeight();
   18689         final int w = dr.getIntrinsicWidth();
   18690         final Rect rect = mAttachInfo.mTmpInvalRect;
   18691         getScrollIndicatorBounds(rect);
   18692 
   18693         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
   18694             final boolean canScrollUp = canScrollVertically(-1);
   18695             if (canScrollUp) {
   18696                 dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
   18697                 dr.draw(c);
   18698             }
   18699         }
   18700 
   18701         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
   18702             final boolean canScrollDown = canScrollVertically(1);
   18703             if (canScrollDown) {
   18704                 dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
   18705                 dr.draw(c);
   18706             }
   18707         }
   18708 
   18709         final int leftRtl;
   18710         final int rightRtl;
   18711         if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
   18712             leftRtl = PFLAG3_SCROLL_INDICATOR_END;
   18713             rightRtl = PFLAG3_SCROLL_INDICATOR_START;
   18714         } else {
   18715             leftRtl = PFLAG3_SCROLL_INDICATOR_START;
   18716             rightRtl = PFLAG3_SCROLL_INDICATOR_END;
   18717         }
   18718 
   18719         final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
   18720         if ((mPrivateFlags3 & leftMask) != 0) {
   18721             final boolean canScrollLeft = canScrollHorizontally(-1);
   18722             if (canScrollLeft) {
   18723                 dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
   18724                 dr.draw(c);
   18725             }
   18726         }
   18727 
   18728         final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
   18729         if ((mPrivateFlags3 & rightMask) != 0) {
   18730             final boolean canScrollRight = canScrollHorizontally(1);
   18731             if (canScrollRight) {
   18732                 dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
   18733                 dr.draw(c);
   18734             }
   18735         }
   18736     }
   18737 
   18738     private void getHorizontalScrollBarBounds(@Nullable Rect drawBounds,
   18739             @Nullable Rect touchBounds) {
   18740         final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
   18741         if (bounds == null) {
   18742             return;
   18743         }
   18744         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
   18745         final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
   18746                 && !isVerticalScrollBarHidden();
   18747         final int size = getHorizontalScrollbarHeight();
   18748         final int verticalScrollBarGap = drawVerticalScrollBar ?
   18749                 getVerticalScrollbarWidth() : 0;
   18750         final int width = mRight - mLeft;
   18751         final int height = mBottom - mTop;
   18752         bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
   18753         bounds.left = mScrollX + (mPaddingLeft & inside);
   18754         bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
   18755         bounds.bottom = bounds.top + size;
   18756 
   18757         if (touchBounds == null) {
   18758             return;
   18759         }
   18760         if (touchBounds != bounds) {
   18761             touchBounds.set(bounds);
   18762         }
   18763         final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
   18764         if (touchBounds.height() < minTouchTarget) {
   18765             final int adjust = (minTouchTarget - touchBounds.height()) / 2;
   18766             touchBounds.bottom = Math.min(touchBounds.bottom + adjust, mScrollY + height);
   18767             touchBounds.top = touchBounds.bottom - minTouchTarget;
   18768         }
   18769         if (touchBounds.width() < minTouchTarget) {
   18770             final int adjust = (minTouchTarget - touchBounds.width()) / 2;
   18771             touchBounds.left -= adjust;
   18772             touchBounds.right = touchBounds.left + minTouchTarget;
   18773         }
   18774     }
   18775 
   18776     private void getVerticalScrollBarBounds(@Nullable Rect bounds, @Nullable Rect touchBounds) {
   18777         if (mRoundScrollbarRenderer == null) {
   18778             getStraightVerticalScrollBarBounds(bounds, touchBounds);
   18779         } else {
   18780             getRoundVerticalScrollBarBounds(bounds != null ? bounds : touchBounds);
   18781         }
   18782     }
   18783 
   18784     private void getRoundVerticalScrollBarBounds(Rect bounds) {
   18785         final int width = mRight - mLeft;
   18786         final int height = mBottom - mTop;
   18787         // Do not take padding into account as we always want the scrollbars
   18788         // to hug the screen for round wearable devices.
   18789         bounds.left = mScrollX;
   18790         bounds.top = mScrollY;
   18791         bounds.right = bounds.left + width;
   18792         bounds.bottom = mScrollY + height;
   18793     }
   18794 
   18795     private void getStraightVerticalScrollBarBounds(@Nullable Rect drawBounds,
   18796             @Nullable Rect touchBounds) {
   18797         final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
   18798         if (bounds == null) {
   18799             return;
   18800         }
   18801         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
   18802         final int size = getVerticalScrollbarWidth();
   18803         int verticalScrollbarPosition = mVerticalScrollbarPosition;
   18804         if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
   18805             verticalScrollbarPosition = isLayoutRtl() ?
   18806                     SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
   18807         }
   18808         final int width = mRight - mLeft;
   18809         final int height = mBottom - mTop;
   18810         switch (verticalScrollbarPosition) {
   18811             default:
   18812             case SCROLLBAR_POSITION_RIGHT:
   18813                 bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
   18814                 break;
   18815             case SCROLLBAR_POSITION_LEFT:
   18816                 bounds.left = mScrollX + (mUserPaddingLeft & inside);
   18817                 break;
   18818         }
   18819         bounds.top = mScrollY + (mPaddingTop & inside);
   18820         bounds.right = bounds.left + size;
   18821         bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
   18822 
   18823         if (touchBounds == null) {
   18824             return;
   18825         }
   18826         if (touchBounds != bounds) {
   18827             touchBounds.set(bounds);
   18828         }
   18829         final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
   18830         if (touchBounds.width() < minTouchTarget) {
   18831             final int adjust = (minTouchTarget - touchBounds.width()) / 2;
   18832             if (verticalScrollbarPosition == SCROLLBAR_POSITION_RIGHT) {
   18833                 touchBounds.right = Math.min(touchBounds.right + adjust, mScrollX + width);
   18834                 touchBounds.left = touchBounds.right - minTouchTarget;
   18835             } else {
   18836                 touchBounds.left = Math.max(touchBounds.left + adjust, mScrollX);
   18837                 touchBounds.right = touchBounds.left + minTouchTarget;
   18838             }
   18839         }
   18840         if (touchBounds.height() < minTouchTarget) {
   18841             final int adjust = (minTouchTarget - touchBounds.height()) / 2;
   18842             touchBounds.top -= adjust;
   18843             touchBounds.bottom = touchBounds.top + minTouchTarget;
   18844         }
   18845     }
   18846 
   18847     /**
   18848      * <p>Request the drawing of the horizontal and the vertical scrollbar. The
   18849      * scrollbars are painted only if they have been awakened first.</p>
   18850      *
   18851      * @param canvas the canvas on which to draw the scrollbars
   18852      *
   18853      * @see #awakenScrollBars(int)
   18854      */
   18855     protected final void onDrawScrollBars(Canvas canvas) {
   18856         // scrollbars are drawn only when the animation is running
   18857         final ScrollabilityCache cache = mScrollCache;
   18858 
   18859         if (cache != null) {
   18860 
   18861             int state = cache.state;
   18862 
   18863             if (state == ScrollabilityCache.OFF) {
   18864                 return;
   18865             }
   18866 
   18867             boolean invalidate = false;
   18868 
   18869             if (state == ScrollabilityCache.FADING) {
   18870                 // We're fading -- get our fade interpolation
   18871                 if (cache.interpolatorValues == null) {
   18872                     cache.interpolatorValues = new float[1];
   18873                 }
   18874 
   18875                 float[] values = cache.interpolatorValues;
   18876 
   18877                 // Stops the animation if we're done
   18878                 if (cache.scrollBarInterpolator.timeToValues(values) ==
   18879                         Interpolator.Result.FREEZE_END) {
   18880                     cache.state = ScrollabilityCache.OFF;
   18881                 } else {
   18882                     cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
   18883                 }
   18884 
   18885                 // This will make the scroll bars inval themselves after
   18886                 // drawing. We only want this when we're fading so that
   18887                 // we prevent excessive redraws
   18888                 invalidate = true;
   18889             } else {
   18890                 // We're just on -- but we may have been fading before so
   18891                 // reset alpha
   18892                 cache.scrollBar.mutate().setAlpha(255);
   18893             }
   18894 
   18895             final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
   18896             final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
   18897                     && !isVerticalScrollBarHidden();
   18898 
   18899             // Fork out the scroll bar drawing for round wearable devices.
   18900             if (mRoundScrollbarRenderer != null) {
   18901                 if (drawVerticalScrollBar) {
   18902                     final Rect bounds = cache.mScrollBarBounds;
   18903                     getVerticalScrollBarBounds(bounds, null);
   18904                     mRoundScrollbarRenderer.drawRoundScrollbars(
   18905                             canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
   18906                     if (invalidate) {
   18907                         invalidate();
   18908                     }
   18909                 }
   18910                 // Do not draw horizontal scroll bars for round wearable devices.
   18911             } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
   18912                 final ScrollBarDrawable scrollBar = cache.scrollBar;
   18913 
   18914                 if (drawHorizontalScrollBar) {
   18915                     scrollBar.setParameters(computeHorizontalScrollRange(),
   18916                             computeHorizontalScrollOffset(),
   18917                             computeHorizontalScrollExtent(), false);
   18918                     final Rect bounds = cache.mScrollBarBounds;
   18919                     getHorizontalScrollBarBounds(bounds, null);
   18920                     onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
   18921                             bounds.right, bounds.bottom);
   18922                     if (invalidate) {
   18923                         invalidate(bounds);
   18924                     }
   18925                 }
   18926 
   18927                 if (drawVerticalScrollBar) {
   18928                     scrollBar.setParameters(computeVerticalScrollRange(),
   18929                             computeVerticalScrollOffset(),
   18930                             computeVerticalScrollExtent(), true);
   18931                     final Rect bounds = cache.mScrollBarBounds;
   18932                     getVerticalScrollBarBounds(bounds, null);
   18933                     onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
   18934                             bounds.right, bounds.bottom);
   18935                     if (invalidate) {
   18936                         invalidate(bounds);
   18937                     }
   18938                 }
   18939             }
   18940         }
   18941     }
   18942 
   18943     /**
   18944      * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
   18945      * FastScroller is visible.
   18946      * @return whether to temporarily hide the vertical scrollbar
   18947      * @hide
   18948      */
   18949     protected boolean isVerticalScrollBarHidden() {
   18950         return false;
   18951     }
   18952 
   18953     /**
   18954      * <p>Draw the horizontal scrollbar if
   18955      * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
   18956      *
   18957      * @param canvas the canvas on which to draw the scrollbar
   18958      * @param scrollBar the scrollbar's drawable
   18959      *
   18960      * @see #isHorizontalScrollBarEnabled()
   18961      * @see #computeHorizontalScrollRange()
   18962      * @see #computeHorizontalScrollExtent()
   18963      * @see #computeHorizontalScrollOffset()
   18964      * @hide
   18965      */
   18966     @UnsupportedAppUsage
   18967     protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
   18968             int l, int t, int r, int b) {
   18969         scrollBar.setBounds(l, t, r, b);
   18970         scrollBar.draw(canvas);
   18971     }
   18972 
   18973     /**
   18974      * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
   18975      * returns true.</p>
   18976      *
   18977      * @param canvas the canvas on which to draw the scrollbar
   18978      * @param scrollBar the scrollbar's drawable
   18979      *
   18980      * @see #isVerticalScrollBarEnabled()
   18981      * @see #computeVerticalScrollRange()
   18982      * @see #computeVerticalScrollExtent()
   18983      * @see #computeVerticalScrollOffset()
   18984      * @hide
   18985      */
   18986     @UnsupportedAppUsage
   18987     protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
   18988             int l, int t, int r, int b) {
   18989         scrollBar.setBounds(l, t, r, b);
   18990         scrollBar.draw(canvas);
   18991     }
   18992 
   18993     /**
   18994      * Implement this to do your drawing.
   18995      *
   18996      * @param canvas the canvas on which the background will be drawn
   18997      */
   18998     protected void onDraw(Canvas canvas) {
   18999     }
   19000 
   19001     /*
   19002      * Caller is responsible for calling requestLayout if necessary.
   19003      * (This allows addViewInLayout to not request a new layout.)
   19004      */
   19005     @UnsupportedAppUsage
   19006     void assignParent(ViewParent parent) {
   19007         if (mParent == null) {
   19008             mParent = parent;
   19009         } else if (parent == null) {
   19010             mParent = null;
   19011         } else {
   19012             throw new RuntimeException("view " + this + " being added, but"
   19013                     + " it already has a parent");
   19014         }
   19015     }
   19016 
   19017     /**
   19018      * This is called when the view is attached to a window.  At this point it
   19019      * has a Surface and will start drawing.  Note that this function is
   19020      * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
   19021      * however it may be called any time before the first onDraw -- including
   19022      * before or after {@link #onMeasure(int, int)}.
   19023      *
   19024      * @see #onDetachedFromWindow()
   19025      */
   19026     @CallSuper
   19027     protected void onAttachedToWindow() {
   19028         if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
   19029             mParent.requestTransparentRegion(this);
   19030         }
   19031 
   19032         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
   19033 
   19034         jumpDrawablesToCurrentState();
   19035 
   19036         AccessibilityNodeIdManager.getInstance().registerViewWithId(this, getAccessibilityViewId());
   19037         resetSubtreeAccessibilityStateChanged();
   19038 
   19039         // rebuild, since Outline not maintained while View is detached
   19040         rebuildOutline();
   19041 
   19042         if (isFocused()) {
   19043             notifyFocusChangeToInputMethodManager(true /* hasFocus */);
   19044         }
   19045     }
   19046 
   19047     /**
   19048      * Resolve all RTL related properties.
   19049      *
   19050      * @return true if resolution of RTL properties has been done
   19051      *
   19052      * @hide
   19053      */
   19054     public boolean resolveRtlPropertiesIfNeeded() {
   19055         if (!needRtlPropertiesResolution()) return false;
   19056 
   19057         // Order is important here: LayoutDirection MUST be resolved first
   19058         if (!isLayoutDirectionResolved()) {
   19059             resolveLayoutDirection();
   19060             resolveLayoutParams();
   19061         }
   19062         // ... then we can resolve the others properties depending on the resolved LayoutDirection.
   19063         if (!isTextDirectionResolved()) {
   19064             resolveTextDirection();
   19065         }
   19066         if (!isTextAlignmentResolved()) {
   19067             resolveTextAlignment();
   19068         }
   19069         // Should resolve Drawables before Padding because we need the layout direction of the
   19070         // Drawable to correctly resolve Padding.
   19071         if (!areDrawablesResolved()) {
   19072             resolveDrawables();
   19073         }
   19074         if (!isPaddingResolved()) {
   19075             resolvePadding();
   19076         }
   19077         onRtlPropertiesChanged(getLayoutDirection());
   19078         return true;
   19079     }
   19080 
   19081     /**
   19082      * Reset resolution of all RTL related properties.
   19083      *
   19084      * @hide
   19085      */
   19086     @TestApi
   19087     public void resetRtlProperties() {
   19088         resetResolvedLayoutDirection();
   19089         resetResolvedTextDirection();
   19090         resetResolvedTextAlignment();
   19091         resetResolvedPadding();
   19092         resetResolvedDrawables();
   19093     }
   19094 
   19095     /**
   19096      * @see #onScreenStateChanged(int)
   19097      */
   19098     void dispatchScreenStateChanged(int screenState) {
   19099         onScreenStateChanged(screenState);
   19100     }
   19101 
   19102     /**
   19103      * This method is called whenever the state of the screen this view is
   19104      * attached to changes. A state change will usually occurs when the screen
   19105      * turns on or off (whether it happens automatically or the user does it
   19106      * manually.)
   19107      *
   19108      * @param screenState The new state of the screen. Can be either
   19109      *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
   19110      */
   19111     public void onScreenStateChanged(int screenState) {
   19112     }
   19113 
   19114     /**
   19115      * @see #onMovedToDisplay(int, Configuration)
   19116      */
   19117     void dispatchMovedToDisplay(Display display, Configuration config) {
   19118         mAttachInfo.mDisplay = display;
   19119         mAttachInfo.mDisplayState = display.getState();
   19120         onMovedToDisplay(display.getDisplayId(), config);
   19121     }
   19122 
   19123     /**
   19124      * Called by the system when the hosting activity is moved from one display to another without
   19125      * recreation. This means that the activity is declared to handle all changes to configuration
   19126      * that happened when it was switched to another display, so it wasn't destroyed and created
   19127      * again.
   19128      *
   19129      * <p>This call will be followed by {@link #onConfigurationChanged(Configuration)} if the
   19130      * applied configuration actually changed. It is up to app developer to choose whether to handle
   19131      * the change in this method or in the following {@link #onConfigurationChanged(Configuration)}
   19132      * call.
   19133      *
   19134      * <p>Use this callback to track changes to the displays if some functionality relies on an
   19135      * association with some display properties.
   19136      *
   19137      * @param displayId The id of the display to which the view was moved.
   19138      * @param config Configuration of the resources on new display after move.
   19139      *
   19140      * @see #onConfigurationChanged(Configuration)
   19141      * @hide
   19142      */
   19143     public void onMovedToDisplay(int displayId, Configuration config) {
   19144     }
   19145 
   19146     /**
   19147      * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
   19148      */
   19149     @UnsupportedAppUsage
   19150     private boolean hasRtlSupport() {
   19151         return mContext.getApplicationInfo().hasRtlSupport();
   19152     }
   19153 
   19154     /**
   19155      * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
   19156      * RTL not supported)
   19157      */
   19158     private boolean isRtlCompatibilityMode() {
   19159         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
   19160         return targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1 || !hasRtlSupport();
   19161     }
   19162 
   19163     /**
   19164      * @return true if RTL properties need resolution.
   19165      *
   19166      */
   19167     private boolean needRtlPropertiesResolution() {
   19168         return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
   19169     }
   19170 
   19171     /**
   19172      * Called when any RTL property (layout direction or text direction or text alignment) has
   19173      * been changed.
   19174      *
   19175      * Subclasses need to override this method to take care of cached information that depends on the
   19176      * resolved layout direction, or to inform child views that inherit their layout direction.
   19177      *
   19178      * The default implementation does nothing.
   19179      *
   19180      * @param layoutDirection the direction of the layout
   19181      *
   19182      * @see #LAYOUT_DIRECTION_LTR
   19183      * @see #LAYOUT_DIRECTION_RTL
   19184      */
   19185     public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
   19186     }
   19187 
   19188     /**
   19189      * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
   19190      * that the parent directionality can and will be resolved before its children.
   19191      *
   19192      * @return true if resolution has been done, false otherwise.
   19193      *
   19194      * @hide
   19195      */
   19196     public boolean resolveLayoutDirection() {
   19197         // Clear any previous layout direction resolution
   19198         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
   19199 
   19200         if (hasRtlSupport()) {
   19201             // Set resolved depending on layout direction
   19202             switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
   19203                     PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
   19204                 case LAYOUT_DIRECTION_INHERIT:
   19205                     // We cannot resolve yet. LTR is by default and let the resolution happen again
   19206                     // later to get the correct resolved value
   19207                     if (!canResolveLayoutDirection()) return false;
   19208 
   19209                     // Parent has not yet resolved, LTR is still the default
   19210                     try {
   19211                         if (!mParent.isLayoutDirectionResolved()) return false;
   19212 
   19213                         if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
   19214                             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
   19215                         }
   19216                     } catch (AbstractMethodError e) {
   19217                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   19218                                 " does not fully implement ViewParent", e);
   19219                     }
   19220                     break;
   19221                 case LAYOUT_DIRECTION_RTL:
   19222                     mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
   19223                     break;
   19224                 case LAYOUT_DIRECTION_LOCALE:
   19225                     if((LAYOUT_DIRECTION_RTL ==
   19226                             TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
   19227                         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
   19228                     }
   19229                     break;
   19230                 default:
   19231                     // Nothing to do, LTR by default
   19232             }
   19233         }
   19234 
   19235         // Set to resolved
   19236         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
   19237         return true;
   19238     }
   19239 
   19240     /**
   19241      * Check if layout direction resolution can be done.
   19242      *
   19243      * @return true if layout direction resolution can be done otherwise return false.
   19244      */
   19245     public boolean canResolveLayoutDirection() {
   19246         switch (getRawLayoutDirection()) {
   19247             case LAYOUT_DIRECTION_INHERIT:
   19248                 if (mParent != null) {
   19249                     try {
   19250                         return mParent.canResolveLayoutDirection();
   19251                     } catch (AbstractMethodError e) {
   19252                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   19253                                 " does not fully implement ViewParent", e);
   19254                     }
   19255                 }
   19256                 return false;
   19257 
   19258             default:
   19259                 return true;
   19260         }
   19261     }
   19262 
   19263     /**
   19264      * Reset the resolved layout direction. Layout direction will be resolved during a call to
   19265      * {@link #onMeasure(int, int)}.
   19266      *
   19267      * @hide
   19268      */
   19269     @TestApi
   19270     public void resetResolvedLayoutDirection() {
   19271         // Reset the current resolved bits
   19272         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
   19273     }
   19274 
   19275     /**
   19276      * @return true if the layout direction is inherited.
   19277      *
   19278      * @hide
   19279      */
   19280     public boolean isLayoutDirectionInherited() {
   19281         return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
   19282     }
   19283 
   19284     /**
   19285      * @return true if layout direction has been resolved.
   19286      */
   19287     public boolean isLayoutDirectionResolved() {
   19288         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
   19289     }
   19290 
   19291     /**
   19292      * Return if padding has been resolved
   19293      *
   19294      * @hide
   19295      */
   19296     @UnsupportedAppUsage
   19297     boolean isPaddingResolved() {
   19298         return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
   19299     }
   19300 
   19301     /**
   19302      * Resolves padding depending on layout direction, if applicable, and
   19303      * recomputes internal padding values to adjust for scroll bars.
   19304      *
   19305      * @hide
   19306      */
   19307     @UnsupportedAppUsage
   19308     public void resolvePadding() {
   19309         final int resolvedLayoutDirection = getLayoutDirection();
   19310 
   19311         if (!isRtlCompatibilityMode()) {
   19312             // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
   19313             // If start / end padding are defined, they will be resolved (hence overriding) to
   19314             // left / right or right / left depending on the resolved layout direction.
   19315             // If start / end padding are not defined, use the left / right ones.
   19316             if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
   19317                 Rect padding = sThreadLocal.get();
   19318                 if (padding == null) {
   19319                     padding = new Rect();
   19320                     sThreadLocal.set(padding);
   19321                 }
   19322                 mBackground.getPadding(padding);
   19323                 if (!mLeftPaddingDefined) {
   19324                     mUserPaddingLeftInitial = padding.left;
   19325                 }
   19326                 if (!mRightPaddingDefined) {
   19327                     mUserPaddingRightInitial = padding.right;
   19328                 }
   19329             }
   19330             switch (resolvedLayoutDirection) {
   19331                 case LAYOUT_DIRECTION_RTL:
   19332                     if (mUserPaddingStart != UNDEFINED_PADDING) {
   19333                         mUserPaddingRight = mUserPaddingStart;
   19334                     } else {
   19335                         mUserPaddingRight = mUserPaddingRightInitial;
   19336                     }
   19337                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
   19338                         mUserPaddingLeft = mUserPaddingEnd;
   19339                     } else {
   19340                         mUserPaddingLeft = mUserPaddingLeftInitial;
   19341                     }
   19342                     break;
   19343                 case LAYOUT_DIRECTION_LTR:
   19344                 default:
   19345                     if (mUserPaddingStart != UNDEFINED_PADDING) {
   19346                         mUserPaddingLeft = mUserPaddingStart;
   19347                     } else {
   19348                         mUserPaddingLeft = mUserPaddingLeftInitial;
   19349                     }
   19350                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
   19351                         mUserPaddingRight = mUserPaddingEnd;
   19352                     } else {
   19353                         mUserPaddingRight = mUserPaddingRightInitial;
   19354                     }
   19355             }
   19356 
   19357             mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
   19358         }
   19359 
   19360         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
   19361         onRtlPropertiesChanged(resolvedLayoutDirection);
   19362 
   19363         mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
   19364     }
   19365 
   19366     /**
   19367      * Reset the resolved layout direction.
   19368      *
   19369      * @hide
   19370      */
   19371     @TestApi
   19372     public void resetResolvedPadding() {
   19373         resetResolvedPaddingInternal();
   19374     }
   19375 
   19376     /**
   19377      * Used when we only want to reset *this* view's padding and not trigger overrides
   19378      * in ViewGroup that reset children too.
   19379      */
   19380     void resetResolvedPaddingInternal() {
   19381         mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
   19382     }
   19383 
   19384     /**
   19385      * This is called when the view is detached from a window.  At this point it
   19386      * no longer has a surface for drawing.
   19387      *
   19388      * @see #onAttachedToWindow()
   19389      */
   19390     @CallSuper
   19391     protected void onDetachedFromWindow() {
   19392     }
   19393 
   19394     /**
   19395      * This is a framework-internal mirror of onDetachedFromWindow() that's called
   19396      * after onDetachedFromWindow().
   19397      *
   19398      * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
   19399      * The super method should be called at the end of the overridden method to ensure
   19400      * subclasses are destroyed first
   19401      *
   19402      * @hide
   19403      */
   19404     @CallSuper
   19405     @UnsupportedAppUsage
   19406     protected void onDetachedFromWindowInternal() {
   19407         mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
   19408         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
   19409         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
   19410 
   19411         removeUnsetPressCallback();
   19412         removeLongPressCallback();
   19413         removePerformClickCallback();
   19414         cancel(mSendViewScrolledAccessibilityEvent);
   19415         stopNestedScroll();
   19416 
   19417         // Anything that started animating right before detach should already
   19418         // be in its final state when re-attached.
   19419         jumpDrawablesToCurrentState();
   19420 
   19421         destroyDrawingCache();
   19422 
   19423         cleanupDraw();
   19424         mCurrentAnimation = null;
   19425 
   19426         if ((mViewFlags & TOOLTIP) == TOOLTIP) {
   19427             hideTooltip();
   19428         }
   19429 
   19430         AccessibilityNodeIdManager.getInstance().unregisterViewWithId(getAccessibilityViewId());
   19431     }
   19432 
   19433     private void cleanupDraw() {
   19434         resetDisplayList();
   19435         if (mAttachInfo != null) {
   19436             mAttachInfo.mViewRootImpl.cancelInvalidate(this);
   19437         }
   19438     }
   19439 
   19440     void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
   19441     }
   19442 
   19443     /**
   19444      * @return The number of times this view has been attached to a window
   19445      */
   19446     protected int getWindowAttachCount() {
   19447         return mWindowAttachCount;
   19448     }
   19449 
   19450     /**
   19451      * Retrieve a unique token identifying the window this view is attached to.
   19452      * @return Return the window's token for use in
   19453      * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
   19454      */
   19455     public IBinder getWindowToken() {
   19456         return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
   19457     }
   19458 
   19459     /**
   19460      * Retrieve the {@link WindowId} for the window this view is
   19461      * currently attached to.
   19462      */
   19463     public WindowId getWindowId() {
   19464         AttachInfo ai = mAttachInfo;
   19465         if (ai == null) {
   19466             return null;
   19467         }
   19468         if (ai.mWindowId == null) {
   19469             try {
   19470                 ai.mIWindowId = ai.mSession.getWindowId(ai.mWindowToken);
   19471                 if (ai.mIWindowId != null) {
   19472                     ai.mWindowId = new WindowId(ai.mIWindowId);
   19473                 }
   19474             } catch (RemoteException e) {
   19475             }
   19476         }
   19477         return ai.mWindowId;
   19478     }
   19479 
   19480     /**
   19481      * Retrieve a unique token identifying the top-level "real" window of
   19482      * the window that this view is attached to.  That is, this is like
   19483      * {@link #getWindowToken}, except if the window this view in is a panel
   19484      * window (attached to another containing window), then the token of
   19485      * the containing window is returned instead.
   19486      *
   19487      * @return Returns the associated window token, either
   19488      * {@link #getWindowToken()} or the containing window's token.
   19489      */
   19490     public IBinder getApplicationWindowToken() {
   19491         AttachInfo ai = mAttachInfo;
   19492         if (ai != null) {
   19493             IBinder appWindowToken = ai.mPanelParentWindowToken;
   19494             if (appWindowToken == null) {
   19495                 appWindowToken = ai.mWindowToken;
   19496             }
   19497             return appWindowToken;
   19498         }
   19499         return null;
   19500     }
   19501 
   19502     /**
   19503      * Gets the logical display to which the view's window has been attached.
   19504      *
   19505      * @return The logical display, or null if the view is not currently attached to a window.
   19506      */
   19507     public Display getDisplay() {
   19508         return mAttachInfo != null ? mAttachInfo.mDisplay : null;
   19509     }
   19510 
   19511     /**
   19512      * Retrieve private session object this view hierarchy is using to
   19513      * communicate with the window manager.
   19514      * @return the session object to communicate with the window manager
   19515      */
   19516     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
   19517     /*package*/ IWindowSession getWindowSession() {
   19518         return mAttachInfo != null ? mAttachInfo.mSession : null;
   19519     }
   19520 
   19521     /**
   19522      * Return the window this view is currently attached to. Used in
   19523      * {@link android.app.ActivityView} to communicate with WM.
   19524      * @hide
   19525      */
   19526     protected IWindow getWindow() {
   19527         return mAttachInfo != null ? mAttachInfo.mWindow : null;
   19528     }
   19529 
   19530     /**
   19531      * Return the visibility value of the least visible component passed.
   19532      */
   19533     int combineVisibility(int vis1, int vis2) {
   19534         // This works because VISIBLE < INVISIBLE < GONE.
   19535         return Math.max(vis1, vis2);
   19536     }
   19537 
   19538     /**
   19539      * @param info the {@link android.view.View.AttachInfo} to associated with
   19540      *        this view
   19541      */
   19542     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
   19543     void dispatchAttachedToWindow(AttachInfo info, int visibility) {
   19544         mAttachInfo = info;
   19545         if (mOverlay != null) {
   19546             mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
   19547         }
   19548         mWindowAttachCount++;
   19549         // We will need to evaluate the drawable state at least once.
   19550         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
   19551         if (mFloatingTreeObserver != null) {
   19552             info.mTreeObserver.merge(mFloatingTreeObserver);
   19553             mFloatingTreeObserver = null;
   19554         }
   19555 
   19556         registerPendingFrameMetricsObservers();
   19557 
   19558         if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
   19559             mAttachInfo.mScrollContainers.add(this);
   19560             mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
   19561         }
   19562         // Transfer all pending runnables.
   19563         if (mRunQueue != null) {
   19564             mRunQueue.executeActions(info.mHandler);
   19565             mRunQueue = null;
   19566         }
   19567         performCollectViewAttributes(mAttachInfo, visibility);
   19568         onAttachedToWindow();
   19569 
   19570         ListenerInfo li = mListenerInfo;
   19571         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
   19572                 li != null ? li.mOnAttachStateChangeListeners : null;
   19573         if (listeners != null && listeners.size() > 0) {
   19574             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
   19575             // perform the dispatching. The iterator is a safe guard against listeners that
   19576             // could mutate the list by calling the various add/remove methods. This prevents
   19577             // the array from being modified while we iterate it.
   19578             for (OnAttachStateChangeListener listener : listeners) {
   19579                 listener.onViewAttachedToWindow(this);
   19580             }
   19581         }
   19582 
   19583         int vis = info.mWindowVisibility;
   19584         if (vis != GONE) {
   19585             onWindowVisibilityChanged(vis);
   19586             if (isShown()) {
   19587                 // Calling onVisibilityAggregated directly here since the subtree will also
   19588                 // receive dispatchAttachedToWindow and this same call
   19589                 onVisibilityAggregated(vis == VISIBLE);
   19590             }
   19591         }
   19592 
   19593         // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
   19594         // As all views in the subtree will already receive dispatchAttachedToWindow
   19595         // traversing the subtree again here is not desired.
   19596         onVisibilityChanged(this, visibility);
   19597 
   19598         if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
   19599             // If nobody has evaluated the drawable state yet, then do it now.
   19600             refreshDrawableState();
   19601         }
   19602         needGlobalAttributesUpdate(false);
   19603 
   19604         notifyEnterOrExitForAutoFillIfNeeded(true);
   19605     }
   19606 
   19607     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
   19608     void dispatchDetachedFromWindow() {
   19609         AttachInfo info = mAttachInfo;
   19610         if (info != null) {
   19611             int vis = info.mWindowVisibility;
   19612             if (vis != GONE) {
   19613                 onWindowVisibilityChanged(GONE);
   19614                 if (isShown()) {
   19615                     // Invoking onVisibilityAggregated directly here since the subtree
   19616                     // will also receive detached from window
   19617                     onVisibilityAggregated(false);
   19618                 }
   19619             }
   19620         }
   19621 
   19622         onDetachedFromWindow();
   19623         onDetachedFromWindowInternal();
   19624 
   19625         InputMethodManager imm = getContext().getSystemService(InputMethodManager.class);
   19626         if (imm != null) {
   19627             imm.onViewDetachedFromWindow(this);
   19628         }
   19629 
   19630         ListenerInfo li = mListenerInfo;
   19631         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
   19632                 li != null ? li.mOnAttachStateChangeListeners : null;
   19633         if (listeners != null && listeners.size() > 0) {
   19634             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
   19635             // perform the dispatching. The iterator is a safe guard against listeners that
   19636             // could mutate the list by calling the various add/remove methods. This prevents
   19637             // the array from being modified while we iterate it.
   19638             for (OnAttachStateChangeListener listener : listeners) {
   19639                 listener.onViewDetachedFromWindow(this);
   19640             }
   19641         }
   19642 
   19643         if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
   19644             mAttachInfo.mScrollContainers.remove(this);
   19645             mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
   19646         }
   19647 
   19648         mAttachInfo = null;
   19649         if (mOverlay != null) {
   19650             mOverlay.getOverlayView().dispatchDetachedFromWindow();
   19651         }
   19652 
   19653         notifyEnterOrExitForAutoFillIfNeeded(false);
   19654     }
   19655 
   19656     /**
   19657      * Cancel any deferred high-level input events that were previously posted to the event queue.
   19658      *
   19659      * <p>Many views post high-level events such as click handlers to the event queue
   19660      * to run deferred in order to preserve a desired user experience - clearing visible
   19661      * pressed states before executing, etc. This method will abort any events of this nature
   19662      * that are currently in flight.</p>
   19663      *
   19664      * <p>Custom views that generate their own high-level deferred input events should override
   19665      * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
   19666      *
   19667      * <p>This will also cancel pending input events for any child views.</p>
   19668      *
   19669      * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
   19670      * This will not impact newer events posted after this call that may occur as a result of
   19671      * lower-level input events still waiting in the queue. If you are trying to prevent
   19672      * double-submitted  events for the duration of some sort of asynchronous transaction
   19673      * you should also take other steps to protect against unexpected double inputs e.g. calling
   19674      * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
   19675      * the transaction completes, tracking already submitted transaction IDs, etc.</p>
   19676      */
   19677     public final void cancelPendingInputEvents() {
   19678         dispatchCancelPendingInputEvents();
   19679     }
   19680 
   19681     /**
   19682      * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
   19683      * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
   19684      */
   19685     void dispatchCancelPendingInputEvents() {
   19686         mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
   19687         onCancelPendingInputEvents();
   19688         if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
   19689             throw new SuperNotCalledException("View " + getClass().getSimpleName() +
   19690                     " did not call through to super.onCancelPendingInputEvents()");
   19691         }
   19692     }
   19693 
   19694     /**
   19695      * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
   19696      * a parent view.
   19697      *
   19698      * <p>This method is responsible for removing any pending high-level input events that were
   19699      * posted to the event queue to run later. Custom view classes that post their own deferred
   19700      * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
   19701      * {@link android.os.Handler} should override this method, call
   19702      * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
   19703      * </p>
   19704      */
   19705     public void onCancelPendingInputEvents() {
   19706         removePerformClickCallback();
   19707         cancelLongPress();
   19708         mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
   19709     }
   19710 
   19711     /**
   19712      * Store this view hierarchy's frozen state into the given container.
   19713      *
   19714      * @param container The SparseArray in which to save the view's state.
   19715      *
   19716      * @see #restoreHierarchyState(android.util.SparseArray)
   19717      * @see #dispatchSaveInstanceState(android.util.SparseArray)
   19718      * @see #onSaveInstanceState()
   19719      */
   19720     public void saveHierarchyState(SparseArray<Parcelable> container) {
   19721         dispatchSaveInstanceState(container);
   19722     }
   19723 
   19724     /**
   19725      * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
   19726      * this view and its children. May be overridden to modify how freezing happens to a
   19727      * view's children; for example, some views may want to not store state for their children.
   19728      *
   19729      * @param container The SparseArray in which to save the view's state.
   19730      *
   19731      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
   19732      * @see #saveHierarchyState(android.util.SparseArray)
   19733      * @see #onSaveInstanceState()
   19734      */
   19735     protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
   19736         if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
   19737             mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
   19738             Parcelable state = onSaveInstanceState();
   19739             if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
   19740                 throw new IllegalStateException(
   19741                         "Derived class did not call super.onSaveInstanceState()");
   19742             }
   19743             if (state != null) {
   19744                 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
   19745                 // + ": " + state);
   19746                 container.put(mID, state);
   19747             }
   19748         }
   19749     }
   19750 
   19751     /**
   19752      * Hook allowing a view to generate a representation of its internal state
   19753      * that can later be used to create a new instance with that same state.
   19754      * This state should only contain information that is not persistent or can
   19755      * not be reconstructed later. For example, you will never store your
   19756      * current position on screen because that will be computed again when a
   19757      * new instance of the view is placed in its view hierarchy.
   19758      * <p>
   19759      * Some examples of things you may store here: the current cursor position
   19760      * in a text view (but usually not the text itself since that is stored in a
   19761      * content provider or other persistent storage), the currently selected
   19762      * item in a list view.
   19763      *
   19764      * @return Returns a Parcelable object containing the view's current dynamic
   19765      *         state, or null if there is nothing interesting to save.
   19766      * @see #onRestoreInstanceState(Parcelable)
   19767      * @see #saveHierarchyState(SparseArray)
   19768      * @see #dispatchSaveInstanceState(SparseArray)
   19769      * @see #setSaveEnabled(boolean)
   19770      */
   19771     @CallSuper
   19772     @Nullable protected Parcelable onSaveInstanceState() {
   19773         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
   19774         if (mStartActivityRequestWho != null || isAutofilled()
   19775                 || mAutofillViewId > LAST_APP_AUTOFILL_ID) {
   19776             BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
   19777 
   19778             if (mStartActivityRequestWho != null) {
   19779                 state.mSavedData |= BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED;
   19780             }
   19781 
   19782             if (isAutofilled()) {
   19783                 state.mSavedData |= BaseSavedState.IS_AUTOFILLED;
   19784             }
   19785 
   19786             if (mAutofillViewId > LAST_APP_AUTOFILL_ID) {
   19787                 state.mSavedData |= BaseSavedState.AUTOFILL_ID;
   19788             }
   19789 
   19790             state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
   19791             state.mIsAutofilled = isAutofilled();
   19792             state.mAutofillViewId = mAutofillViewId;
   19793             return state;
   19794         }
   19795         return BaseSavedState.EMPTY_STATE;
   19796     }
   19797 
   19798     /**
   19799      * Restore this view hierarchy's frozen state from the given container.
   19800      *
   19801      * @param container The SparseArray which holds previously frozen states.
   19802      *
   19803      * @see #saveHierarchyState(android.util.SparseArray)
   19804      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
   19805      * @see #onRestoreInstanceState(android.os.Parcelable)
   19806      */
   19807     public void restoreHierarchyState(SparseArray<Parcelable> container) {
   19808         dispatchRestoreInstanceState(container);
   19809     }
   19810 
   19811     /**
   19812      * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
   19813      * state for this view and its children. May be overridden to modify how restoring
   19814      * happens to a view's children; for example, some views may want to not store state
   19815      * for their children.
   19816      *
   19817      * @param container The SparseArray which holds previously saved state.
   19818      *
   19819      * @see #dispatchSaveInstanceState(android.util.SparseArray)
   19820      * @see #restoreHierarchyState(android.util.SparseArray)
   19821      * @see #onRestoreInstanceState(android.os.Parcelable)
   19822      */
   19823     protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
   19824         if (mID != NO_ID) {
   19825             Parcelable state = container.get(mID);
   19826             if (state != null) {
   19827                 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
   19828                 // + ": " + state);
   19829                 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
   19830                 onRestoreInstanceState(state);
   19831                 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
   19832                     throw new IllegalStateException(
   19833                             "Derived class did not call super.onRestoreInstanceState()");
   19834                 }
   19835             }
   19836         }
   19837     }
   19838 
   19839     /**
   19840      * Hook allowing a view to re-apply a representation of its internal state that had previously
   19841      * been generated by {@link #onSaveInstanceState}. This function will never be called with a
   19842      * null state.
   19843      *
   19844      * @param state The frozen state that had previously been returned by
   19845      *        {@link #onSaveInstanceState}.
   19846      *
   19847      * @see #onSaveInstanceState()
   19848      * @see #restoreHierarchyState(android.util.SparseArray)
   19849      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
   19850      */
   19851     @CallSuper
   19852     protected void onRestoreInstanceState(Parcelable state) {
   19853         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
   19854         if (state != null && !(state instanceof AbsSavedState)) {
   19855             throw new IllegalArgumentException("Wrong state class, expecting View State but "
   19856                     + "received " + state.getClass().toString() + " instead. This usually happens "
   19857                     + "when two views of different type have the same id in the same hierarchy. "
   19858                     + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
   19859                     + "other views do not use the same id.");
   19860         }
   19861         if (state != null && state instanceof BaseSavedState) {
   19862             BaseSavedState baseState = (BaseSavedState) state;
   19863 
   19864             if ((baseState.mSavedData & BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED) != 0) {
   19865                 mStartActivityRequestWho = baseState.mStartActivityRequestWhoSaved;
   19866             }
   19867             if ((baseState.mSavedData & BaseSavedState.IS_AUTOFILLED) != 0) {
   19868                 setAutofilled(baseState.mIsAutofilled);
   19869             }
   19870             if ((baseState.mSavedData & BaseSavedState.AUTOFILL_ID) != 0) {
   19871                 // It can happen that views have the same view id and the restoration path will not
   19872                 // be able to distinguish between them. The autofill id needs to be unique though.
   19873                 // Hence prevent the same autofill view id from being restored multiple times.
   19874                 ((BaseSavedState) state).mSavedData &= ~BaseSavedState.AUTOFILL_ID;
   19875 
   19876                 if ((mPrivateFlags3 & PFLAG3_AUTOFILLID_EXPLICITLY_SET) != 0) {
   19877                     // Ignore when view already set it through setAutofillId();
   19878                     if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.DEBUG)) {
   19879                         Log.d(AUTOFILL_LOG_TAG, "onRestoreInstanceState(): not setting autofillId "
   19880                                 + "to " + baseState.mAutofillViewId + " because view explicitly set"
   19881                                 + " it to " + mAutofillId);
   19882                     }
   19883                 } else {
   19884                     mAutofillViewId = baseState.mAutofillViewId;
   19885                     mAutofillId = null; // will be set on demand by getAutofillId()
   19886                 }
   19887             }
   19888         }
   19889     }
   19890 
   19891     /**
   19892      * <p>Return the time at which the drawing of the view hierarchy started.</p>
   19893      *
   19894      * @return the drawing start time in milliseconds
   19895      */
   19896     public long getDrawingTime() {
   19897         return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
   19898     }
   19899 
   19900     /**
   19901      * <p>Enables or disables the duplication of the parent's state into this view. When
   19902      * duplication is enabled, this view gets its drawable state from its parent rather
   19903      * than from its own internal properties.</p>
   19904      *
   19905      * <p>Note: in the current implementation, setting this property to true after the
   19906      * view was added to a ViewGroup might have no effect at all. This property should
   19907      * always be used from XML or set to true before adding this view to a ViewGroup.</p>
   19908      *
   19909      * <p>Note: if this view's parent addStateFromChildren property is enabled and this
   19910      * property is enabled, an exception will be thrown.</p>
   19911      *
   19912      * <p>Note: if the child view uses and updates additional states which are unknown to the
   19913      * parent, these states should not be affected by this method.</p>
   19914      *
   19915      * @param enabled True to enable duplication of the parent's drawable state, false
   19916      *                to disable it.
   19917      *
   19918      * @see #getDrawableState()
   19919      * @see #isDuplicateParentStateEnabled()
   19920      */
   19921     public void setDuplicateParentStateEnabled(boolean enabled) {
   19922         setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
   19923     }
   19924 
   19925     /**
   19926      * <p>Indicates whether this duplicates its drawable state from its parent.</p>
   19927      *
   19928      * @return True if this view's drawable state is duplicated from the parent,
   19929      *         false otherwise
   19930      *
   19931      * @see #getDrawableState()
   19932      * @see #setDuplicateParentStateEnabled(boolean)
   19933      */
   19934     @InspectableProperty(name = "duplicateParentState")
   19935     public boolean isDuplicateParentStateEnabled() {
   19936         return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
   19937     }
   19938 
   19939     /**
   19940      * <p>Specifies the type of layer backing this view. The layer can be
   19941      * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
   19942      * {@link #LAYER_TYPE_HARDWARE}.</p>
   19943      *
   19944      * <p>A layer is associated with an optional {@link android.graphics.Paint}
   19945      * instance that controls how the layer is composed on screen. The following
   19946      * properties of the paint are taken into account when composing the layer:</p>
   19947      * <ul>
   19948      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
   19949      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
   19950      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
   19951      * </ul>
   19952      *
   19953      * <p>If this view has an alpha value set to < 1.0 by calling
   19954      * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
   19955      * by this view's alpha value.</p>
   19956      *
   19957      * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
   19958      * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
   19959      * for more information on when and how to use layers.</p>
   19960      *
   19961      * @param layerType The type of layer to use with this view, must be one of
   19962      *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
   19963      *        {@link #LAYER_TYPE_HARDWARE}
   19964      * @param paint The paint used to compose the layer. This argument is optional
   19965      *        and can be null. It is ignored when the layer type is
   19966      *        {@link #LAYER_TYPE_NONE}
   19967      *
   19968      * @see #getLayerType()
   19969      * @see #LAYER_TYPE_NONE
   19970      * @see #LAYER_TYPE_SOFTWARE
   19971      * @see #LAYER_TYPE_HARDWARE
   19972      * @see #setAlpha(float)
   19973      *
   19974      * @attr ref android.R.styleable#View_layerType
   19975      */
   19976     public void setLayerType(@LayerType int layerType, @Nullable Paint paint) {
   19977         if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
   19978             throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
   19979                     + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
   19980         }
   19981 
   19982         boolean typeChanged = mRenderNode.setLayerType(layerType);
   19983 
   19984         if (!typeChanged) {
   19985             setLayerPaint(paint);
   19986             return;
   19987         }
   19988 
   19989         if (layerType != LAYER_TYPE_SOFTWARE) {
   19990             // Destroy any previous software drawing cache if present
   19991             // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
   19992             // drawing cache created in View#draw when drawing to a SW canvas.
   19993             destroyDrawingCache();
   19994         }
   19995 
   19996         mLayerType = layerType;
   19997         mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
   19998         mRenderNode.setLayerPaint(mLayerPaint);
   19999 
   20000         // draw() behaves differently if we are on a layer, so we need to
   20001         // invalidate() here
   20002         invalidateParentCaches();
   20003         invalidate(true);
   20004     }
   20005 
   20006     /**
   20007      * Updates the {@link Paint} object used with the current layer (used only if the current
   20008      * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
   20009      * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
   20010      * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
   20011      * ensure that the view gets redrawn immediately.
   20012      *
   20013      * <p>A layer is associated with an optional {@link android.graphics.Paint}
   20014      * instance that controls how the layer is composed on screen. The following
   20015      * properties of the paint are taken into account when composing the layer:</p>
   20016      * <ul>
   20017      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
   20018      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
   20019      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
   20020      * </ul>
   20021      *
   20022      * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
   20023      * alpha value of the layer's paint is superseded by this view's alpha value.</p>
   20024      *
   20025      * @param paint The paint used to compose the layer. This argument is optional
   20026      *        and can be null. It is ignored when the layer type is
   20027      *        {@link #LAYER_TYPE_NONE}
   20028      *
   20029      * @see #setLayerType(int, android.graphics.Paint)
   20030      */
   20031     public void setLayerPaint(@Nullable Paint paint) {
   20032         int layerType = getLayerType();
   20033         if (layerType != LAYER_TYPE_NONE) {
   20034             mLayerPaint = paint;
   20035             if (layerType == LAYER_TYPE_HARDWARE) {
   20036                 if (mRenderNode.setLayerPaint(paint)) {
   20037                     invalidateViewProperty(false, false);
   20038                 }
   20039             } else {
   20040                 invalidate();
   20041             }
   20042         }
   20043     }
   20044 
   20045     /**
   20046      * Indicates what type of layer is currently associated with this view. By default
   20047      * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
   20048      * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
   20049      * for more information on the different types of layers.
   20050      *
   20051      * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
   20052      *         {@link #LAYER_TYPE_HARDWARE}
   20053      *
   20054      * @see #setLayerType(int, android.graphics.Paint)
   20055      * @see #buildLayer()
   20056      * @see #LAYER_TYPE_NONE
   20057      * @see #LAYER_TYPE_SOFTWARE
   20058      * @see #LAYER_TYPE_HARDWARE
   20059      */
   20060     @InspectableProperty(enumMapping = {
   20061             @EnumEntry(value = LAYER_TYPE_NONE, name = "none"),
   20062             @EnumEntry(value = LAYER_TYPE_SOFTWARE, name = "software"),
   20063             @EnumEntry(value = LAYER_TYPE_HARDWARE, name = "hardware")
   20064     })
   20065     @LayerType
   20066     public int getLayerType() {
   20067         return mLayerType;
   20068     }
   20069 
   20070     /**
   20071      * Forces this view's layer to be created and this view to be rendered
   20072      * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
   20073      * invoking this method will have no effect.
   20074      *
   20075      * This method can for instance be used to render a view into its layer before
   20076      * starting an animation. If this view is complex, rendering into the layer
   20077      * before starting the animation will avoid skipping frames.
   20078      *
   20079      * @throws IllegalStateException If this view is not attached to a window
   20080      *
   20081      * @see #setLayerType(int, android.graphics.Paint)
   20082      */
   20083     public void buildLayer() {
   20084         if (mLayerType == LAYER_TYPE_NONE) return;
   20085 
   20086         final AttachInfo attachInfo = mAttachInfo;
   20087         if (attachInfo == null) {
   20088             throw new IllegalStateException("This view must be attached to a window first");
   20089         }
   20090 
   20091         if (getWidth() == 0 || getHeight() == 0) {
   20092             return;
   20093         }
   20094 
   20095         switch (mLayerType) {
   20096             case LAYER_TYPE_HARDWARE:
   20097                 updateDisplayListIfDirty();
   20098                 if (attachInfo.mThreadedRenderer != null && mRenderNode.hasDisplayList()) {
   20099                     attachInfo.mThreadedRenderer.buildLayer(mRenderNode);
   20100                 }
   20101                 break;
   20102             case LAYER_TYPE_SOFTWARE:
   20103                 buildDrawingCache(true);
   20104                 break;
   20105         }
   20106     }
   20107 
   20108     /**
   20109      * Destroys all hardware rendering resources. This method is invoked
   20110      * when the system needs to reclaim resources. Upon execution of this
   20111      * method, you should free any OpenGL resources created by the view.
   20112      *
   20113      * Note: you <strong>must</strong> call
   20114      * <code>super.destroyHardwareResources()</code> when overriding
   20115      * this method.
   20116      *
   20117      * @hide
   20118      */
   20119     @CallSuper
   20120     @UnsupportedAppUsage
   20121     protected void destroyHardwareResources() {
   20122         if (mOverlay != null) {
   20123             mOverlay.getOverlayView().destroyHardwareResources();
   20124         }
   20125         if (mGhostView != null) {
   20126             mGhostView.destroyHardwareResources();
   20127         }
   20128     }
   20129 
   20130     /**
   20131      * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
   20132      * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
   20133      * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
   20134      * the cache is enabled. To benefit from the cache, you must request the drawing cache by
   20135      * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
   20136      * null.</p>
   20137      *
   20138      * <p>Enabling the drawing cache is similar to
   20139      * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
   20140      * acceleration is turned off. When hardware acceleration is turned on, enabling the
   20141      * drawing cache has no effect on rendering because the system uses a different mechanism
   20142      * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
   20143      * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
   20144      * for information on how to enable software and hardware layers.</p>
   20145      *
   20146      * <p>This API can be used to manually generate
   20147      * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
   20148      * {@link #getDrawingCache()}.</p>
   20149      *
   20150      * @param enabled true to enable the drawing cache, false otherwise
   20151      *
   20152      * @see #isDrawingCacheEnabled()
   20153      * @see #getDrawingCache()
   20154      * @see #buildDrawingCache()
   20155      * @see #setLayerType(int, android.graphics.Paint)
   20156      *
   20157      * @deprecated The view drawing cache was largely made obsolete with the introduction of
   20158      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
   20159      * layers are largely unnecessary and can easily result in a net loss in performance due to the
   20160      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
   20161      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
   20162      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
   20163      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
   20164      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
   20165      * software-rendered usages are discouraged and have compatibility issues with hardware-only
   20166      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
   20167      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
   20168      * reports or unit testing the {@link PixelCopy} API is recommended.
   20169      */
   20170     @Deprecated
   20171     public void setDrawingCacheEnabled(boolean enabled) {
   20172         mCachingFailed = false;
   20173         setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
   20174     }
   20175 
   20176     /**
   20177      * <p>Indicates whether the drawing cache is enabled for this view.</p>
   20178      *
   20179      * @return true if the drawing cache is enabled
   20180      *
   20181      * @see #setDrawingCacheEnabled(boolean)
   20182      * @see #getDrawingCache()
   20183      *
   20184      * @deprecated The view drawing cache was largely made obsolete with the introduction of
   20185      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
   20186      * layers are largely unnecessary and can easily result in a net loss in performance due to the
   20187      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
   20188      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
   20189      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
   20190      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
   20191      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
   20192      * software-rendered usages are discouraged and have compatibility issues with hardware-only
   20193      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
   20194      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
   20195      * reports or unit testing the {@link PixelCopy} API is recommended.
   20196      */
   20197     @Deprecated
   20198     @ViewDebug.ExportedProperty(category = "drawing")
   20199     public boolean isDrawingCacheEnabled() {
   20200         return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
   20201     }
   20202 
   20203     /**
   20204      * Debugging utility which recursively outputs the dirty state of a view and its
   20205      * descendants.
   20206      *
   20207      * @hide
   20208      */
   20209     @SuppressWarnings({"UnusedDeclaration"})
   20210     public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
   20211         Log.d(VIEW_LOG_TAG, indent + this + "             DIRTY("
   20212                 + (mPrivateFlags & View.PFLAG_DIRTY_MASK)
   20213                 + ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID("
   20214                 + (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID)
   20215                 + ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
   20216         if (clear) {
   20217             mPrivateFlags &= clearMask;
   20218         }
   20219         if (this instanceof ViewGroup) {
   20220             ViewGroup parent = (ViewGroup) this;
   20221             final int count = parent.getChildCount();
   20222             for (int i = 0; i < count; i++) {
   20223                 final View child = parent.getChildAt(i);
   20224                 child.outputDirtyFlags(indent + "  ", clear, clearMask);
   20225             }
   20226         }
   20227     }
   20228 
   20229     /**
   20230      * This method is used by ViewGroup to cause its children to restore or recreate their
   20231      * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
   20232      * to recreate its own display list, which would happen if it went through the normal
   20233      * draw/dispatchDraw mechanisms.
   20234      *
   20235      * @hide
   20236      */
   20237     protected void dispatchGetDisplayList() {}
   20238 
   20239     /**
   20240      * A view that is not attached or hardware accelerated cannot create a display list.
   20241      * This method checks these conditions and returns the appropriate result.
   20242      *
   20243      * @return true if view has the ability to create a display list, false otherwise.
   20244      *
   20245      * @hide
   20246      */
   20247     public boolean canHaveDisplayList() {
   20248         return !(mAttachInfo == null || mAttachInfo.mThreadedRenderer == null);
   20249     }
   20250 
   20251     /**
   20252      * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
   20253      * @hide
   20254      */
   20255     @NonNull
   20256     @UnsupportedAppUsage
   20257     public RenderNode updateDisplayListIfDirty() {
   20258         final RenderNode renderNode = mRenderNode;
   20259         if (!canHaveDisplayList()) {
   20260             // can't populate RenderNode, don't try
   20261             return renderNode;
   20262         }
   20263 
   20264         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
   20265                 || !renderNode.hasDisplayList()
   20266                 || (mRecreateDisplayList)) {
   20267             // Don't need to recreate the display list, just need to tell our
   20268             // children to restore/recreate theirs
   20269             if (renderNode.hasDisplayList()
   20270                     && !mRecreateDisplayList) {
   20271                 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
   20272                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   20273                 dispatchGetDisplayList();
   20274 
   20275                 return renderNode; // no work needed
   20276             }
   20277 
   20278             // If we got here, we're recreating it. Mark it as such to ensure that
   20279             // we copy in child display lists into ours in drawChild()
   20280             mRecreateDisplayList = true;
   20281 
   20282             int width = mRight - mLeft;
   20283             int height = mBottom - mTop;
   20284             int layerType = getLayerType();
   20285 
   20286             final RecordingCanvas canvas = renderNode.beginRecording(width, height);
   20287 
   20288             try {
   20289                 if (layerType == LAYER_TYPE_SOFTWARE) {
   20290                     buildDrawingCache(true);
   20291                     Bitmap cache = getDrawingCache(true);
   20292                     if (cache != null) {
   20293                         canvas.drawBitmap(cache, 0, 0, mLayerPaint);
   20294                     }
   20295                 } else {
   20296                     computeScroll();
   20297 
   20298                     canvas.translate(-mScrollX, -mScrollY);
   20299                     mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
   20300                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   20301 
   20302                     // Fast path for layouts with no backgrounds
   20303                     if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
   20304                         dispatchDraw(canvas);
   20305                         drawAutofilledHighlight(canvas);
   20306                         if (mOverlay != null && !mOverlay.isEmpty()) {
   20307                             mOverlay.getOverlayView().draw(canvas);
   20308                         }
   20309                         if (debugDraw()) {
   20310                             debugDrawFocus(canvas);
   20311                         }
   20312                     } else {
   20313                         draw(canvas);
   20314                     }
   20315                 }
   20316             } finally {
   20317                 renderNode.endRecording();
   20318                 setDisplayListProperties(renderNode);
   20319             }
   20320         } else {
   20321             mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
   20322             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   20323         }
   20324         return renderNode;
   20325     }
   20326 
   20327     @UnsupportedAppUsage
   20328     private void resetDisplayList() {
   20329         mRenderNode.discardDisplayList();
   20330         if (mBackgroundRenderNode != null) {
   20331             mBackgroundRenderNode.discardDisplayList();
   20332         }
   20333     }
   20334 
   20335     /**
   20336      * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
   20337      *
   20338      * @return A non-scaled bitmap representing this view or null if cache is disabled.
   20339      *
   20340      * @see #getDrawingCache(boolean)
   20341      *
   20342      * @deprecated The view drawing cache was largely made obsolete with the introduction of
   20343      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
   20344      * layers are largely unnecessary and can easily result in a net loss in performance due to the
   20345      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
   20346      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
   20347      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
   20348      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
   20349      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
   20350      * software-rendered usages are discouraged and have compatibility issues with hardware-only
   20351      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
   20352      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
   20353      * reports or unit testing the {@link PixelCopy} API is recommended.
   20354      */
   20355     @Deprecated
   20356     public Bitmap getDrawingCache() {
   20357         return getDrawingCache(false);
   20358     }
   20359 
   20360     /**
   20361      * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
   20362      * is null when caching is disabled. If caching is enabled and the cache is not ready,
   20363      * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
   20364      * draw from the cache when the cache is enabled. To benefit from the cache, you must
   20365      * request the drawing cache by calling this method and draw it on screen if the
   20366      * returned bitmap is not null.</p>
   20367      *
   20368      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
   20369      * this method will create a bitmap of the same size as this view. Because this bitmap
   20370      * will be drawn scaled by the parent ViewGroup, the result on screen might show
   20371      * scaling artifacts. To avoid such artifacts, you should call this method by setting
   20372      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
   20373      * size than the view. This implies that your application must be able to handle this
   20374      * size.</p>
   20375      *
   20376      * @param autoScale Indicates whether the generated bitmap should be scaled based on
   20377      *        the current density of the screen when the application is in compatibility
   20378      *        mode.
   20379      *
   20380      * @return A bitmap representing this view or null if cache is disabled.
   20381      *
   20382      * @see #setDrawingCacheEnabled(boolean)
   20383      * @see #isDrawingCacheEnabled()
   20384      * @see #buildDrawingCache(boolean)
   20385      * @see #destroyDrawingCache()
   20386      *
   20387      * @deprecated The view drawing cache was largely made obsolete with the introduction of
   20388      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
   20389      * layers are largely unnecessary and can easily result in a net loss in performance due to the
   20390      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
   20391      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
   20392      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
   20393      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
   20394      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
   20395      * software-rendered usages are discouraged and have compatibility issues with hardware-only
   20396      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
   20397      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
   20398      * reports or unit testing the {@link PixelCopy} API is recommended.
   20399      */
   20400     @Deprecated
   20401     public Bitmap getDrawingCache(boolean autoScale) {
   20402         if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
   20403             return null;
   20404         }
   20405         if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
   20406             buildDrawingCache(autoScale);
   20407         }
   20408         return autoScale ? mDrawingCache : mUnscaledDrawingCache;
   20409     }
   20410 
   20411     /**
   20412      * <p>Frees the resources used by the drawing cache. If you call
   20413      * {@link #buildDrawingCache()} manually without calling
   20414      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
   20415      * should cleanup the cache with this method afterwards.</p>
   20416      *
   20417      * @see #setDrawingCacheEnabled(boolean)
   20418      * @see #buildDrawingCache()
   20419      * @see #getDrawingCache()
   20420      *
   20421      * @deprecated The view drawing cache was largely made obsolete with the introduction of
   20422      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
   20423      * layers are largely unnecessary and can easily result in a net loss in performance due to the
   20424      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
   20425      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
   20426      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
   20427      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
   20428      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
   20429      * software-rendered usages are discouraged and have compatibility issues with hardware-only
   20430      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
   20431      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
   20432      * reports or unit testing the {@link PixelCopy} API is recommended.
   20433      */
   20434     @Deprecated
   20435     public void destroyDrawingCache() {
   20436         if (mDrawingCache != null) {
   20437             mDrawingCache.recycle();
   20438             mDrawingCache = null;
   20439         }
   20440         if (mUnscaledDrawingCache != null) {
   20441             mUnscaledDrawingCache.recycle();
   20442             mUnscaledDrawingCache = null;
   20443         }
   20444     }
   20445 
   20446     /**
   20447      * Setting a solid background color for the drawing cache's bitmaps will improve
   20448      * performance and memory usage. Note, though that this should only be used if this
   20449      * view will always be drawn on top of a solid color.
   20450      *
   20451      * @param color The background color to use for the drawing cache's bitmap
   20452      *
   20453      * @see #setDrawingCacheEnabled(boolean)
   20454      * @see #buildDrawingCache()
   20455      * @see #getDrawingCache()
   20456      *
   20457      * @deprecated The view drawing cache was largely made obsolete with the introduction of
   20458      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
   20459      * layers are largely unnecessary and can easily result in a net loss in performance due to the
   20460      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
   20461      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
   20462      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
   20463      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
   20464      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
   20465      * software-rendered usages are discouraged and have compatibility issues with hardware-only
   20466      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
   20467      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
   20468      * reports or unit testing the {@link PixelCopy} API is recommended.
   20469      */
   20470     @Deprecated
   20471     public void setDrawingCacheBackgroundColor(@ColorInt int color) {
   20472         if (color != mDrawingCacheBackgroundColor) {
   20473             mDrawingCacheBackgroundColor = color;
   20474             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
   20475         }
   20476     }
   20477 
   20478     /**
   20479      * @see #setDrawingCacheBackgroundColor(int)
   20480      *
   20481      * @return The background color to used for the drawing cache's bitmap
   20482      *
   20483      * @deprecated The view drawing cache was largely made obsolete with the introduction of
   20484      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
   20485      * layers are largely unnecessary and can easily result in a net loss in performance due to the
   20486      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
   20487      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
   20488      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
   20489      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
   20490      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
   20491      * software-rendered usages are discouraged and have compatibility issues with hardware-only
   20492      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
   20493      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
   20494      * reports or unit testing the {@link PixelCopy} API is recommended.
   20495      */
   20496     @Deprecated
   20497     @ColorInt
   20498     public int getDrawingCacheBackgroundColor() {
   20499         return mDrawingCacheBackgroundColor;
   20500     }
   20501 
   20502     /**
   20503      * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
   20504      *
   20505      * @see #buildDrawingCache(boolean)
   20506      *
   20507      * @deprecated The view drawing cache was largely made obsolete with the introduction of
   20508      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
   20509      * layers are largely unnecessary and can easily result in a net loss in performance due to the
   20510      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
   20511      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
   20512      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
   20513      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
   20514      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
   20515      * software-rendered usages are discouraged and have compatibility issues with hardware-only
   20516      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
   20517      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
   20518      * reports or unit testing the {@link PixelCopy} API is recommended.
   20519      */
   20520     @Deprecated
   20521     public void buildDrawingCache() {
   20522         buildDrawingCache(false);
   20523     }
   20524 
   20525     /**
   20526      * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
   20527      *
   20528      * <p>If you call {@link #buildDrawingCache()} manually without calling
   20529      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
   20530      * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
   20531      *
   20532      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
   20533      * this method will create a bitmap of the same size as this view. Because this bitmap
   20534      * will be drawn scaled by the parent ViewGroup, the result on screen might show
   20535      * scaling artifacts. To avoid such artifacts, you should call this method by setting
   20536      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
   20537      * size than the view. This implies that your application must be able to handle this
   20538      * size.</p>
   20539      *
   20540      * <p>You should avoid calling this method when hardware acceleration is enabled. If
   20541      * you do not need the drawing cache bitmap, calling this method will increase memory
   20542      * usage and cause the view to be rendered in software once, thus negatively impacting
   20543      * performance.</p>
   20544      *
   20545      * @see #getDrawingCache()
   20546      * @see #destroyDrawingCache()
   20547      *
   20548      * @deprecated The view drawing cache was largely made obsolete with the introduction of
   20549      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
   20550      * layers are largely unnecessary and can easily result in a net loss in performance due to the
   20551      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
   20552      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
   20553      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
   20554      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
   20555      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
   20556      * software-rendered usages are discouraged and have compatibility issues with hardware-only
   20557      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
   20558      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
   20559      * reports or unit testing the {@link PixelCopy} API is recommended.
   20560      */
   20561     @Deprecated
   20562     public void buildDrawingCache(boolean autoScale) {
   20563         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
   20564                 mDrawingCache == null : mUnscaledDrawingCache == null)) {
   20565             if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
   20566                 Trace.traceBegin(Trace.TRACE_TAG_VIEW,
   20567                         "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
   20568             }
   20569             try {
   20570                 buildDrawingCacheImpl(autoScale);
   20571             } finally {
   20572                 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
   20573             }
   20574         }
   20575     }
   20576 
   20577     /**
   20578      * private, internal implementation of buildDrawingCache, used to enable tracing
   20579      */
   20580     private void buildDrawingCacheImpl(boolean autoScale) {
   20581         mCachingFailed = false;
   20582 
   20583         int width = mRight - mLeft;
   20584         int height = mBottom - mTop;
   20585 
   20586         final AttachInfo attachInfo = mAttachInfo;
   20587         final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
   20588 
   20589         if (autoScale && scalingRequired) {
   20590             width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
   20591             height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
   20592         }
   20593 
   20594         final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
   20595         final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
   20596         final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
   20597 
   20598         final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
   20599         final long drawingCacheSize =
   20600                 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
   20601         if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
   20602             if (width > 0 && height > 0) {
   20603                 Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
   20604                         + " too large to fit into a software layer (or drawing cache), needs "
   20605                         + projectedBitmapSize + " bytes, only "
   20606                         + drawingCacheSize + " available");
   20607             }
   20608             destroyDrawingCache();
   20609             mCachingFailed = true;
   20610             return;
   20611         }
   20612 
   20613         boolean clear = true;
   20614         Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
   20615 
   20616         if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
   20617             Bitmap.Config quality;
   20618             if (!opaque) {
   20619                 // Never pick ARGB_4444 because it looks awful
   20620                 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
   20621                 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
   20622                     case DRAWING_CACHE_QUALITY_AUTO:
   20623                     case DRAWING_CACHE_QUALITY_LOW:
   20624                     case DRAWING_CACHE_QUALITY_HIGH:
   20625                     default:
   20626                         quality = Bitmap.Config.ARGB_8888;
   20627                         break;
   20628                 }
   20629             } else {
   20630                 // Optimization for translucent windows
   20631                 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
   20632                 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
   20633             }
   20634 
   20635             // Try to cleanup memory
   20636             if (bitmap != null) bitmap.recycle();
   20637 
   20638             try {
   20639                 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
   20640                         width, height, quality);
   20641                 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
   20642                 if (autoScale) {
   20643                     mDrawingCache = bitmap;
   20644                 } else {
   20645                     mUnscaledDrawingCache = bitmap;
   20646                 }
   20647                 if (opaque && use32BitCache) bitmap.setHasAlpha(false);
   20648             } catch (OutOfMemoryError e) {
   20649                 // If there is not enough memory to create the bitmap cache, just
   20650                 // ignore the issue as bitmap caches are not required to draw the
   20651                 // view hierarchy
   20652                 if (autoScale) {
   20653                     mDrawingCache = null;
   20654                 } else {
   20655                     mUnscaledDrawingCache = null;
   20656                 }
   20657                 mCachingFailed = true;
   20658                 return;
   20659             }
   20660 
   20661             clear = drawingCacheBackgroundColor != 0;
   20662         }
   20663 
   20664         Canvas canvas;
   20665         if (attachInfo != null) {
   20666             canvas = attachInfo.mCanvas;
   20667             if (canvas == null) {
   20668                 canvas = new Canvas();
   20669             }
   20670             canvas.setBitmap(bitmap);
   20671             // Temporarily clobber the cached Canvas in case one of our children
   20672             // is also using a drawing cache. Without this, the children would
   20673             // steal the canvas by attaching their own bitmap to it and bad, bad
   20674             // thing would happen (invisible views, corrupted drawings, etc.)
   20675             attachInfo.mCanvas = null;
   20676         } else {
   20677             // This case should hopefully never or seldom happen
   20678             canvas = new Canvas(bitmap);
   20679         }
   20680 
   20681         if (clear) {
   20682             bitmap.eraseColor(drawingCacheBackgroundColor);
   20683         }
   20684 
   20685         computeScroll();
   20686         final int restoreCount = canvas.save();
   20687 
   20688         if (autoScale && scalingRequired) {
   20689             final float scale = attachInfo.mApplicationScale;
   20690             canvas.scale(scale, scale);
   20691         }
   20692 
   20693         canvas.translate(-mScrollX, -mScrollY);
   20694 
   20695         mPrivateFlags |= PFLAG_DRAWN;
   20696         if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
   20697                 mLayerType != LAYER_TYPE_NONE) {
   20698             mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
   20699         }
   20700 
   20701         // Fast path for layouts with no backgrounds
   20702         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
   20703             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   20704             dispatchDraw(canvas);
   20705             drawAutofilledHighlight(canvas);
   20706             if (mOverlay != null && !mOverlay.isEmpty()) {
   20707                 mOverlay.getOverlayView().draw(canvas);
   20708             }
   20709         } else {
   20710             draw(canvas);
   20711         }
   20712 
   20713         canvas.restoreToCount(restoreCount);
   20714         canvas.setBitmap(null);
   20715 
   20716         if (attachInfo != null) {
   20717             // Restore the cached Canvas for our siblings
   20718             attachInfo.mCanvas = canvas;
   20719         }
   20720     }
   20721 
   20722     /**
   20723      * Create a snapshot of the view into a bitmap.  We should probably make
   20724      * some form of this public, but should think about the API.
   20725      *
   20726      * @hide
   20727      */
   20728     @UnsupportedAppUsage
   20729     public Bitmap createSnapshot(ViewDebug.CanvasProvider canvasProvider, boolean skipChildren) {
   20730         int width = mRight - mLeft;
   20731         int height = mBottom - mTop;
   20732 
   20733         final AttachInfo attachInfo = mAttachInfo;
   20734         final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
   20735         width = (int) ((width * scale) + 0.5f);
   20736         height = (int) ((height * scale) + 0.5f);
   20737 
   20738         Canvas oldCanvas = null;
   20739         try {
   20740             Canvas canvas = canvasProvider.getCanvas(this,
   20741                     width > 0 ? width : 1, height > 0 ? height : 1);
   20742 
   20743             if (attachInfo != null) {
   20744                 oldCanvas = attachInfo.mCanvas;
   20745                 // Temporarily clobber the cached Canvas in case one of our children
   20746                 // is also using a drawing cache. Without this, the children would
   20747                 // steal the canvas by attaching their own bitmap to it and bad, bad
   20748                 // things would happen (invisible views, corrupted drawings, etc.)
   20749                 attachInfo.mCanvas = null;
   20750             }
   20751 
   20752             computeScroll();
   20753             final int restoreCount = canvas.save();
   20754             canvas.scale(scale, scale);
   20755             canvas.translate(-mScrollX, -mScrollY);
   20756 
   20757             // Temporarily remove the dirty mask
   20758             int flags = mPrivateFlags;
   20759             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   20760 
   20761             // Fast path for layouts with no backgrounds
   20762             if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
   20763                 dispatchDraw(canvas);
   20764                 drawAutofilledHighlight(canvas);
   20765                 if (mOverlay != null && !mOverlay.isEmpty()) {
   20766                     mOverlay.getOverlayView().draw(canvas);
   20767                 }
   20768             } else {
   20769                 draw(canvas);
   20770             }
   20771 
   20772             mPrivateFlags = flags;
   20773             canvas.restoreToCount(restoreCount);
   20774             return canvasProvider.createBitmap();
   20775         } finally {
   20776             if (oldCanvas != null) {
   20777                 attachInfo.mCanvas = oldCanvas;
   20778             }
   20779         }
   20780     }
   20781 
   20782     /**
   20783      * Indicates whether this View is currently in edit mode. A View is usually
   20784      * in edit mode when displayed within a developer tool. For instance, if
   20785      * this View is being drawn by a visual user interface builder, this method
   20786      * should return true.
   20787      *
   20788      * Subclasses should check the return value of this method to provide
   20789      * different behaviors if their normal behavior might interfere with the
   20790      * host environment. For instance: the class spawns a thread in its
   20791      * constructor, the drawing code relies on device-specific features, etc.
   20792      *
   20793      * This method is usually checked in the drawing code of custom widgets.
   20794      *
   20795      * @return True if this View is in edit mode, false otherwise.
   20796      */
   20797     public boolean isInEditMode() {
   20798         return false;
   20799     }
   20800 
   20801     /**
   20802      * If the View draws content inside its padding and enables fading edges,
   20803      * it needs to support padding offsets. Padding offsets are added to the
   20804      * fading edges to extend the length of the fade so that it covers pixels
   20805      * drawn inside the padding.
   20806      *
   20807      * Subclasses of this class should override this method if they need
   20808      * to draw content inside the padding.
   20809      *
   20810      * @return True if padding offset must be applied, false otherwise.
   20811      *
   20812      * @see #getLeftPaddingOffset()
   20813      * @see #getRightPaddingOffset()
   20814      * @see #getTopPaddingOffset()
   20815      * @see #getBottomPaddingOffset()
   20816      *
   20817      * @since CURRENT
   20818      */
   20819     protected boolean isPaddingOffsetRequired() {
   20820         return false;
   20821     }
   20822 
   20823     /**
   20824      * Amount by which to extend the left fading region. Called only when
   20825      * {@link #isPaddingOffsetRequired()} returns true.
   20826      *
   20827      * @return The left padding offset in pixels.
   20828      *
   20829      * @see #isPaddingOffsetRequired()
   20830      *
   20831      * @since CURRENT
   20832      */
   20833     protected int getLeftPaddingOffset() {
   20834         return 0;
   20835     }
   20836 
   20837     /**
   20838      * Amount by which to extend the right fading region. Called only when
   20839      * {@link #isPaddingOffsetRequired()} returns true.
   20840      *
   20841      * @return The right padding offset in pixels.
   20842      *
   20843      * @see #isPaddingOffsetRequired()
   20844      *
   20845      * @since CURRENT
   20846      */
   20847     protected int getRightPaddingOffset() {
   20848         return 0;
   20849     }
   20850 
   20851     /**
   20852      * Amount by which to extend the top fading region. Called only when
   20853      * {@link #isPaddingOffsetRequired()} returns true.
   20854      *
   20855      * @return The top padding offset in pixels.
   20856      *
   20857      * @see #isPaddingOffsetRequired()
   20858      *
   20859      * @since CURRENT
   20860      */
   20861     protected int getTopPaddingOffset() {
   20862         return 0;
   20863     }
   20864 
   20865     /**
   20866      * Amount by which to extend the bottom fading region. Called only when
   20867      * {@link #isPaddingOffsetRequired()} returns true.
   20868      *
   20869      * @return The bottom padding offset in pixels.
   20870      *
   20871      * @see #isPaddingOffsetRequired()
   20872      *
   20873      * @since CURRENT
   20874      */
   20875     protected int getBottomPaddingOffset() {
   20876         return 0;
   20877     }
   20878 
   20879     /**
   20880      * @hide
   20881      * @param offsetRequired
   20882      */
   20883     protected int getFadeTop(boolean offsetRequired) {
   20884         int top = mPaddingTop;
   20885         if (offsetRequired) top += getTopPaddingOffset();
   20886         return top;
   20887     }
   20888 
   20889     /**
   20890      * @hide
   20891      * @param offsetRequired
   20892      */
   20893     protected int getFadeHeight(boolean offsetRequired) {
   20894         int padding = mPaddingTop;
   20895         if (offsetRequired) padding += getTopPaddingOffset();
   20896         return mBottom - mTop - mPaddingBottom - padding;
   20897     }
   20898 
   20899     /**
   20900      * <p>Indicates whether this view is attached to a hardware accelerated
   20901      * window or not.</p>
   20902      *
   20903      * <p>Even if this method returns true, it does not mean that every call
   20904      * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
   20905      * accelerated {@link android.graphics.Canvas}. For instance, if this view
   20906      * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
   20907      * window is hardware accelerated,
   20908      * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
   20909      * return false, and this method will return true.</p>
   20910      *
   20911      * @return True if the view is attached to a window and the window is
   20912      *         hardware accelerated; false in any other case.
   20913      */
   20914     @ViewDebug.ExportedProperty(category = "drawing")
   20915     public boolean isHardwareAccelerated() {
   20916         return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
   20917     }
   20918 
   20919     /**
   20920      * Sets a rectangular area on this view to which the view will be clipped
   20921      * when it is drawn. Setting the value to null will remove the clip bounds
   20922      * and the view will draw normally, using its full bounds.
   20923      *
   20924      * @param clipBounds The rectangular area, in the local coordinates of
   20925      * this view, to which future drawing operations will be clipped.
   20926      */
   20927     public void setClipBounds(Rect clipBounds) {
   20928         if (clipBounds == mClipBounds
   20929                 || (clipBounds != null && clipBounds.equals(mClipBounds))) {
   20930             return;
   20931         }
   20932         if (clipBounds != null) {
   20933             if (mClipBounds == null) {
   20934                 mClipBounds = new Rect(clipBounds);
   20935             } else {
   20936                 mClipBounds.set(clipBounds);
   20937             }
   20938         } else {
   20939             mClipBounds = null;
   20940         }
   20941         mRenderNode.setClipRect(mClipBounds);
   20942         invalidateViewProperty(false, false);
   20943     }
   20944 
   20945     /**
   20946      * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
   20947      *
   20948      * @return A copy of the current clip bounds if clip bounds are set,
   20949      * otherwise null.
   20950      */
   20951     public Rect getClipBounds() {
   20952         return (mClipBounds != null) ? new Rect(mClipBounds) : null;
   20953     }
   20954 
   20955 
   20956     /**
   20957      * Populates an output rectangle with the clip bounds of the view,
   20958      * returning {@code true} if successful or {@code false} if the view's
   20959      * clip bounds are {@code null}.
   20960      *
   20961      * @param outRect rectangle in which to place the clip bounds of the view
   20962      * @return {@code true} if successful or {@code false} if the view's
   20963      *         clip bounds are {@code null}
   20964      */
   20965     public boolean getClipBounds(Rect outRect) {
   20966         if (mClipBounds != null) {
   20967             outRect.set(mClipBounds);
   20968             return true;
   20969         }
   20970         return false;
   20971     }
   20972 
   20973     /**
   20974      * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
   20975      * case of an active Animation being run on the view.
   20976      */
   20977     private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
   20978             Animation a, boolean scalingRequired) {
   20979         Transformation invalidationTransform;
   20980         final int flags = parent.mGroupFlags;
   20981         final boolean initialized = a.isInitialized();
   20982         if (!initialized) {
   20983             a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
   20984             a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
   20985             if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
   20986             onAnimationStart();
   20987         }
   20988 
   20989         final Transformation t = parent.getChildTransformation();
   20990         boolean more = a.getTransformation(drawingTime, t, 1f);
   20991         if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
   20992             if (parent.mInvalidationTransformation == null) {
   20993                 parent.mInvalidationTransformation = new Transformation();
   20994             }
   20995             invalidationTransform = parent.mInvalidationTransformation;
   20996             a.getTransformation(drawingTime, invalidationTransform, 1f);
   20997         } else {
   20998             invalidationTransform = t;
   20999         }
   21000 
   21001         if (more) {
   21002             if (!a.willChangeBounds()) {
   21003                 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
   21004                         ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
   21005                     parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
   21006                 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
   21007                     // The child need to draw an animation, potentially offscreen, so
   21008                     // make sure we do not cancel invalidate requests
   21009                     parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
   21010                     parent.invalidate(mLeft, mTop, mRight, mBottom);
   21011                 }
   21012             } else {
   21013                 if (parent.mInvalidateRegion == null) {
   21014                     parent.mInvalidateRegion = new RectF();
   21015                 }
   21016                 final RectF region = parent.mInvalidateRegion;
   21017                 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
   21018                         invalidationTransform);
   21019 
   21020                 // The child need to draw an animation, potentially offscreen, so
   21021                 // make sure we do not cancel invalidate requests
   21022                 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
   21023 
   21024                 final int left = mLeft + (int) region.left;
   21025                 final int top = mTop + (int) region.top;
   21026                 parent.invalidate(left, top, left + (int) (region.width() + .5f),
   21027                         top + (int) (region.height() + .5f));
   21028             }
   21029         }
   21030         return more;
   21031     }
   21032 
   21033     /**
   21034      * This method is called by getDisplayList() when a display list is recorded for a View.
   21035      * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
   21036      */
   21037     void setDisplayListProperties(RenderNode renderNode) {
   21038         if (renderNode != null) {
   21039             renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
   21040             renderNode.setClipToBounds(mParent instanceof ViewGroup
   21041                     && ((ViewGroup) mParent).getClipChildren());
   21042 
   21043             float alpha = 1;
   21044             if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
   21045                     ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
   21046                 ViewGroup parentVG = (ViewGroup) mParent;
   21047                 final Transformation t = parentVG.getChildTransformation();
   21048                 if (parentVG.getChildStaticTransformation(this, t)) {
   21049                     final int transformType = t.getTransformationType();
   21050                     if (transformType != Transformation.TYPE_IDENTITY) {
   21051                         if ((transformType & Transformation.TYPE_ALPHA) != 0) {
   21052                             alpha = t.getAlpha();
   21053                         }
   21054                         if ((transformType & Transformation.TYPE_MATRIX) != 0) {
   21055                             renderNode.setStaticMatrix(t.getMatrix());
   21056                         }
   21057                     }
   21058                 }
   21059             }
   21060             if (mTransformationInfo != null) {
   21061                 alpha *= getFinalAlpha();
   21062                 if (alpha < 1) {
   21063                     final int multipliedAlpha = (int) (255 * alpha);
   21064                     if (onSetAlpha(multipliedAlpha)) {
   21065                         alpha = 1;
   21066                     }
   21067                 }
   21068                 renderNode.setAlpha(alpha);
   21069             } else if (alpha < 1) {
   21070                 renderNode.setAlpha(alpha);
   21071             }
   21072         }
   21073     }
   21074 
   21075     /**
   21076      * This method is called by ViewGroup.drawChild() to have each child view draw itself.
   21077      *
   21078      * This is where the View specializes rendering behavior based on layer type,
   21079      * and hardware acceleration.
   21080      */
   21081     boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
   21082         final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
   21083         /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
   21084          *
   21085          * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
   21086          * HW accelerated, it can't handle drawing RenderNodes.
   21087          */
   21088         boolean drawingWithRenderNode = mAttachInfo != null
   21089                 && mAttachInfo.mHardwareAccelerated
   21090                 && hardwareAcceleratedCanvas;
   21091 
   21092         boolean more = false;
   21093         final boolean childHasIdentityMatrix = hasIdentityMatrix();
   21094         final int parentFlags = parent.mGroupFlags;
   21095 
   21096         if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
   21097             parent.getChildTransformation().clear();
   21098             parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
   21099         }
   21100 
   21101         Transformation transformToApply = null;
   21102         boolean concatMatrix = false;
   21103         final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
   21104         final Animation a = getAnimation();
   21105         if (a != null) {
   21106             more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
   21107             concatMatrix = a.willChangeTransformationMatrix();
   21108             if (concatMatrix) {
   21109                 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
   21110             }
   21111             transformToApply = parent.getChildTransformation();
   21112         } else {
   21113             if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
   21114                 // No longer animating: clear out old animation matrix
   21115                 mRenderNode.setAnimationMatrix(null);
   21116                 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
   21117             }
   21118             if (!drawingWithRenderNode
   21119                     && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
   21120                 final Transformation t = parent.getChildTransformation();
   21121                 final boolean hasTransform = parent.getChildStaticTransformation(this, t);
   21122                 if (hasTransform) {
   21123                     final int transformType = t.getTransformationType();
   21124                     transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
   21125                     concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
   21126                 }
   21127             }
   21128         }
   21129 
   21130         concatMatrix |= !childHasIdentityMatrix;
   21131 
   21132         // Sets the flag as early as possible to allow draw() implementations
   21133         // to call invalidate() successfully when doing animations
   21134         mPrivateFlags |= PFLAG_DRAWN;
   21135 
   21136         if (!concatMatrix &&
   21137                 (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
   21138                         ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
   21139                 canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
   21140                 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
   21141             mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
   21142             return more;
   21143         }
   21144         mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
   21145 
   21146         if (hardwareAcceleratedCanvas) {
   21147             // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
   21148             // retain the flag's value temporarily in the mRecreateDisplayList flag
   21149             mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
   21150             mPrivateFlags &= ~PFLAG_INVALIDATED;
   21151         }
   21152 
   21153         RenderNode renderNode = null;
   21154         Bitmap cache = null;
   21155         int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
   21156         if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
   21157              if (layerType != LAYER_TYPE_NONE) {
   21158                  // If not drawing with RenderNode, treat HW layers as SW
   21159                  layerType = LAYER_TYPE_SOFTWARE;
   21160                  buildDrawingCache(true);
   21161             }
   21162             cache = getDrawingCache(true);
   21163         }
   21164 
   21165         if (drawingWithRenderNode) {
   21166             // Delay getting the display list until animation-driven alpha values are
   21167             // set up and possibly passed on to the view
   21168             renderNode = updateDisplayListIfDirty();
   21169             if (!renderNode.hasDisplayList()) {
   21170                 // Uncommon, but possible. If a view is removed from the hierarchy during the call
   21171                 // to getDisplayList(), the display list will be marked invalid and we should not
   21172                 // try to use it again.
   21173                 renderNode = null;
   21174                 drawingWithRenderNode = false;
   21175             }
   21176         }
   21177 
   21178         int sx = 0;
   21179         int sy = 0;
   21180         if (!drawingWithRenderNode) {
   21181             computeScroll();
   21182             sx = mScrollX;
   21183             sy = mScrollY;
   21184         }
   21185 
   21186         final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
   21187         final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
   21188 
   21189         int restoreTo = -1;
   21190         if (!drawingWithRenderNode || transformToApply != null) {
   21191             restoreTo = canvas.save();
   21192         }
   21193         if (offsetForScroll) {
   21194             canvas.translate(mLeft - sx, mTop - sy);
   21195         } else {
   21196             if (!drawingWithRenderNode) {
   21197                 canvas.translate(mLeft, mTop);
   21198             }
   21199             if (scalingRequired) {
   21200                 if (drawingWithRenderNode) {
   21201                     // TODO: Might not need this if we put everything inside the DL
   21202                     restoreTo = canvas.save();
   21203                 }
   21204                 // mAttachInfo cannot be null, otherwise scalingRequired == false
   21205                 final float scale = 1.0f / mAttachInfo.mApplicationScale;
   21206                 canvas.scale(scale, scale);
   21207             }
   21208         }
   21209 
   21210         float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
   21211         if (transformToApply != null
   21212                 || alpha < 1
   21213                 || !hasIdentityMatrix()
   21214                 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
   21215             if (transformToApply != null || !childHasIdentityMatrix) {
   21216                 int transX = 0;
   21217                 int transY = 0;
   21218 
   21219                 if (offsetForScroll) {
   21220                     transX = -sx;
   21221                     transY = -sy;
   21222                 }
   21223 
   21224                 if (transformToApply != null) {
   21225                     if (concatMatrix) {
   21226                         if (drawingWithRenderNode) {
   21227                             renderNode.setAnimationMatrix(transformToApply.getMatrix());
   21228                         } else {
   21229                             // Undo the scroll translation, apply the transformation matrix,
   21230                             // then redo the scroll translate to get the correct result.
   21231                             canvas.translate(-transX, -transY);
   21232                             canvas.concat(transformToApply.getMatrix());
   21233                             canvas.translate(transX, transY);
   21234                         }
   21235                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
   21236                     }
   21237 
   21238                     float transformAlpha = transformToApply.getAlpha();
   21239                     if (transformAlpha < 1) {
   21240                         alpha *= transformAlpha;
   21241                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
   21242                     }
   21243                 }
   21244 
   21245                 if (!childHasIdentityMatrix && !drawingWithRenderNode) {
   21246                     canvas.translate(-transX, -transY);
   21247                     canvas.concat(getMatrix());
   21248                     canvas.translate(transX, transY);
   21249                 }
   21250             }
   21251 
   21252             // Deal with alpha if it is or used to be <1
   21253             if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
   21254                 if (alpha < 1) {
   21255                     mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
   21256                 } else {
   21257                     mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
   21258                 }
   21259                 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
   21260                 if (!drawingWithDrawingCache) {
   21261                     final int multipliedAlpha = (int) (255 * alpha);
   21262                     if (!onSetAlpha(multipliedAlpha)) {
   21263                         if (drawingWithRenderNode) {
   21264                             renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
   21265                         } else if (layerType == LAYER_TYPE_NONE) {
   21266                             canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
   21267                                     multipliedAlpha);
   21268                         }
   21269                     } else {
   21270                         // Alpha is handled by the child directly, clobber the layer's alpha
   21271                         mPrivateFlags |= PFLAG_ALPHA_SET;
   21272                     }
   21273                 }
   21274             }
   21275         } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
   21276             onSetAlpha(255);
   21277             mPrivateFlags &= ~PFLAG_ALPHA_SET;
   21278         }
   21279 
   21280         if (!drawingWithRenderNode) {
   21281             // apply clips directly, since RenderNode won't do it for this draw
   21282             if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
   21283                 if (offsetForScroll) {
   21284                     canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
   21285                 } else {
   21286                     if (!scalingRequired || cache == null) {
   21287                         canvas.clipRect(0, 0, getWidth(), getHeight());
   21288                     } else {
   21289                         canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
   21290                     }
   21291                 }
   21292             }
   21293 
   21294             if (mClipBounds != null) {
   21295                 // clip bounds ignore scroll
   21296                 canvas.clipRect(mClipBounds);
   21297             }
   21298         }
   21299 
   21300         if (!drawingWithDrawingCache) {
   21301             if (drawingWithRenderNode) {
   21302                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   21303                 ((RecordingCanvas) canvas).drawRenderNode(renderNode);
   21304             } else {
   21305                 // Fast path for layouts with no backgrounds
   21306                 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
   21307                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   21308                     dispatchDraw(canvas);
   21309                 } else {
   21310                     draw(canvas);
   21311                 }
   21312             }
   21313         } else if (cache != null) {
   21314             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   21315             if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
   21316                 // no layer paint, use temporary paint to draw bitmap
   21317                 Paint cachePaint = parent.mCachePaint;
   21318                 if (cachePaint == null) {
   21319                     cachePaint = new Paint();
   21320                     cachePaint.setDither(false);
   21321                     parent.mCachePaint = cachePaint;
   21322                 }
   21323                 cachePaint.setAlpha((int) (alpha * 255));
   21324                 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
   21325             } else {
   21326                 // use layer paint to draw the bitmap, merging the two alphas, but also restore
   21327                 int layerPaintAlpha = mLayerPaint.getAlpha();
   21328                 if (alpha < 1) {
   21329                     mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
   21330                 }
   21331                 canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
   21332                 if (alpha < 1) {
   21333                     mLayerPaint.setAlpha(layerPaintAlpha);
   21334                 }
   21335             }
   21336         }
   21337 
   21338         if (restoreTo >= 0) {
   21339             canvas.restoreToCount(restoreTo);
   21340         }
   21341 
   21342         if (a != null && !more) {
   21343             if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
   21344                 onSetAlpha(255);
   21345             }
   21346             parent.finishAnimatingView(this, a);
   21347         }
   21348 
   21349         if (more && hardwareAcceleratedCanvas) {
   21350             if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
   21351                 // alpha animations should cause the child to recreate its display list
   21352                 invalidate(true);
   21353             }
   21354         }
   21355 
   21356         mRecreateDisplayList = false;
   21357 
   21358         return more;
   21359     }
   21360 
   21361     static Paint getDebugPaint() {
   21362         if (sDebugPaint == null) {
   21363             sDebugPaint = new Paint();
   21364             sDebugPaint.setAntiAlias(false);
   21365         }
   21366         return sDebugPaint;
   21367     }
   21368 
   21369     final int dipsToPixels(int dips) {
   21370         float scale = getContext().getResources().getDisplayMetrics().density;
   21371         return (int) (dips * scale + 0.5f);
   21372     }
   21373 
   21374     final private void debugDrawFocus(Canvas canvas) {
   21375         if (isFocused()) {
   21376             final int cornerSquareSize = dipsToPixels(DEBUG_CORNERS_SIZE_DIP);
   21377             final int l = mScrollX;
   21378             final int r = l + mRight - mLeft;
   21379             final int t = mScrollY;
   21380             final int b = t + mBottom - mTop;
   21381 
   21382             final Paint paint = getDebugPaint();
   21383             paint.setColor(DEBUG_CORNERS_COLOR);
   21384 
   21385             // Draw squares in corners.
   21386             paint.setStyle(Paint.Style.FILL);
   21387             canvas.drawRect(l, t, l + cornerSquareSize, t + cornerSquareSize, paint);
   21388             canvas.drawRect(r - cornerSquareSize, t, r, t + cornerSquareSize, paint);
   21389             canvas.drawRect(l, b - cornerSquareSize, l + cornerSquareSize, b, paint);
   21390             canvas.drawRect(r - cornerSquareSize, b - cornerSquareSize, r, b, paint);
   21391 
   21392             // Draw big X across the view.
   21393             paint.setStyle(Paint.Style.STROKE);
   21394             canvas.drawLine(l, t, r, b, paint);
   21395             canvas.drawLine(l, b, r, t, paint);
   21396         }
   21397     }
   21398 
   21399     /**
   21400      * Manually render this view (and all of its children) to the given Canvas.
   21401      * The view must have already done a full layout before this function is
   21402      * called.  When implementing a view, implement
   21403      * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
   21404      * If you do need to override this method, call the superclass version.
   21405      *
   21406      * @param canvas The Canvas to which the View is rendered.
   21407      */
   21408     @CallSuper
   21409     public void draw(Canvas canvas) {
   21410         final int privateFlags = mPrivateFlags;
   21411         mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
   21412 
   21413         /*
   21414          * Draw traversal performs several drawing steps which must be executed
   21415          * in the appropriate order:
   21416          *
   21417          *      1. Draw the background
   21418          *      2. If necessary, save the canvas' layers to prepare for fading
   21419          *      3. Draw view's content
   21420          *      4. Draw children
   21421          *      5. If necessary, draw the fading edges and restore layers
   21422          *      6. Draw decorations (scrollbars for instance)
   21423          */
   21424 
   21425         // Step 1, draw the background, if needed
   21426         int saveCount;
   21427 
   21428         drawBackground(canvas);
   21429 
   21430         // skip step 2 & 5 if possible (common case)
   21431         final int viewFlags = mViewFlags;
   21432         boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
   21433         boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
   21434         if (!verticalEdges && !horizontalEdges) {
   21435             // Step 3, draw the content
   21436             onDraw(canvas);
   21437 
   21438             // Step 4, draw the children
   21439             dispatchDraw(canvas);
   21440 
   21441             drawAutofilledHighlight(canvas);
   21442 
   21443             // Overlay is part of the content and draws beneath Foreground
   21444             if (mOverlay != null && !mOverlay.isEmpty()) {
   21445                 mOverlay.getOverlayView().dispatchDraw(canvas);
   21446             }
   21447 
   21448             // Step 6, draw decorations (foreground, scrollbars)
   21449             onDrawForeground(canvas);
   21450 
   21451             // Step 7, draw the default focus highlight
   21452             drawDefaultFocusHighlight(canvas);
   21453 
   21454             if (debugDraw()) {
   21455                 debugDrawFocus(canvas);
   21456             }
   21457 
   21458             // we're done...
   21459             return;
   21460         }
   21461 
   21462         /*
   21463          * Here we do the full fledged routine...
   21464          * (this is an uncommon case where speed matters less,
   21465          * this is why we repeat some of the tests that have been
   21466          * done above)
   21467          */
   21468 
   21469         boolean drawTop = false;
   21470         boolean drawBottom = false;
   21471         boolean drawLeft = false;
   21472         boolean drawRight = false;
   21473 
   21474         float topFadeStrength = 0.0f;
   21475         float bottomFadeStrength = 0.0f;
   21476         float leftFadeStrength = 0.0f;
   21477         float rightFadeStrength = 0.0f;
   21478 
   21479         // Step 2, save the canvas' layers
   21480         int paddingLeft = mPaddingLeft;
   21481 
   21482         final boolean offsetRequired = isPaddingOffsetRequired();
   21483         if (offsetRequired) {
   21484             paddingLeft += getLeftPaddingOffset();
   21485         }
   21486 
   21487         int left = mScrollX + paddingLeft;
   21488         int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
   21489         int top = mScrollY + getFadeTop(offsetRequired);
   21490         int bottom = top + getFadeHeight(offsetRequired);
   21491 
   21492         if (offsetRequired) {
   21493             right += getRightPaddingOffset();
   21494             bottom += getBottomPaddingOffset();
   21495         }
   21496 
   21497         final ScrollabilityCache scrollabilityCache = mScrollCache;
   21498         final float fadeHeight = scrollabilityCache.fadingEdgeLength;
   21499         int length = (int) fadeHeight;
   21500 
   21501         // clip the fade length if top and bottom fades overlap
   21502         // overlapping fades produce odd-looking artifacts
   21503         if (verticalEdges && (top + length > bottom - length)) {
   21504             length = (bottom - top) / 2;
   21505         }
   21506 
   21507         // also clip horizontal fades if necessary
   21508         if (horizontalEdges && (left + length > right - length)) {
   21509             length = (right - left) / 2;
   21510         }
   21511 
   21512         if (verticalEdges) {
   21513             topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
   21514             drawTop = topFadeStrength * fadeHeight > 1.0f;
   21515             bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
   21516             drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
   21517         }
   21518 
   21519         if (horizontalEdges) {
   21520             leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
   21521             drawLeft = leftFadeStrength * fadeHeight > 1.0f;
   21522             rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
   21523             drawRight = rightFadeStrength * fadeHeight > 1.0f;
   21524         }
   21525 
   21526         saveCount = canvas.getSaveCount();
   21527         int topSaveCount = -1;
   21528         int bottomSaveCount = -1;
   21529         int leftSaveCount = -1;
   21530         int rightSaveCount = -1;
   21531 
   21532         int solidColor = getSolidColor();
   21533         if (solidColor == 0) {
   21534             if (drawTop) {
   21535                 topSaveCount = canvas.saveUnclippedLayer(left, top, right, top + length);
   21536             }
   21537 
   21538             if (drawBottom) {
   21539                 bottomSaveCount = canvas.saveUnclippedLayer(left, bottom - length, right, bottom);
   21540             }
   21541 
   21542             if (drawLeft) {
   21543                 leftSaveCount = canvas.saveUnclippedLayer(left, top, left + length, bottom);
   21544             }
   21545 
   21546             if (drawRight) {
   21547                 rightSaveCount = canvas.saveUnclippedLayer(right - length, top, right, bottom);
   21548             }
   21549         } else {
   21550             scrollabilityCache.setFadeColor(solidColor);
   21551         }
   21552 
   21553         // Step 3, draw the content
   21554         onDraw(canvas);
   21555 
   21556         // Step 4, draw the children
   21557         dispatchDraw(canvas);
   21558 
   21559         // Step 5, draw the fade effect and restore layers
   21560         final Paint p = scrollabilityCache.paint;
   21561         final Matrix matrix = scrollabilityCache.matrix;
   21562         final Shader fade = scrollabilityCache.shader;
   21563 
   21564         // must be restored in the reverse order that they were saved
   21565         if (drawRight) {
   21566             matrix.setScale(1, fadeHeight * rightFadeStrength);
   21567             matrix.postRotate(90);
   21568             matrix.postTranslate(right, top);
   21569             fade.setLocalMatrix(matrix);
   21570             p.setShader(fade);
   21571             if (solidColor == 0) {
   21572                 canvas.restoreUnclippedLayer(rightSaveCount, p);
   21573 
   21574             } else {
   21575                 canvas.drawRect(right - length, top, right, bottom, p);
   21576             }
   21577         }
   21578 
   21579         if (drawLeft) {
   21580             matrix.setScale(1, fadeHeight * leftFadeStrength);
   21581             matrix.postRotate(-90);
   21582             matrix.postTranslate(left, top);
   21583             fade.setLocalMatrix(matrix);
   21584             p.setShader(fade);
   21585             if (solidColor == 0) {
   21586                 canvas.restoreUnclippedLayer(leftSaveCount, p);
   21587             } else {
   21588                 canvas.drawRect(left, top, left + length, bottom, p);
   21589             }
   21590         }
   21591 
   21592         if (drawBottom) {
   21593             matrix.setScale(1, fadeHeight * bottomFadeStrength);
   21594             matrix.postRotate(180);
   21595             matrix.postTranslate(left, bottom);
   21596             fade.setLocalMatrix(matrix);
   21597             p.setShader(fade);
   21598             if (solidColor == 0) {
   21599                 canvas.restoreUnclippedLayer(bottomSaveCount, p);
   21600             } else {
   21601                 canvas.drawRect(left, bottom - length, right, bottom, p);
   21602             }
   21603         }
   21604 
   21605         if (drawTop) {
   21606             matrix.setScale(1, fadeHeight * topFadeStrength);
   21607             matrix.postTranslate(left, top);
   21608             fade.setLocalMatrix(matrix);
   21609             p.setShader(fade);
   21610             if (solidColor == 0) {
   21611                 canvas.restoreUnclippedLayer(topSaveCount, p);
   21612             } else {
   21613                 canvas.drawRect(left, top, right, top + length, p);
   21614             }
   21615         }
   21616 
   21617         canvas.restoreToCount(saveCount);
   21618 
   21619         drawAutofilledHighlight(canvas);
   21620 
   21621         // Overlay is part of the content and draws beneath Foreground
   21622         if (mOverlay != null && !mOverlay.isEmpty()) {
   21623             mOverlay.getOverlayView().dispatchDraw(canvas);
   21624         }
   21625 
   21626         // Step 6, draw decorations (foreground, scrollbars)
   21627         onDrawForeground(canvas);
   21628 
   21629         if (debugDraw()) {
   21630             debugDrawFocus(canvas);
   21631         }
   21632     }
   21633 
   21634     /**
   21635      * Draws the background onto the specified canvas.
   21636      *
   21637      * @param canvas Canvas on which to draw the background
   21638      */
   21639     @UnsupportedAppUsage
   21640     private void drawBackground(Canvas canvas) {
   21641         final Drawable background = mBackground;
   21642         if (background == null) {
   21643             return;
   21644         }
   21645 
   21646         setBackgroundBounds();
   21647 
   21648         // Attempt to use a display list if requested.
   21649         if (canvas.isHardwareAccelerated() && mAttachInfo != null
   21650                 && mAttachInfo.mThreadedRenderer != null) {
   21651             mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
   21652 
   21653             final RenderNode renderNode = mBackgroundRenderNode;
   21654             if (renderNode != null && renderNode.hasDisplayList()) {
   21655                 setBackgroundRenderNodeProperties(renderNode);
   21656                 ((RecordingCanvas) canvas).drawRenderNode(renderNode);
   21657                 return;
   21658             }
   21659         }
   21660 
   21661         final int scrollX = mScrollX;
   21662         final int scrollY = mScrollY;
   21663         if ((scrollX | scrollY) == 0) {
   21664             background.draw(canvas);
   21665         } else {
   21666             canvas.translate(scrollX, scrollY);
   21667             background.draw(canvas);
   21668             canvas.translate(-scrollX, -scrollY);
   21669         }
   21670     }
   21671 
   21672     /**
   21673      * Sets the correct background bounds and rebuilds the outline, if needed.
   21674      * <p/>
   21675      * This is called by LayoutLib.
   21676      */
   21677     void setBackgroundBounds() {
   21678         if (mBackgroundSizeChanged && mBackground != null) {
   21679             mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
   21680             mBackgroundSizeChanged = false;
   21681             rebuildOutline();
   21682         }
   21683     }
   21684 
   21685     private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
   21686         renderNode.setTranslationX(mScrollX);
   21687         renderNode.setTranslationY(mScrollY);
   21688     }
   21689 
   21690     /**
   21691      * Creates a new display list or updates the existing display list for the
   21692      * specified Drawable.
   21693      *
   21694      * @param drawable Drawable for which to create a display list
   21695      * @param renderNode Existing RenderNode, or {@code null}
   21696      * @return A valid display list for the specified drawable
   21697      */
   21698     private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
   21699         if (renderNode == null) {
   21700             renderNode = RenderNode.create(drawable.getClass().getName(),
   21701                     new ViewAnimationHostBridge(this));
   21702             renderNode.setUsageHint(RenderNode.USAGE_BACKGROUND);
   21703         }
   21704 
   21705         final Rect bounds = drawable.getBounds();
   21706         final int width = bounds.width();
   21707         final int height = bounds.height();
   21708         final RecordingCanvas canvas = renderNode.beginRecording(width, height);
   21709 
   21710         // Reverse left/top translation done by drawable canvas, which will
   21711         // instead be applied by rendernode's LTRB bounds below. This way, the
   21712         // drawable's bounds match with its rendernode bounds and its content
   21713         // will lie within those bounds in the rendernode tree.
   21714         canvas.translate(-bounds.left, -bounds.top);
   21715 
   21716         try {
   21717             drawable.draw(canvas);
   21718         } finally {
   21719             renderNode.endRecording();
   21720         }
   21721 
   21722         // Set up drawable properties that are view-independent.
   21723         renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
   21724         renderNode.setProjectBackwards(drawable.isProjected());
   21725         renderNode.setProjectionReceiver(true);
   21726         renderNode.setClipToBounds(false);
   21727         return renderNode;
   21728     }
   21729 
   21730     /**
   21731      * Returns the overlay for this view, creating it if it does not yet exist.
   21732      * Adding drawables to the overlay will cause them to be displayed whenever
   21733      * the view itself is redrawn. Objects in the overlay should be actively
   21734      * managed: remove them when they should not be displayed anymore. The
   21735      * overlay will always have the same size as its host view.
   21736      *
   21737      * <p>Note: Overlays do not currently work correctly with {@link
   21738      * SurfaceView} or {@link TextureView}; contents in overlays for these
   21739      * types of views may not display correctly.</p>
   21740      *
   21741      * @return The ViewOverlay object for this view.
   21742      * @see ViewOverlay
   21743      */
   21744     public ViewOverlay getOverlay() {
   21745         if (mOverlay == null) {
   21746             mOverlay = new ViewOverlay(mContext, this);
   21747         }
   21748         return mOverlay;
   21749     }
   21750 
   21751     /**
   21752      * Override this if your view is known to always be drawn on top of a solid color background,
   21753      * and needs to draw fading edges. Returning a non-zero color enables the view system to
   21754      * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
   21755      * should be set to 0xFF.
   21756      *
   21757      * @see #setVerticalFadingEdgeEnabled(boolean)
   21758      * @see #setHorizontalFadingEdgeEnabled(boolean)
   21759      *
   21760      * @return The known solid color background for this view, or 0 if the color may vary
   21761      */
   21762     @ViewDebug.ExportedProperty(category = "drawing")
   21763     @InspectableProperty
   21764     @ColorInt
   21765     public int getSolidColor() {
   21766         return 0;
   21767     }
   21768 
   21769     /**
   21770      * Build a human readable string representation of the specified view flags.
   21771      *
   21772      * @param flags the view flags to convert to a string
   21773      * @return a String representing the supplied flags
   21774      */
   21775     private static String printFlags(int flags) {
   21776         String output = "";
   21777         int numFlags = 0;
   21778         if ((flags & FOCUSABLE) == FOCUSABLE) {
   21779             output += "TAKES_FOCUS";
   21780             numFlags++;
   21781         }
   21782 
   21783         switch (flags & VISIBILITY_MASK) {
   21784         case INVISIBLE:
   21785             if (numFlags > 0) {
   21786                 output += " ";
   21787             }
   21788             output += "INVISIBLE";
   21789             // USELESS HERE numFlags++;
   21790             break;
   21791         case GONE:
   21792             if (numFlags > 0) {
   21793                 output += " ";
   21794             }
   21795             output += "GONE";
   21796             // USELESS HERE numFlags++;
   21797             break;
   21798         default:
   21799             break;
   21800         }
   21801         return output;
   21802     }
   21803 
   21804     /**
   21805      * Build a human readable string representation of the specified private
   21806      * view flags.
   21807      *
   21808      * @param privateFlags the private view flags to convert to a string
   21809      * @return a String representing the supplied flags
   21810      */
   21811     private static String printPrivateFlags(int privateFlags) {
   21812         String output = "";
   21813         int numFlags = 0;
   21814 
   21815         if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
   21816             output += "WANTS_FOCUS";
   21817             numFlags++;
   21818         }
   21819 
   21820         if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
   21821             if (numFlags > 0) {
   21822                 output += " ";
   21823             }
   21824             output += "FOCUSED";
   21825             numFlags++;
   21826         }
   21827 
   21828         if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
   21829             if (numFlags > 0) {
   21830                 output += " ";
   21831             }
   21832             output += "SELECTED";
   21833             numFlags++;
   21834         }
   21835 
   21836         if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
   21837             if (numFlags > 0) {
   21838                 output += " ";
   21839             }
   21840             output += "IS_ROOT_NAMESPACE";
   21841             numFlags++;
   21842         }
   21843 
   21844         if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
   21845             if (numFlags > 0) {
   21846                 output += " ";
   21847             }
   21848             output += "HAS_BOUNDS";
   21849             numFlags++;
   21850         }
   21851 
   21852         if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
   21853             if (numFlags > 0) {
   21854                 output += " ";
   21855             }
   21856             output += "DRAWN";
   21857             // USELESS HERE numFlags++;
   21858         }
   21859         return output;
   21860     }
   21861 
   21862     /**
   21863      * <p>Indicates whether or not this view's layout will be requested during
   21864      * the next hierarchy layout pass.</p>
   21865      *
   21866      * @return true if the layout will be forced during next layout pass
   21867      */
   21868     public boolean isLayoutRequested() {
   21869         return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
   21870     }
   21871 
   21872     /**
   21873      * Return true if o is a ViewGroup that is laying out using optical bounds.
   21874      * @hide
   21875      */
   21876     public static boolean isLayoutModeOptical(Object o) {
   21877         return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
   21878     }
   21879 
   21880     private boolean setOpticalFrame(int left, int top, int right, int bottom) {
   21881         Insets parentInsets = mParent instanceof View ?
   21882                 ((View) mParent).getOpticalInsets() : Insets.NONE;
   21883         Insets childInsets = getOpticalInsets();
   21884         return setFrame(
   21885                 left   + parentInsets.left - childInsets.left,
   21886                 top    + parentInsets.top  - childInsets.top,
   21887                 right  + parentInsets.left + childInsets.right,
   21888                 bottom + parentInsets.top  + childInsets.bottom);
   21889     }
   21890 
   21891     /**
   21892      * Assign a size and position to a view and all of its
   21893      * descendants
   21894      *
   21895      * <p>This is the second phase of the layout mechanism.
   21896      * (The first is measuring). In this phase, each parent calls
   21897      * layout on all of its children to position them.
   21898      * This is typically done using the child measurements
   21899      * that were stored in the measure pass().</p>
   21900      *
   21901      * <p>Derived classes should not override this method.
   21902      * Derived classes with children should override
   21903      * onLayout. In that method, they should
   21904      * call layout on each of their children.</p>
   21905      *
   21906      * @param l Left position, relative to parent
   21907      * @param t Top position, relative to parent
   21908      * @param r Right position, relative to parent
   21909      * @param b Bottom position, relative to parent
   21910      */
   21911     @SuppressWarnings({"unchecked"})
   21912     public void layout(int l, int t, int r, int b) {
   21913         if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
   21914             onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
   21915             mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
   21916         }
   21917 
   21918         int oldL = mLeft;
   21919         int oldT = mTop;
   21920         int oldB = mBottom;
   21921         int oldR = mRight;
   21922 
   21923         boolean changed = isLayoutModeOptical(mParent) ?
   21924                 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
   21925 
   21926         if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
   21927             onLayout(changed, l, t, r, b);
   21928 
   21929             if (shouldDrawRoundScrollbar()) {
   21930                 if(mRoundScrollbarRenderer == null) {
   21931                     mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
   21932                 }
   21933             } else {
   21934                 mRoundScrollbarRenderer = null;
   21935             }
   21936 
   21937             mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
   21938 
   21939             ListenerInfo li = mListenerInfo;
   21940             if (li != null && li.mOnLayoutChangeListeners != null) {
   21941                 ArrayList<OnLayoutChangeListener> listenersCopy =
   21942                         (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
   21943                 int numListeners = listenersCopy.size();
   21944                 for (int i = 0; i < numListeners; ++i) {
   21945                     listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
   21946                 }
   21947             }
   21948         }
   21949 
   21950         final boolean wasLayoutValid = isLayoutValid();
   21951 
   21952         mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
   21953         mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
   21954 
   21955         if (!wasLayoutValid && isFocused()) {
   21956             mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
   21957             if (canTakeFocus()) {
   21958                 // We have a robust focus, so parents should no longer be wanting focus.
   21959                 clearParentsWantFocus();
   21960             } else if (getViewRootImpl() == null || !getViewRootImpl().isInLayout()) {
   21961                 // This is a weird case. Most-likely the user, rather than ViewRootImpl, called
   21962                 // layout. In this case, there's no guarantee that parent layouts will be evaluated
   21963                 // and thus the safest action is to clear focus here.
   21964                 clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
   21965                 clearParentsWantFocus();
   21966             } else if (!hasParentWantsFocus()) {
   21967                 // original requestFocus was likely on this view directly, so just clear focus
   21968                 clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
   21969             }
   21970             // otherwise, we let parents handle re-assigning focus during their layout passes.
   21971         } else if ((mPrivateFlags & PFLAG_WANTS_FOCUS) != 0) {
   21972             mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
   21973             View focused = findFocus();
   21974             if (focused != null) {
   21975                 // Try to restore focus as close as possible to our starting focus.
   21976                 if (!restoreDefaultFocus() && !hasParentWantsFocus()) {
   21977                     // Give up and clear focus once we've reached the top-most parent which wants
   21978                     // focus.
   21979                     focused.clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
   21980                 }
   21981             }
   21982         }
   21983 
   21984         if ((mPrivateFlags3 & PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT) != 0) {
   21985             mPrivateFlags3 &= ~PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
   21986             notifyEnterOrExitForAutoFillIfNeeded(true);
   21987         }
   21988     }
   21989 
   21990     private boolean hasParentWantsFocus() {
   21991         ViewParent parent = mParent;
   21992         while (parent instanceof ViewGroup) {
   21993             ViewGroup pv = (ViewGroup) parent;
   21994             if ((pv.mPrivateFlags & PFLAG_WANTS_FOCUS) != 0) {
   21995                 return true;
   21996             }
   21997             parent = pv.mParent;
   21998         }
   21999         return false;
   22000     }
   22001 
   22002     /**
   22003      * Called from layout when this view should
   22004      * assign a size and position to each of its children.
   22005      *
   22006      * Derived classes with children should override
   22007      * this method and call layout on each of
   22008      * their children.
   22009      * @param changed This is a new size or position for this view
   22010      * @param left Left position, relative to parent
   22011      * @param top Top position, relative to parent
   22012      * @param right Right position, relative to parent
   22013      * @param bottom Bottom position, relative to parent
   22014      */
   22015     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
   22016     }
   22017 
   22018     /**
   22019      * Assign a size and position to this view.
   22020      *
   22021      * This is called from layout.
   22022      *
   22023      * @param left Left position, relative to parent
   22024      * @param top Top position, relative to parent
   22025      * @param right Right position, relative to parent
   22026      * @param bottom Bottom position, relative to parent
   22027      * @return true if the new size and position are different than the
   22028      *         previous ones
   22029      * {@hide}
   22030      */
   22031     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
   22032     protected boolean setFrame(int left, int top, int right, int bottom) {
   22033         boolean changed = false;
   22034 
   22035         if (DBG) {
   22036             Log.d(VIEW_LOG_TAG, this + " View.setFrame(" + left + "," + top + ","
   22037                     + right + "," + bottom + ")");
   22038         }
   22039 
   22040         if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
   22041             changed = true;
   22042 
   22043             // Remember our drawn bit
   22044             int drawn = mPrivateFlags & PFLAG_DRAWN;
   22045 
   22046             int oldWidth = mRight - mLeft;
   22047             int oldHeight = mBottom - mTop;
   22048             int newWidth = right - left;
   22049             int newHeight = bottom - top;
   22050             boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
   22051 
   22052             // Invalidate our old position
   22053             invalidate(sizeChanged);
   22054 
   22055             mLeft = left;
   22056             mTop = top;
   22057             mRight = right;
   22058             mBottom = bottom;
   22059             mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
   22060 
   22061             mPrivateFlags |= PFLAG_HAS_BOUNDS;
   22062 
   22063 
   22064             if (sizeChanged) {
   22065                 sizeChange(newWidth, newHeight, oldWidth, oldHeight);
   22066             }
   22067 
   22068             if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
   22069                 // If we are visible, force the DRAWN bit to on so that
   22070                 // this invalidate will go through (at least to our parent).
   22071                 // This is because someone may have invalidated this view
   22072                 // before this call to setFrame came in, thereby clearing
   22073                 // the DRAWN bit.
   22074                 mPrivateFlags |= PFLAG_DRAWN;
   22075                 invalidate(sizeChanged);
   22076                 // parent display list may need to be recreated based on a change in the bounds
   22077                 // of any child
   22078                 invalidateParentCaches();
   22079             }
   22080 
   22081             // Reset drawn bit to original value (invalidate turns it off)
   22082             mPrivateFlags |= drawn;
   22083 
   22084             mBackgroundSizeChanged = true;
   22085             mDefaultFocusHighlightSizeChanged = true;
   22086             if (mForegroundInfo != null) {
   22087                 mForegroundInfo.mBoundsChanged = true;
   22088             }
   22089 
   22090             notifySubtreeAccessibilityStateChangedIfNeeded();
   22091         }
   22092         return changed;
   22093     }
   22094 
   22095     /**
   22096      * Assign a size and position to this view.
   22097      *
   22098      * This method is meant to be used in animations only as it applies this position and size
   22099      * for the view only temporary and it can be changed back at any time by the layout.
   22100      *
   22101      * @param left Left position, relative to parent
   22102      * @param top Top position, relative to parent
   22103      * @param right Right position, relative to parent
   22104      * @param bottom Bottom position, relative to parent
   22105      *
   22106      * @see #setLeft(int), #setRight(int), #setTop(int), #setBottom(int)
   22107      */
   22108     public final void setLeftTopRightBottom(int left, int top, int right, int bottom) {
   22109         setFrame(left, top, right, bottom);
   22110     }
   22111 
   22112     private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
   22113         onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
   22114         if (mOverlay != null) {
   22115             mOverlay.getOverlayView().setRight(newWidth);
   22116             mOverlay.getOverlayView().setBottom(newHeight);
   22117         }
   22118         // If this isn't laid out yet, focus assignment will be handled during the "deferment/
   22119         // backtracking" of requestFocus during layout, so don't touch focus here.
   22120         if (!sCanFocusZeroSized && isLayoutValid()
   22121                 // Don't touch focus if animating
   22122                 && !(mParent instanceof ViewGroup && ((ViewGroup) mParent).isLayoutSuppressed())) {
   22123             if (newWidth <= 0 || newHeight <= 0) {
   22124                 if (hasFocus()) {
   22125                     clearFocus();
   22126                     if (mParent instanceof ViewGroup) {
   22127                         ((ViewGroup) mParent).clearFocusedInCluster();
   22128                     }
   22129                 }
   22130                 clearAccessibilityFocus();
   22131             } else if (oldWidth <= 0 || oldHeight <= 0) {
   22132                 if (mParent != null && canTakeFocus()) {
   22133                     mParent.focusableViewAvailable(this);
   22134                 }
   22135             }
   22136         }
   22137         rebuildOutline();
   22138     }
   22139 
   22140     /**
   22141      * Finalize inflating a view from XML.  This is called as the last phase
   22142      * of inflation, after all child views have been added.
   22143      *
   22144      * <p>Even if the subclass overrides onFinishInflate, they should always be
   22145      * sure to call the super method, so that we get called.
   22146      */
   22147     @CallSuper
   22148     protected void onFinishInflate() {
   22149     }
   22150 
   22151     /**
   22152      * Returns the resources associated with this view.
   22153      *
   22154      * @return Resources object.
   22155      */
   22156     public Resources getResources() {
   22157         return mResources;
   22158     }
   22159 
   22160     /**
   22161      * Invalidates the specified Drawable.
   22162      *
   22163      * @param drawable the drawable to invalidate
   22164      */
   22165     @Override
   22166     public void invalidateDrawable(@NonNull Drawable drawable) {
   22167         if (verifyDrawable(drawable)) {
   22168             final Rect dirty = drawable.getDirtyBounds();
   22169             final int scrollX = mScrollX;
   22170             final int scrollY = mScrollY;
   22171 
   22172             invalidate(dirty.left + scrollX, dirty.top + scrollY,
   22173                     dirty.right + scrollX, dirty.bottom + scrollY);
   22174             rebuildOutline();
   22175         }
   22176     }
   22177 
   22178     /**
   22179      * Schedules an action on a drawable to occur at a specified time.
   22180      *
   22181      * @param who the recipient of the action
   22182      * @param what the action to run on the drawable
   22183      * @param when the time at which the action must occur. Uses the
   22184      *        {@link SystemClock#uptimeMillis} timebase.
   22185      */
   22186     @Override
   22187     public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
   22188         if (verifyDrawable(who) && what != null) {
   22189             final long delay = when - SystemClock.uptimeMillis();
   22190             if (mAttachInfo != null) {
   22191                 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
   22192                         Choreographer.CALLBACK_ANIMATION, what, who,
   22193                         Choreographer.subtractFrameDelay(delay));
   22194             } else {
   22195                 // Postpone the runnable until we know
   22196                 // on which thread it needs to run.
   22197                 getRunQueue().postDelayed(what, delay);
   22198             }
   22199         }
   22200     }
   22201 
   22202     /**
   22203      * Cancels a scheduled action on a drawable.
   22204      *
   22205      * @param who the recipient of the action
   22206      * @param what the action to cancel
   22207      */
   22208     @Override
   22209     public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
   22210         if (verifyDrawable(who) && what != null) {
   22211             if (mAttachInfo != null) {
   22212                 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
   22213                         Choreographer.CALLBACK_ANIMATION, what, who);
   22214             }
   22215             getRunQueue().removeCallbacks(what);
   22216         }
   22217     }
   22218 
   22219     /**
   22220      * Unschedule any events associated with the given Drawable.  This can be
   22221      * used when selecting a new Drawable into a view, so that the previous
   22222      * one is completely unscheduled.
   22223      *
   22224      * @param who The Drawable to unschedule.
   22225      *
   22226      * @see #drawableStateChanged
   22227      */
   22228     public void unscheduleDrawable(Drawable who) {
   22229         if (mAttachInfo != null && who != null) {
   22230             mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
   22231                     Choreographer.CALLBACK_ANIMATION, null, who);
   22232         }
   22233     }
   22234 
   22235     /**
   22236      * Resolve the Drawables depending on the layout direction. This is implicitly supposing
   22237      * that the View directionality can and will be resolved before its Drawables.
   22238      *
   22239      * Will call {@link View#onResolveDrawables} when resolution is done.
   22240      *
   22241      * @hide
   22242      */
   22243     protected void resolveDrawables() {
   22244         // Drawables resolution may need to happen before resolving the layout direction (which is
   22245         // done only during the measure() call).
   22246         // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
   22247         // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
   22248         // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
   22249         // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
   22250         // direction to be resolved as its resolved value will be the same as its raw value.
   22251         if (!isLayoutDirectionResolved() &&
   22252                 getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
   22253             return;
   22254         }
   22255 
   22256         final int layoutDirection = isLayoutDirectionResolved() ?
   22257                 getLayoutDirection() : getRawLayoutDirection();
   22258 
   22259         if (mBackground != null) {
   22260             mBackground.setLayoutDirection(layoutDirection);
   22261         }
   22262         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
   22263             mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
   22264         }
   22265         if (mDefaultFocusHighlight != null) {
   22266             mDefaultFocusHighlight.setLayoutDirection(layoutDirection);
   22267         }
   22268         mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
   22269         onResolveDrawables(layoutDirection);
   22270     }
   22271 
   22272     boolean areDrawablesResolved() {
   22273         return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
   22274     }
   22275 
   22276     /**
   22277      * Called when layout direction has been resolved.
   22278      *
   22279      * The default implementation does nothing.
   22280      *
   22281      * @param layoutDirection The resolved layout direction.
   22282      *
   22283      * @see #LAYOUT_DIRECTION_LTR
   22284      * @see #LAYOUT_DIRECTION_RTL
   22285      *
   22286      * @hide
   22287      */
   22288     public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
   22289     }
   22290 
   22291     /**
   22292      * @hide
   22293      */
   22294     @TestApi
   22295     protected void resetResolvedDrawables() {
   22296         resetResolvedDrawablesInternal();
   22297     }
   22298 
   22299     void resetResolvedDrawablesInternal() {
   22300         mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
   22301     }
   22302 
   22303     /**
   22304      * If your view subclass is displaying its own Drawable objects, it should
   22305      * override this function and return true for any Drawable it is
   22306      * displaying.  This allows animations for those drawables to be
   22307      * scheduled.
   22308      *
   22309      * <p>Be sure to call through to the super class when overriding this
   22310      * function.
   22311      *
   22312      * @param who The Drawable to verify.  Return true if it is one you are
   22313      *            displaying, else return the result of calling through to the
   22314      *            super class.
   22315      *
   22316      * @return boolean If true than the Drawable is being displayed in the
   22317      *         view; else false and it is not allowed to animate.
   22318      *
   22319      * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
   22320      * @see #drawableStateChanged()
   22321      */
   22322     @CallSuper
   22323     protected boolean verifyDrawable(@NonNull Drawable who) {
   22324         // Avoid verifying the scroll bar drawable so that we don't end up in
   22325         // an invalidation loop. This effectively prevents the scroll bar
   22326         // drawable from triggering invalidations and scheduling runnables.
   22327         return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who)
   22328                 || (mDefaultFocusHighlight == who);
   22329     }
   22330 
   22331     /**
   22332      * This function is called whenever the state of the view changes in such
   22333      * a way that it impacts the state of drawables being shown.
   22334      * <p>
   22335      * If the View has a StateListAnimator, it will also be called to run necessary state
   22336      * change animations.
   22337      * <p>
   22338      * Be sure to call through to the superclass when overriding this function.
   22339      *
   22340      * @see Drawable#setState(int[])
   22341      */
   22342     @CallSuper
   22343     protected void drawableStateChanged() {
   22344         final int[] state = getDrawableState();
   22345         boolean changed = false;
   22346 
   22347         final Drawable bg = mBackground;
   22348         if (bg != null && bg.isStateful()) {
   22349             changed |= bg.setState(state);
   22350         }
   22351 
   22352         final Drawable hl = mDefaultFocusHighlight;
   22353         if (hl != null && hl.isStateful()) {
   22354             changed |= hl.setState(state);
   22355         }
   22356 
   22357         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
   22358         if (fg != null && fg.isStateful()) {
   22359             changed |= fg.setState(state);
   22360         }
   22361 
   22362         if (mScrollCache != null) {
   22363             final Drawable scrollBar = mScrollCache.scrollBar;
   22364             if (scrollBar != null && scrollBar.isStateful()) {
   22365                 changed |= scrollBar.setState(state)
   22366                         && mScrollCache.state != ScrollabilityCache.OFF;
   22367             }
   22368         }
   22369 
   22370         if (mStateListAnimator != null) {
   22371             mStateListAnimator.setState(state);
   22372         }
   22373 
   22374         if (changed) {
   22375             invalidate();
   22376         }
   22377     }
   22378 
   22379     /**
   22380      * This function is called whenever the view hotspot changes and needs to
   22381      * be propagated to drawables or child views managed by the view.
   22382      * <p>
   22383      * Dispatching to child views is handled by
   22384      * {@link #dispatchDrawableHotspotChanged(float, float)}.
   22385      * <p>
   22386      * Be sure to call through to the superclass when overriding this function.
   22387      *
   22388      * @param x hotspot x coordinate
   22389      * @param y hotspot y coordinate
   22390      */
   22391     @CallSuper
   22392     public void drawableHotspotChanged(float x, float y) {
   22393         if (mBackground != null) {
   22394             mBackground.setHotspot(x, y);
   22395         }
   22396         if (mDefaultFocusHighlight != null) {
   22397             mDefaultFocusHighlight.setHotspot(x, y);
   22398         }
   22399         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
   22400             mForegroundInfo.mDrawable.setHotspot(x, y);
   22401         }
   22402 
   22403         dispatchDrawableHotspotChanged(x, y);
   22404     }
   22405 
   22406     /**
   22407      * Dispatches drawableHotspotChanged to all of this View's children.
   22408      *
   22409      * @param x hotspot x coordinate
   22410      * @param y hotspot y coordinate
   22411      * @see #drawableHotspotChanged(float, float)
   22412      */
   22413     public void dispatchDrawableHotspotChanged(float x, float y) {
   22414     }
   22415 
   22416     /**
   22417      * Call this to force a view to update its drawable state. This will cause
   22418      * drawableStateChanged to be called on this view. Views that are interested
   22419      * in the new state should call getDrawableState.
   22420      *
   22421      * @see #drawableStateChanged
   22422      * @see #getDrawableState
   22423      */
   22424     public void refreshDrawableState() {
   22425         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
   22426         drawableStateChanged();
   22427 
   22428         ViewParent parent = mParent;
   22429         if (parent != null) {
   22430             parent.childDrawableStateChanged(this);
   22431         }
   22432     }
   22433 
   22434     /**
   22435      * Create a default focus highlight if it doesn't exist.
   22436      * @return a default focus highlight.
   22437      */
   22438     private Drawable getDefaultFocusHighlightDrawable() {
   22439         if (mDefaultFocusHighlightCache == null) {
   22440             if (mContext != null) {
   22441                 final int[] attrs = new int[] { android.R.attr.selectableItemBackground };
   22442                 final TypedArray ta = mContext.obtainStyledAttributes(attrs);
   22443                 mDefaultFocusHighlightCache = ta.getDrawable(0);
   22444                 ta.recycle();
   22445             }
   22446         }
   22447         return mDefaultFocusHighlightCache;
   22448     }
   22449 
   22450     /**
   22451      * Set the current default focus highlight.
   22452      * @param highlight the highlight drawable, or {@code null} if it's no longer needed.
   22453      */
   22454     private void setDefaultFocusHighlight(Drawable highlight) {
   22455         mDefaultFocusHighlight = highlight;
   22456         mDefaultFocusHighlightSizeChanged = true;
   22457         if (highlight != null) {
   22458             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
   22459                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
   22460             }
   22461             highlight.setLayoutDirection(getLayoutDirection());
   22462             if (highlight.isStateful()) {
   22463                 highlight.setState(getDrawableState());
   22464             }
   22465             if (isAttachedToWindow()) {
   22466                 highlight.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
   22467             }
   22468             // Set callback last, since the view may still be initializing.
   22469             highlight.setCallback(this);
   22470         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
   22471                 && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
   22472             mPrivateFlags |= PFLAG_SKIP_DRAW;
   22473         }
   22474         invalidate();
   22475     }
   22476 
   22477     /**
   22478      * Check whether we need to draw a default focus highlight when this view gets focused,
   22479      * which requires:
   22480      * <ul>
   22481      *     <li>In both background and foreground, {@link android.R.attr#state_focused}
   22482      *         is not defined.</li>
   22483      *     <li>This view is not in touch mode.</li>
   22484      *     <li>This view doesn't opt out for a default focus highlight, via
   22485      *         {@link #setDefaultFocusHighlightEnabled(boolean)}.</li>
   22486      *     <li>This view is attached to window.</li>
   22487      * </ul>
   22488      * @return {@code true} if a default focus highlight is needed.
   22489      * @hide
   22490      */
   22491     @TestApi
   22492     public boolean isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground) {
   22493         final boolean lackFocusState = (background == null || !background.isStateful()
   22494                 || !background.hasFocusStateSpecified())
   22495                 && (foreground == null || !foreground.isStateful()
   22496                 || !foreground.hasFocusStateSpecified());
   22497         return !isInTouchMode() && getDefaultFocusHighlightEnabled() && lackFocusState
   22498                 && isAttachedToWindow() && sUseDefaultFocusHighlight;
   22499     }
   22500 
   22501     /**
   22502      * When this view is focused, switches on/off the default focused highlight.
   22503      * <p>
   22504      * This always happens when this view is focused, and only at this moment the default focus
   22505      * highlight can be visible.
   22506      */
   22507     private void switchDefaultFocusHighlight() {
   22508         if (isFocused()) {
   22509             final boolean needed = isDefaultFocusHighlightNeeded(mBackground,
   22510                     mForegroundInfo == null ? null : mForegroundInfo.mDrawable);
   22511             final boolean active = mDefaultFocusHighlight != null;
   22512             if (needed && !active) {
   22513                 setDefaultFocusHighlight(getDefaultFocusHighlightDrawable());
   22514             } else if (!needed && active) {
   22515                 // The highlight is no longer needed, so tear it down.
   22516                 setDefaultFocusHighlight(null);
   22517             }
   22518         }
   22519     }
   22520 
   22521     /**
   22522      * Draw the default focus highlight onto the canvas.
   22523      * @param canvas the canvas where we're drawing the highlight.
   22524      */
   22525     private void drawDefaultFocusHighlight(Canvas canvas) {
   22526         if (mDefaultFocusHighlight != null) {
   22527             if (mDefaultFocusHighlightSizeChanged) {
   22528                 mDefaultFocusHighlightSizeChanged = false;
   22529                 final int l = mScrollX;
   22530                 final int r = l + mRight - mLeft;
   22531                 final int t = mScrollY;
   22532                 final int b = t + mBottom - mTop;
   22533                 mDefaultFocusHighlight.setBounds(l, t, r, b);
   22534             }
   22535             mDefaultFocusHighlight.draw(canvas);
   22536         }
   22537     }
   22538 
   22539     /**
   22540      * Return an array of resource IDs of the drawable states representing the
   22541      * current state of the view.
   22542      *
   22543      * @return The current drawable state
   22544      *
   22545      * @see Drawable#setState(int[])
   22546      * @see #drawableStateChanged()
   22547      * @see #onCreateDrawableState(int)
   22548      */
   22549     public final int[] getDrawableState() {
   22550         if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
   22551             return mDrawableState;
   22552         } else {
   22553             mDrawableState = onCreateDrawableState(0);
   22554             mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
   22555             return mDrawableState;
   22556         }
   22557     }
   22558 
   22559     /**
   22560      * Generate the new {@link android.graphics.drawable.Drawable} state for
   22561      * this view. This is called by the view
   22562      * system when the cached Drawable state is determined to be invalid.  To
   22563      * retrieve the current state, you should use {@link #getDrawableState}.
   22564      *
   22565      * @param extraSpace if non-zero, this is the number of extra entries you
   22566      * would like in the returned array in which you can place your own
   22567      * states.
   22568      *
   22569      * @return Returns an array holding the current {@link Drawable} state of
   22570      * the view.
   22571      *
   22572      * @see #mergeDrawableStates(int[], int[])
   22573      */
   22574     protected int[] onCreateDrawableState(int extraSpace) {
   22575         if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
   22576                 mParent instanceof View) {
   22577             return ((View) mParent).onCreateDrawableState(extraSpace);
   22578         }
   22579 
   22580         int[] drawableState;
   22581 
   22582         int privateFlags = mPrivateFlags;
   22583 
   22584         int viewStateIndex = 0;
   22585         if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
   22586         if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
   22587         if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
   22588         if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
   22589         if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
   22590         if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
   22591         if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
   22592                 ThreadedRenderer.isAvailable()) {
   22593             // This is set if HW acceleration is requested, even if the current
   22594             // process doesn't allow it.  This is just to allow app preview
   22595             // windows to better match their app.
   22596             viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
   22597         }
   22598         if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
   22599 
   22600         final int privateFlags2 = mPrivateFlags2;
   22601         if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
   22602             viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
   22603         }
   22604         if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
   22605             viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
   22606         }
   22607 
   22608         drawableState = StateSet.get(viewStateIndex);
   22609 
   22610         //noinspection ConstantIfStatement
   22611         if (false) {
   22612             Log.i("View", "drawableStateIndex=" + viewStateIndex);
   22613             Log.i("View", toString()
   22614                     + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
   22615                     + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
   22616                     + " fo=" + hasFocus()
   22617                     + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
   22618                     + " wf=" + hasWindowFocus()
   22619                     + ": " + Arrays.toString(drawableState));
   22620         }
   22621 
   22622         if (extraSpace == 0) {
   22623             return drawableState;
   22624         }
   22625 
   22626         final int[] fullState;
   22627         if (drawableState != null) {
   22628             fullState = new int[drawableState.length + extraSpace];
   22629             System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
   22630         } else {
   22631             fullState = new int[extraSpace];
   22632         }
   22633 
   22634         return fullState;
   22635     }
   22636 
   22637     /**
   22638      * Merge your own state values in <var>additionalState</var> into the base
   22639      * state values <var>baseState</var> that were returned by
   22640      * {@link #onCreateDrawableState(int)}.
   22641      *
   22642      * @param baseState The base state values returned by
   22643      * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
   22644      * own additional state values.
   22645      *
   22646      * @param additionalState The additional state values you would like
   22647      * added to <var>baseState</var>; this array is not modified.
   22648      *
   22649      * @return As a convenience, the <var>baseState</var> array you originally
   22650      * passed into the function is returned.
   22651      *
   22652      * @see #onCreateDrawableState(int)
   22653      */
   22654     protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
   22655         final int N = baseState.length;
   22656         int i = N - 1;
   22657         while (i >= 0 && baseState[i] == 0) {
   22658             i--;
   22659         }
   22660         System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
   22661         return baseState;
   22662     }
   22663 
   22664     /**
   22665      * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
   22666      * on all Drawable objects associated with this view.
   22667      * <p>
   22668      * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
   22669      * attached to this view.
   22670      */
   22671     @CallSuper
   22672     public void jumpDrawablesToCurrentState() {
   22673         if (mBackground != null) {
   22674             mBackground.jumpToCurrentState();
   22675         }
   22676         if (mStateListAnimator != null) {
   22677             mStateListAnimator.jumpToCurrentState();
   22678         }
   22679         if (mDefaultFocusHighlight != null) {
   22680             mDefaultFocusHighlight.jumpToCurrentState();
   22681         }
   22682         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
   22683             mForegroundInfo.mDrawable.jumpToCurrentState();
   22684         }
   22685     }
   22686 
   22687     /**
   22688      * Sets the background color for this view.
   22689      * @param color the color of the background
   22690      */
   22691     @RemotableViewMethod
   22692     public void setBackgroundColor(@ColorInt int color) {
   22693         if (mBackground instanceof ColorDrawable) {
   22694             ((ColorDrawable) mBackground.mutate()).setColor(color);
   22695             computeOpaqueFlags();
   22696             mBackgroundResource = 0;
   22697         } else {
   22698             setBackground(new ColorDrawable(color));
   22699         }
   22700     }
   22701 
   22702     /**
   22703      * Set the background to a given resource. The resource should refer to
   22704      * a Drawable object or 0 to remove the background.
   22705      * @param resid The identifier of the resource.
   22706      *
   22707      * @attr ref android.R.styleable#View_background
   22708      */
   22709     @RemotableViewMethod
   22710     public void setBackgroundResource(@DrawableRes int resid) {
   22711         if (resid != 0 && resid == mBackgroundResource) {
   22712             return;
   22713         }
   22714 
   22715         Drawable d = null;
   22716         if (resid != 0) {
   22717             d = mContext.getDrawable(resid);
   22718         }
   22719         setBackground(d);
   22720 
   22721         mBackgroundResource = resid;
   22722     }
   22723 
   22724     /**
   22725      * Set the background to a given Drawable, or remove the background. If the
   22726      * background has padding, this View's padding is set to the background's
   22727      * padding. However, when a background is removed, this View's padding isn't
   22728      * touched. If setting the padding is desired, please use
   22729      * {@link #setPadding(int, int, int, int)}.
   22730      *
   22731      * @param background The Drawable to use as the background, or null to remove the
   22732      *        background
   22733      */
   22734     public void setBackground(Drawable background) {
   22735         //noinspection deprecation
   22736         setBackgroundDrawable(background);
   22737     }
   22738 
   22739     /**
   22740      * @deprecated use {@link #setBackground(Drawable)} instead
   22741      */
   22742     @Deprecated
   22743     public void setBackgroundDrawable(Drawable background) {
   22744         computeOpaqueFlags();
   22745 
   22746         if (background == mBackground) {
   22747             return;
   22748         }
   22749 
   22750         boolean requestLayout = false;
   22751 
   22752         mBackgroundResource = 0;
   22753 
   22754         /*
   22755          * Regardless of whether we're setting a new background or not, we want
   22756          * to clear the previous drawable. setVisible first while we still have the callback set.
   22757          */
   22758         if (mBackground != null) {
   22759             if (isAttachedToWindow()) {
   22760                 mBackground.setVisible(false, false);
   22761             }
   22762             mBackground.setCallback(null);
   22763             unscheduleDrawable(mBackground);
   22764         }
   22765 
   22766         if (background != null) {
   22767             Rect padding = sThreadLocal.get();
   22768             if (padding == null) {
   22769                 padding = new Rect();
   22770                 sThreadLocal.set(padding);
   22771             }
   22772             resetResolvedDrawablesInternal();
   22773             background.setLayoutDirection(getLayoutDirection());
   22774             if (background.getPadding(padding)) {
   22775                 resetResolvedPaddingInternal();
   22776                 switch (background.getLayoutDirection()) {
   22777                     case LAYOUT_DIRECTION_RTL:
   22778                         mUserPaddingLeftInitial = padding.right;
   22779                         mUserPaddingRightInitial = padding.left;
   22780                         internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
   22781                         break;
   22782                     case LAYOUT_DIRECTION_LTR:
   22783                     default:
   22784                         mUserPaddingLeftInitial = padding.left;
   22785                         mUserPaddingRightInitial = padding.right;
   22786                         internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
   22787                 }
   22788                 mLeftPaddingDefined = false;
   22789                 mRightPaddingDefined = false;
   22790             }
   22791 
   22792             // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
   22793             // if it has a different minimum size, we should layout again
   22794             if (mBackground == null
   22795                     || mBackground.getMinimumHeight() != background.getMinimumHeight()
   22796                     || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
   22797                 requestLayout = true;
   22798             }
   22799 
   22800             // Set mBackground before we set this as the callback and start making other
   22801             // background drawable state change calls. In particular, the setVisible call below
   22802             // can result in drawables attempting to start animations or otherwise invalidate,
   22803             // which requires the view set as the callback (us) to recognize the drawable as
   22804             // belonging to it as per verifyDrawable.
   22805             mBackground = background;
   22806             if (background.isStateful()) {
   22807                 background.setState(getDrawableState());
   22808             }
   22809             if (isAttachedToWindow()) {
   22810                 background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
   22811             }
   22812 
   22813             applyBackgroundTint();
   22814 
   22815             // Set callback last, since the view may still be initializing.
   22816             background.setCallback(this);
   22817 
   22818             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
   22819                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
   22820                 requestLayout = true;
   22821             }
   22822         } else {
   22823             /* Remove the background */
   22824             mBackground = null;
   22825             if ((mViewFlags & WILL_NOT_DRAW) != 0
   22826                     && (mDefaultFocusHighlight == null)
   22827                     && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
   22828                 mPrivateFlags |= PFLAG_SKIP_DRAW;
   22829             }
   22830 
   22831             /*
   22832              * When the background is set, we try to apply its padding to this
   22833              * View. When the background is removed, we don't touch this View's
   22834              * padding. This is noted in the Javadocs. Hence, we don't need to
   22835              * requestLayout(), the invalidate() below is sufficient.
   22836              */
   22837 
   22838             // The old background's minimum size could have affected this
   22839             // View's layout, so let's requestLayout
   22840             requestLayout = true;
   22841         }
   22842 
   22843         computeOpaqueFlags();
   22844 
   22845         if (requestLayout) {
   22846             requestLayout();
   22847         }
   22848 
   22849         mBackgroundSizeChanged = true;
   22850         invalidate(true);
   22851         invalidateOutline();
   22852     }
   22853 
   22854     /**
   22855      * Gets the background drawable
   22856      *
   22857      * @return The drawable used as the background for this view, if any.
   22858      *
   22859      * @see #setBackground(Drawable)
   22860      *
   22861      * @attr ref android.R.styleable#View_background
   22862      */
   22863     @InspectableProperty
   22864     public Drawable getBackground() {
   22865         return mBackground;
   22866     }
   22867 
   22868     /**
   22869      * Applies a tint to the background drawable. Does not modify the current tint
   22870      * mode, which is {@link BlendMode#SRC_IN} by default.
   22871      * <p>
   22872      * Subsequent calls to {@link #setBackground(Drawable)} will automatically
   22873      * mutate the drawable and apply the specified tint and tint mode using
   22874      * {@link Drawable#setTintList(ColorStateList)}.
   22875      *
   22876      * @param tint the tint to apply, may be {@code null} to clear tint
   22877      *
   22878      * @attr ref android.R.styleable#View_backgroundTint
   22879      * @see #getBackgroundTintList()
   22880      * @see Drawable#setTintList(ColorStateList)
   22881      */
   22882     public void setBackgroundTintList(@Nullable ColorStateList tint) {
   22883         if (mBackgroundTint == null) {
   22884             mBackgroundTint = new TintInfo();
   22885         }
   22886         mBackgroundTint.mTintList = tint;
   22887         mBackgroundTint.mHasTintList = true;
   22888 
   22889         applyBackgroundTint();
   22890     }
   22891 
   22892     /**
   22893      * Return the tint applied to the background drawable, if specified.
   22894      *
   22895      * @return the tint applied to the background drawable
   22896      * @attr ref android.R.styleable#View_backgroundTint
   22897      * @see #setBackgroundTintList(ColorStateList)
   22898      */
   22899     @InspectableProperty(name = "backgroundTint")
   22900     @Nullable
   22901     public ColorStateList getBackgroundTintList() {
   22902         return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
   22903     }
   22904 
   22905     /**
   22906      * Specifies the blending mode used to apply the tint specified by
   22907      * {@link #setBackgroundTintList(ColorStateList)}} to the background
   22908      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
   22909      *
   22910      * @param tintMode the blending mode used to apply the tint, may be
   22911      *                 {@code null} to clear tint
   22912      * @attr ref android.R.styleable#View_backgroundTintMode
   22913      * @see #getBackgroundTintMode()
   22914      * @see Drawable#setTintMode(PorterDuff.Mode)
   22915      */
   22916     public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
   22917         BlendMode mode = null;
   22918         if (tintMode != null) {
   22919             mode = BlendMode.fromValue(tintMode.nativeInt);
   22920         }
   22921 
   22922         setBackgroundTintBlendMode(mode);
   22923     }
   22924 
   22925     /**
   22926      * Specifies the blending mode used to apply the tint specified by
   22927      * {@link #setBackgroundTintList(ColorStateList)}} to the background
   22928      * drawable. The default mode is {@link BlendMode#SRC_IN}.
   22929      *
   22930      * @param blendMode the blending mode used to apply the tint, may be
   22931      *                 {@code null} to clear tint
   22932      * @attr ref android.R.styleable#View_backgroundTintMode
   22933      * @see #getBackgroundTintMode()
   22934      * @see Drawable#setTintBlendMode(BlendMode)
   22935      */
   22936     public void setBackgroundTintBlendMode(@Nullable BlendMode blendMode) {
   22937         if (mBackgroundTint == null) {
   22938             mBackgroundTint = new TintInfo();
   22939         }
   22940 
   22941         mBackgroundTint.mBlendMode = blendMode;
   22942         mBackgroundTint.mHasTintMode = true;
   22943 
   22944         applyBackgroundTint();
   22945     }
   22946 
   22947     /**
   22948      * Return the blending mode used to apply the tint to the background
   22949      * drawable, if specified.
   22950      *
   22951      * @return the blending mode used to apply the tint to the background
   22952      *         drawable
   22953      * @attr ref android.R.styleable#View_backgroundTintMode
   22954      * @see #setBackgroundTintBlendMode(BlendMode)
   22955      *
   22956      */
   22957     @Nullable
   22958     @InspectableProperty
   22959     public PorterDuff.Mode getBackgroundTintMode() {
   22960         PorterDuff.Mode porterDuffMode;
   22961         if (mBackgroundTint != null && mBackgroundTint.mBlendMode != null) {
   22962             porterDuffMode = BlendMode.blendModeToPorterDuffMode(mBackgroundTint.mBlendMode);
   22963         } else {
   22964             porterDuffMode = null;
   22965         }
   22966         return porterDuffMode;
   22967     }
   22968 
   22969     /**
   22970      * Return the blending mode used to apply the tint to the background
   22971      * drawable, if specified.
   22972      *
   22973      * @return the blending mode used to apply the tint to the background
   22974      *         drawable, null if no blend has previously been configured
   22975      * @attr ref android.R.styleable#View_backgroundTintMode
   22976      * @see #setBackgroundTintBlendMode(BlendMode)
   22977      */
   22978     public @Nullable BlendMode getBackgroundTintBlendMode() {
   22979         return mBackgroundTint != null ? mBackgroundTint.mBlendMode : null;
   22980     }
   22981 
   22982     private void applyBackgroundTint() {
   22983         if (mBackground != null && mBackgroundTint != null) {
   22984             final TintInfo tintInfo = mBackgroundTint;
   22985             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
   22986                 mBackground = mBackground.mutate();
   22987 
   22988                 if (tintInfo.mHasTintList) {
   22989                     mBackground.setTintList(tintInfo.mTintList);
   22990                 }
   22991 
   22992                 if (tintInfo.mHasTintMode) {
   22993                     mBackground.setTintBlendMode(tintInfo.mBlendMode);
   22994                 }
   22995 
   22996                 // The drawable (or one of its children) may not have been
   22997                 // stateful before applying the tint, so let's try again.
   22998                 if (mBackground.isStateful()) {
   22999                     mBackground.setState(getDrawableState());
   23000                 }
   23001             }
   23002         }
   23003     }
   23004 
   23005     /**
   23006      * Returns the drawable used as the foreground of this View. The
   23007      * foreground drawable, if non-null, is always drawn on top of the view's content.
   23008      *
   23009      * @return a Drawable or null if no foreground was set
   23010      *
   23011      * @see #onDrawForeground(Canvas)
   23012      */
   23013     @InspectableProperty
   23014     public Drawable getForeground() {
   23015         return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
   23016     }
   23017 
   23018     /**
   23019      * Supply a Drawable that is to be rendered on top of all of the content in the view.
   23020      *
   23021      * @param foreground the Drawable to be drawn on top of the children
   23022      *
   23023      * @attr ref android.R.styleable#View_foreground
   23024      */
   23025     public void setForeground(Drawable foreground) {
   23026         if (mForegroundInfo == null) {
   23027             if (foreground == null) {
   23028                 // Nothing to do.
   23029                 return;
   23030             }
   23031             mForegroundInfo = new ForegroundInfo();
   23032         }
   23033 
   23034         if (foreground == mForegroundInfo.mDrawable) {
   23035             // Nothing to do
   23036             return;
   23037         }
   23038 
   23039         if (mForegroundInfo.mDrawable != null) {
   23040             if (isAttachedToWindow()) {
   23041                 mForegroundInfo.mDrawable.setVisible(false, false);
   23042             }
   23043             mForegroundInfo.mDrawable.setCallback(null);
   23044             unscheduleDrawable(mForegroundInfo.mDrawable);
   23045         }
   23046 
   23047         mForegroundInfo.mDrawable = foreground;
   23048         mForegroundInfo.mBoundsChanged = true;
   23049         if (foreground != null) {
   23050             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
   23051                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
   23052             }
   23053             foreground.setLayoutDirection(getLayoutDirection());
   23054             if (foreground.isStateful()) {
   23055                 foreground.setState(getDrawableState());
   23056             }
   23057             applyForegroundTint();
   23058             if (isAttachedToWindow()) {
   23059                 foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
   23060             }
   23061             // Set callback last, since the view may still be initializing.
   23062             foreground.setCallback(this);
   23063         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
   23064                 && (mDefaultFocusHighlight == null)) {
   23065             mPrivateFlags |= PFLAG_SKIP_DRAW;
   23066         }
   23067         requestLayout();
   23068         invalidate();
   23069     }
   23070 
   23071     /**
   23072      * Magic bit used to support features of framework-internal window decor implementation details.
   23073      * This used to live exclusively in FrameLayout.
   23074      *
   23075      * @return true if the foreground should draw inside the padding region or false
   23076      *         if it should draw inset by the view's padding
   23077      * @hide internal use only; only used by FrameLayout and internal screen layouts.
   23078      */
   23079     public boolean isForegroundInsidePadding() {
   23080         return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
   23081     }
   23082 
   23083     /**
   23084      * Describes how the foreground is positioned.
   23085      *
   23086      * @return foreground gravity.
   23087      *
   23088      * @see #setForegroundGravity(int)
   23089      *
   23090      * @attr ref android.R.styleable#View_foregroundGravity
   23091      */
   23092     @InspectableProperty(valueType = InspectableProperty.ValueType.GRAVITY)
   23093     public int getForegroundGravity() {
   23094         return mForegroundInfo != null ? mForegroundInfo.mGravity
   23095                 : Gravity.START | Gravity.TOP;
   23096     }
   23097 
   23098     /**
   23099      * Describes how the foreground is positioned. Defaults to START and TOP.
   23100      *
   23101      * @param gravity see {@link android.view.Gravity}
   23102      *
   23103      * @see #getForegroundGravity()
   23104      *
   23105      * @attr ref android.R.styleable#View_foregroundGravity
   23106      */
   23107     public void setForegroundGravity(int gravity) {
   23108         if (mForegroundInfo == null) {
   23109             mForegroundInfo = new ForegroundInfo();
   23110         }
   23111 
   23112         if (mForegroundInfo.mGravity != gravity) {
   23113             if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
   23114                 gravity |= Gravity.START;
   23115             }
   23116 
   23117             if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
   23118                 gravity |= Gravity.TOP;
   23119             }
   23120 
   23121             mForegroundInfo.mGravity = gravity;
   23122             requestLayout();
   23123         }
   23124     }
   23125 
   23126     /**
   23127      * Applies a tint to the foreground drawable. Does not modify the current tint
   23128      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
   23129      * <p>
   23130      * Subsequent calls to {@link #setForeground(Drawable)} will automatically
   23131      * mutate the drawable and apply the specified tint and tint mode using
   23132      * {@link Drawable#setTintList(ColorStateList)}.
   23133      *
   23134      * @param tint the tint to apply, may be {@code null} to clear tint
   23135      *
   23136      * @attr ref android.R.styleable#View_foregroundTint
   23137      * @see #getForegroundTintList()
   23138      * @see Drawable#setTintList(ColorStateList)
   23139      */
   23140     public void setForegroundTintList(@Nullable ColorStateList tint) {
   23141         if (mForegroundInfo == null) {
   23142             mForegroundInfo = new ForegroundInfo();
   23143         }
   23144         if (mForegroundInfo.mTintInfo == null) {
   23145             mForegroundInfo.mTintInfo = new TintInfo();
   23146         }
   23147         mForegroundInfo.mTintInfo.mTintList = tint;
   23148         mForegroundInfo.mTintInfo.mHasTintList = true;
   23149 
   23150         applyForegroundTint();
   23151     }
   23152 
   23153     /**
   23154      * Return the tint applied to the foreground drawable, if specified.
   23155      *
   23156      * @return the tint applied to the foreground drawable
   23157      * @attr ref android.R.styleable#View_foregroundTint
   23158      * @see #setForegroundTintList(ColorStateList)
   23159      */
   23160     @InspectableProperty(name = "foregroundTint")
   23161     @Nullable
   23162     public ColorStateList getForegroundTintList() {
   23163         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
   23164                 ? mForegroundInfo.mTintInfo.mTintList : null;
   23165     }
   23166 
   23167     /**
   23168      * Specifies the blending mode used to apply the tint specified by
   23169      * {@link #setForegroundTintList(ColorStateList)}} to the background
   23170      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
   23171      *
   23172      * @param tintMode the blending mode used to apply the tint, may be
   23173      *                 {@code null} to clear tint
   23174      * @attr ref android.R.styleable#View_foregroundTintMode
   23175      * @see #getForegroundTintMode()
   23176      * @see Drawable#setTintMode(PorterDuff.Mode)
   23177      *
   23178      */
   23179     public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
   23180         BlendMode mode = null;
   23181         if (tintMode != null) {
   23182             mode = BlendMode.fromValue(tintMode.nativeInt);
   23183         }
   23184         setForegroundTintBlendMode(mode);
   23185     }
   23186 
   23187     /**
   23188      * Specifies the blending mode used to apply the tint specified by
   23189      * {@link #setForegroundTintList(ColorStateList)}} to the background
   23190      * drawable. The default mode is {@link BlendMode#SRC_IN}.
   23191      *
   23192      * @param blendMode the blending mode used to apply the tint, may be
   23193      *                 {@code null} to clear tint
   23194      * @attr ref android.R.styleable#View_foregroundTintMode
   23195      * @see #getForegroundTintMode()
   23196      * @see Drawable#setTintBlendMode(BlendMode)
   23197      */
   23198     public void setForegroundTintBlendMode(@Nullable BlendMode blendMode) {
   23199         if (mForegroundInfo == null) {
   23200             mForegroundInfo = new ForegroundInfo();
   23201         }
   23202         if (mForegroundInfo.mTintInfo == null) {
   23203             mForegroundInfo.mTintInfo = new TintInfo();
   23204         }
   23205         mForegroundInfo.mTintInfo.mBlendMode = blendMode;
   23206         mForegroundInfo.mTintInfo.mHasTintMode = true;
   23207 
   23208         applyForegroundTint();
   23209     }
   23210 
   23211     /**
   23212      * Return the blending mode used to apply the tint to the foreground
   23213      * drawable, if specified.
   23214      *
   23215      * @return the blending mode used to apply the tint to the foreground
   23216      *         drawable
   23217      * @attr ref android.R.styleable#View_foregroundTintMode
   23218      * @see #setForegroundTintMode(PorterDuff.Mode)
   23219      */
   23220     @InspectableProperty
   23221     @Nullable
   23222     public PorterDuff.Mode getForegroundTintMode() {
   23223         BlendMode blendMode = mForegroundInfo != null && mForegroundInfo.mTintInfo != null
   23224                 ? mForegroundInfo.mTintInfo.mBlendMode : null;
   23225         if (blendMode != null) {
   23226             return BlendMode.blendModeToPorterDuffMode(blendMode);
   23227         } else {
   23228             return null;
   23229         }
   23230     }
   23231 
   23232     /**
   23233      * Return the blending mode used to apply the tint to the foreground
   23234      * drawable, if specified.
   23235      *
   23236      * @return the blending mode used to apply the tint to the foreground
   23237      *         drawable
   23238      * @attr ref android.R.styleable#View_foregroundTintMode
   23239      * @see #setForegroundTintBlendMode(BlendMode)
   23240      *
   23241      */
   23242     public @Nullable BlendMode getForegroundTintBlendMode() {
   23243         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
   23244                 ? mForegroundInfo.mTintInfo.mBlendMode : null;
   23245     }
   23246 
   23247     private void applyForegroundTint() {
   23248         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
   23249                 && mForegroundInfo.mTintInfo != null) {
   23250             final TintInfo tintInfo = mForegroundInfo.mTintInfo;
   23251             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
   23252                 mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
   23253 
   23254                 if (tintInfo.mHasTintList) {
   23255                     mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
   23256                 }
   23257 
   23258                 if (tintInfo.mHasTintMode) {
   23259                     mForegroundInfo.mDrawable.setTintBlendMode(tintInfo.mBlendMode);
   23260                 }
   23261 
   23262                 // The drawable (or one of its children) may not have been
   23263                 // stateful before applying the tint, so let's try again.
   23264                 if (mForegroundInfo.mDrawable.isStateful()) {
   23265                     mForegroundInfo.mDrawable.setState(getDrawableState());
   23266                 }
   23267             }
   23268         }
   23269     }
   23270 
   23271     /**
   23272      * Get the drawable to be overlayed when a view is autofilled
   23273      *
   23274      * @return The drawable
   23275      *
   23276      * @throws IllegalStateException if the drawable could not be found.
   23277      */
   23278     @Nullable private Drawable getAutofilledDrawable() {
   23279         if (mAttachInfo == null) {
   23280             return null;
   23281         }
   23282         // Lazily load the isAutofilled drawable.
   23283         if (mAttachInfo.mAutofilledDrawable == null) {
   23284             Context rootContext = getRootView().getContext();
   23285             TypedArray a = rootContext.getTheme().obtainStyledAttributes(AUTOFILL_HIGHLIGHT_ATTR);
   23286             int attributeResourceId = a.getResourceId(0, 0);
   23287             mAttachInfo.mAutofilledDrawable = rootContext.getDrawable(attributeResourceId);
   23288             a.recycle();
   23289         }
   23290 
   23291         return mAttachInfo.mAutofilledDrawable;
   23292     }
   23293 
   23294     /**
   23295      * Draw {@link View#isAutofilled()} highlight over view if the view is autofilled.
   23296      *
   23297      * @param canvas The canvas to draw on
   23298      */
   23299     private void drawAutofilledHighlight(@NonNull Canvas canvas) {
   23300         if (isAutofilled()) {
   23301             Drawable autofilledHighlight = getAutofilledDrawable();
   23302 
   23303             if (autofilledHighlight != null) {
   23304                 autofilledHighlight.setBounds(0, 0, getWidth(), getHeight());
   23305                 autofilledHighlight.draw(canvas);
   23306             }
   23307         }
   23308     }
   23309 
   23310     /**
   23311      * Draw any foreground content for this view.
   23312      *
   23313      * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
   23314      * drawable or other view-specific decorations. The foreground is drawn on top of the
   23315      * primary view content.</p>
   23316      *
   23317      * @param canvas canvas to draw into
   23318      */
   23319     public void onDrawForeground(Canvas canvas) {
   23320         onDrawScrollIndicators(canvas);
   23321         onDrawScrollBars(canvas);
   23322 
   23323         final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
   23324         if (foreground != null) {
   23325             if (mForegroundInfo.mBoundsChanged) {
   23326                 mForegroundInfo.mBoundsChanged = false;
   23327                 final Rect selfBounds = mForegroundInfo.mSelfBounds;
   23328                 final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
   23329 
   23330                 if (mForegroundInfo.mInsidePadding) {
   23331                     selfBounds.set(0, 0, getWidth(), getHeight());
   23332                 } else {
   23333                     selfBounds.set(getPaddingLeft(), getPaddingTop(),
   23334                             getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
   23335                 }
   23336 
   23337                 final int ld = getLayoutDirection();
   23338                 Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
   23339                         foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
   23340                 foreground.setBounds(overlayBounds);
   23341             }
   23342 
   23343             foreground.draw(canvas);
   23344         }
   23345     }
   23346 
   23347     /**
   23348      * Sets the padding. The view may add on the space required to display
   23349      * the scrollbars, depending on the style and visibility of the scrollbars.
   23350      * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
   23351      * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
   23352      * from the values set in this call.
   23353      *
   23354      * @attr ref android.R.styleable#View_padding
   23355      * @attr ref android.R.styleable#View_paddingBottom
   23356      * @attr ref android.R.styleable#View_paddingLeft
   23357      * @attr ref android.R.styleable#View_paddingRight
   23358      * @attr ref android.R.styleable#View_paddingTop
   23359      * @param left the left padding in pixels
   23360      * @param top the top padding in pixels
   23361      * @param right the right padding in pixels
   23362      * @param bottom the bottom padding in pixels
   23363      */
   23364     public void setPadding(int left, int top, int right, int bottom) {
   23365         resetResolvedPaddingInternal();
   23366 
   23367         mUserPaddingStart = UNDEFINED_PADDING;
   23368         mUserPaddingEnd = UNDEFINED_PADDING;
   23369 
   23370         mUserPaddingLeftInitial = left;
   23371         mUserPaddingRightInitial = right;
   23372 
   23373         mLeftPaddingDefined = true;
   23374         mRightPaddingDefined = true;
   23375 
   23376         internalSetPadding(left, top, right, bottom);
   23377     }
   23378 
   23379     /**
   23380      * @hide
   23381      */
   23382     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768420)
   23383     protected void internalSetPadding(int left, int top, int right, int bottom) {
   23384         mUserPaddingLeft = left;
   23385         mUserPaddingRight = right;
   23386         mUserPaddingBottom = bottom;
   23387 
   23388         final int viewFlags = mViewFlags;
   23389         boolean changed = false;
   23390 
   23391         // Common case is there are no scroll bars.
   23392         if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
   23393             if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
   23394                 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
   23395                         ? 0 : getVerticalScrollbarWidth();
   23396                 switch (mVerticalScrollbarPosition) {
   23397                     case SCROLLBAR_POSITION_DEFAULT:
   23398                         if (isLayoutRtl()) {
   23399                             left += offset;
   23400                         } else {
   23401                             right += offset;
   23402                         }
   23403                         break;
   23404                     case SCROLLBAR_POSITION_RIGHT:
   23405                         right += offset;
   23406                         break;
   23407                     case SCROLLBAR_POSITION_LEFT:
   23408                         left += offset;
   23409                         break;
   23410                 }
   23411             }
   23412             if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
   23413                 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
   23414                         ? 0 : getHorizontalScrollbarHeight();
   23415             }
   23416         }
   23417 
   23418         if (mPaddingLeft != left) {
   23419             changed = true;
   23420             mPaddingLeft = left;
   23421         }
   23422         if (mPaddingTop != top) {
   23423             changed = true;
   23424             mPaddingTop = top;
   23425         }
   23426         if (mPaddingRight != right) {
   23427             changed = true;
   23428             mPaddingRight = right;
   23429         }
   23430         if (mPaddingBottom != bottom) {
   23431             changed = true;
   23432             mPaddingBottom = bottom;
   23433         }
   23434 
   23435         if (changed) {
   23436             requestLayout();
   23437             invalidateOutline();
   23438         }
   23439     }
   23440 
   23441     /**
   23442      * Sets the relative padding. The view may add on the space required to display
   23443      * the scrollbars, depending on the style and visibility of the scrollbars.
   23444      * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
   23445      * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
   23446      * from the values set in this call.
   23447      *
   23448      * @attr ref android.R.styleable#View_padding
   23449      * @attr ref android.R.styleable#View_paddingBottom
   23450      * @attr ref android.R.styleable#View_paddingStart
   23451      * @attr ref android.R.styleable#View_paddingEnd
   23452      * @attr ref android.R.styleable#View_paddingTop
   23453      * @param start the start padding in pixels
   23454      * @param top the top padding in pixels
   23455      * @param end the end padding in pixels
   23456      * @param bottom the bottom padding in pixels
   23457      */
   23458     public void setPaddingRelative(int start, int top, int end, int bottom) {
   23459         resetResolvedPaddingInternal();
   23460 
   23461         mUserPaddingStart = start;
   23462         mUserPaddingEnd = end;
   23463         mLeftPaddingDefined = true;
   23464         mRightPaddingDefined = true;
   23465 
   23466         switch(getLayoutDirection()) {
   23467             case LAYOUT_DIRECTION_RTL:
   23468                 mUserPaddingLeftInitial = end;
   23469                 mUserPaddingRightInitial = start;
   23470                 internalSetPadding(end, top, start, bottom);
   23471                 break;
   23472             case LAYOUT_DIRECTION_LTR:
   23473             default:
   23474                 mUserPaddingLeftInitial = start;
   23475                 mUserPaddingRightInitial = end;
   23476                 internalSetPadding(start, top, end, bottom);
   23477         }
   23478     }
   23479 
   23480     /**
   23481      * A {@link View} can be inflated from an XML layout. For such Views this method returns the
   23482      * resource ID of the source layout.
   23483      *
   23484      * @return The layout resource id if this view was inflated from XML, otherwise
   23485      * {@link Resources#ID_NULL}.
   23486      */
   23487     @LayoutRes
   23488     public int getSourceLayoutResId() {
   23489         return mSourceLayoutId;
   23490     }
   23491 
   23492     /**
   23493      * Returns the top padding of this view.
   23494      *
   23495      * @return the top padding in pixels
   23496      */
   23497     @InspectableProperty
   23498     public int getPaddingTop() {
   23499         return mPaddingTop;
   23500     }
   23501 
   23502     /**
   23503      * Returns the bottom padding of this view. If there are inset and enabled
   23504      * scrollbars, this value may include the space required to display the
   23505      * scrollbars as well.
   23506      *
   23507      * @return the bottom padding in pixels
   23508      */
   23509     @InspectableProperty
   23510     public int getPaddingBottom() {
   23511         return mPaddingBottom;
   23512     }
   23513 
   23514     /**
   23515      * Returns the left padding of this view. If there are inset and enabled
   23516      * scrollbars, this value may include the space required to display the
   23517      * scrollbars as well.
   23518      *
   23519      * @return the left padding in pixels
   23520      */
   23521     @InspectableProperty
   23522     public int getPaddingLeft() {
   23523         if (!isPaddingResolved()) {
   23524             resolvePadding();
   23525         }
   23526         return mPaddingLeft;
   23527     }
   23528 
   23529     /**
   23530      * Returns the start padding of this view depending on its resolved layout direction.
   23531      * If there are inset and enabled scrollbars, this value may include the space
   23532      * required to display the scrollbars as well.
   23533      *
   23534      * @return the start padding in pixels
   23535      */
   23536     public int getPaddingStart() {
   23537         if (!isPaddingResolved()) {
   23538             resolvePadding();
   23539         }
   23540         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
   23541                 mPaddingRight : mPaddingLeft;
   23542     }
   23543 
   23544     /**
   23545      * Returns the right padding of this view. If there are inset and enabled
   23546      * scrollbars, this value may include the space required to display the
   23547      * scrollbars as well.
   23548      *
   23549      * @return the right padding in pixels
   23550      */
   23551     @InspectableProperty
   23552     public int getPaddingRight() {
   23553         if (!isPaddingResolved()) {
   23554             resolvePadding();
   23555         }
   23556         return mPaddingRight;
   23557     }
   23558 
   23559     /**
   23560      * Returns the end padding of this view depending on its resolved layout direction.
   23561      * If there are inset and enabled scrollbars, this value may include the space
   23562      * required to display the scrollbars as well.
   23563      *
   23564      * @return the end padding in pixels
   23565      */
   23566     public int getPaddingEnd() {
   23567         if (!isPaddingResolved()) {
   23568             resolvePadding();
   23569         }
   23570         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
   23571                 mPaddingLeft : mPaddingRight;
   23572     }
   23573 
   23574     /**
   23575      * Return if the padding has been set through relative values
   23576      * {@link #setPaddingRelative(int, int, int, int)} or through
   23577      * @attr ref android.R.styleable#View_paddingStart or
   23578      * @attr ref android.R.styleable#View_paddingEnd
   23579      *
   23580      * @return true if the padding is relative or false if it is not.
   23581      */
   23582     public boolean isPaddingRelative() {
   23583         return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
   23584     }
   23585 
   23586     Insets computeOpticalInsets() {
   23587         return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
   23588     }
   23589 
   23590     /**
   23591      * @hide
   23592      */
   23593     @UnsupportedAppUsage
   23594     public void resetPaddingToInitialValues() {
   23595         if (isRtlCompatibilityMode()) {
   23596             mPaddingLeft = mUserPaddingLeftInitial;
   23597             mPaddingRight = mUserPaddingRightInitial;
   23598             return;
   23599         }
   23600         if (isLayoutRtl()) {
   23601             mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
   23602             mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
   23603         } else {
   23604             mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
   23605             mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
   23606         }
   23607     }
   23608 
   23609     /**
   23610      * @hide
   23611      */
   23612     public Insets getOpticalInsets() {
   23613         if (mLayoutInsets == null) {
   23614             mLayoutInsets = computeOpticalInsets();
   23615         }
   23616         return mLayoutInsets;
   23617     }
   23618 
   23619     /**
   23620      * Set this view's optical insets.
   23621      *
   23622      * <p>This method should be treated similarly to setMeasuredDimension and not as a general
   23623      * property. Views that compute their own optical insets should call it as part of measurement.
   23624      * This method does not request layout. If you are setting optical insets outside of
   23625      * measure/layout itself you will want to call requestLayout() yourself.
   23626      * </p>
   23627      * @hide
   23628      */
   23629     public void setOpticalInsets(Insets insets) {
   23630         mLayoutInsets = insets;
   23631     }
   23632 
   23633     /**
   23634      * Changes the selection state of this view. A view can be selected or not.
   23635      * Note that selection is not the same as focus. Views are typically
   23636      * selected in the context of an AdapterView like ListView or GridView;
   23637      * the selected view is the view that is highlighted.
   23638      *
   23639      * @param selected true if the view must be selected, false otherwise
   23640      */
   23641     public void setSelected(boolean selected) {
   23642         //noinspection DoubleNegation
   23643         if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
   23644             mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
   23645             if (!selected) resetPressedState();
   23646             invalidate(true);
   23647             refreshDrawableState();
   23648             dispatchSetSelected(selected);
   23649             if (selected) {
   23650                 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
   23651             } else {
   23652                 notifyViewAccessibilityStateChangedIfNeeded(
   23653                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   23654             }
   23655         }
   23656     }
   23657 
   23658     /**
   23659      * Dispatch setSelected to all of this View's children.
   23660      *
   23661      * @see #setSelected(boolean)
   23662      *
   23663      * @param selected The new selected state
   23664      */
   23665     protected void dispatchSetSelected(boolean selected) {
   23666     }
   23667 
   23668     /**
   23669      * Indicates the selection state of this view.
   23670      *
   23671      * @return true if the view is selected, false otherwise
   23672      */
   23673     @ViewDebug.ExportedProperty
   23674     @InspectableProperty(hasAttributeId = false)
   23675     public boolean isSelected() {
   23676         return (mPrivateFlags & PFLAG_SELECTED) != 0;
   23677     }
   23678 
   23679     /**
   23680      * Changes the activated state of this view. A view can be activated or not.
   23681      * Note that activation is not the same as selection.  Selection is
   23682      * a transient property, representing the view (hierarchy) the user is
   23683      * currently interacting with.  Activation is a longer-term state that the
   23684      * user can move views in and out of.  For example, in a list view with
   23685      * single or multiple selection enabled, the views in the current selection
   23686      * set are activated.  (Um, yeah, we are deeply sorry about the terminology
   23687      * here.)  The activated state is propagated down to children of the view it
   23688      * is set on.
   23689      *
   23690      * @param activated true if the view must be activated, false otherwise
   23691      */
   23692     public void setActivated(boolean activated) {
   23693         //noinspection DoubleNegation
   23694         if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
   23695             mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
   23696             invalidate(true);
   23697             refreshDrawableState();
   23698             dispatchSetActivated(activated);
   23699         }
   23700     }
   23701 
   23702     /**
   23703      * Dispatch setActivated to all of this View's children.
   23704      *
   23705      * @see #setActivated(boolean)
   23706      *
   23707      * @param activated The new activated state
   23708      */
   23709     protected void dispatchSetActivated(boolean activated) {
   23710     }
   23711 
   23712     /**
   23713      * Indicates the activation state of this view.
   23714      *
   23715      * @return true if the view is activated, false otherwise
   23716      */
   23717     @ViewDebug.ExportedProperty
   23718     @InspectableProperty(hasAttributeId = false)
   23719     public boolean isActivated() {
   23720         return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
   23721     }
   23722 
   23723     /**
   23724      * Returns the ViewTreeObserver for this view's hierarchy. The view tree
   23725      * observer can be used to get notifications when global events, like
   23726      * layout, happen.
   23727      *
   23728      * The returned ViewTreeObserver observer is not guaranteed to remain
   23729      * valid for the lifetime of this View. If the caller of this method keeps
   23730      * a long-lived reference to ViewTreeObserver, it should always check for
   23731      * the return value of {@link ViewTreeObserver#isAlive()}.
   23732      *
   23733      * @return The ViewTreeObserver for this view's hierarchy.
   23734      */
   23735     public ViewTreeObserver getViewTreeObserver() {
   23736         if (mAttachInfo != null) {
   23737             return mAttachInfo.mTreeObserver;
   23738         }
   23739         if (mFloatingTreeObserver == null) {
   23740             mFloatingTreeObserver = new ViewTreeObserver(mContext);
   23741         }
   23742         return mFloatingTreeObserver;
   23743     }
   23744 
   23745     /**
   23746      * <p>Finds the topmost view in the current view hierarchy.</p>
   23747      *
   23748      * @return the topmost view containing this view
   23749      */
   23750     public View getRootView() {
   23751         if (mAttachInfo != null) {
   23752             final View v = mAttachInfo.mRootView;
   23753             if (v != null) {
   23754                 return v;
   23755             }
   23756         }
   23757 
   23758         View parent = this;
   23759 
   23760         while (parent.mParent != null && parent.mParent instanceof View) {
   23761             parent = (View) parent.mParent;
   23762         }
   23763 
   23764         return parent;
   23765     }
   23766 
   23767     /**
   23768      * Transforms a motion event from view-local coordinates to on-screen
   23769      * coordinates.
   23770      *
   23771      * @param ev the view-local motion event
   23772      * @return false if the transformation could not be applied
   23773      * @hide
   23774      */
   23775     @UnsupportedAppUsage
   23776     public boolean toGlobalMotionEvent(MotionEvent ev) {
   23777         final AttachInfo info = mAttachInfo;
   23778         if (info == null) {
   23779             return false;
   23780         }
   23781 
   23782         final Matrix m = info.mTmpMatrix;
   23783         m.set(Matrix.IDENTITY_MATRIX);
   23784         transformMatrixToGlobal(m);
   23785         ev.transform(m);
   23786         return true;
   23787     }
   23788 
   23789     /**
   23790      * Transforms a motion event from on-screen coordinates to view-local
   23791      * coordinates.
   23792      *
   23793      * @param ev the on-screen motion event
   23794      * @return false if the transformation could not be applied
   23795      * @hide
   23796      */
   23797     @UnsupportedAppUsage
   23798     public boolean toLocalMotionEvent(MotionEvent ev) {
   23799         final AttachInfo info = mAttachInfo;
   23800         if (info == null) {
   23801             return false;
   23802         }
   23803 
   23804         final Matrix m = info.mTmpMatrix;
   23805         m.set(Matrix.IDENTITY_MATRIX);
   23806         transformMatrixToLocal(m);
   23807         ev.transform(m);
   23808         return true;
   23809     }
   23810 
   23811     /**
   23812      * Modifies the input matrix such that it maps view-local coordinates to
   23813      * on-screen coordinates.
   23814      *
   23815      * @param matrix input matrix to modify
   23816      */
   23817     public void transformMatrixToGlobal(@NonNull Matrix matrix) {
   23818         final ViewParent parent = mParent;
   23819         if (parent instanceof View) {
   23820             final View vp = (View) parent;
   23821             vp.transformMatrixToGlobal(matrix);
   23822             matrix.preTranslate(-vp.mScrollX, -vp.mScrollY);
   23823         } else if (parent instanceof ViewRootImpl) {
   23824             final ViewRootImpl vr = (ViewRootImpl) parent;
   23825             vr.transformMatrixToGlobal(matrix);
   23826             matrix.preTranslate(0, -vr.mCurScrollY);
   23827         }
   23828 
   23829         matrix.preTranslate(mLeft, mTop);
   23830 
   23831         if (!hasIdentityMatrix()) {
   23832             matrix.preConcat(getMatrix());
   23833         }
   23834     }
   23835 
   23836     /**
   23837      * Modifies the input matrix such that it maps on-screen coordinates to
   23838      * view-local coordinates.
   23839      *
   23840      * @param matrix input matrix to modify
   23841      */
   23842     public void transformMatrixToLocal(@NonNull Matrix matrix) {
   23843         final ViewParent parent = mParent;
   23844         if (parent instanceof View) {
   23845             final View vp = (View) parent;
   23846             vp.transformMatrixToLocal(matrix);
   23847             matrix.postTranslate(vp.mScrollX, vp.mScrollY);
   23848         } else if (parent instanceof ViewRootImpl) {
   23849             final ViewRootImpl vr = (ViewRootImpl) parent;
   23850             vr.transformMatrixToLocal(matrix);
   23851             matrix.postTranslate(0, vr.mCurScrollY);
   23852         }
   23853 
   23854         matrix.postTranslate(-mLeft, -mTop);
   23855 
   23856         if (!hasIdentityMatrix()) {
   23857             matrix.postConcat(getInverseMatrix());
   23858         }
   23859     }
   23860 
   23861     /**
   23862      * @hide
   23863      */
   23864     @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
   23865             @ViewDebug.IntToString(from = 0, to = "x"),
   23866             @ViewDebug.IntToString(from = 1, to = "y")
   23867     })
   23868     @UnsupportedAppUsage
   23869     public int[] getLocationOnScreen() {
   23870         int[] location = new int[2];
   23871         getLocationOnScreen(location);
   23872         return location;
   23873     }
   23874 
   23875     /**
   23876      * <p>Computes the coordinates of this view on the screen. The argument
   23877      * must be an array of two integers. After the method returns, the array
   23878      * contains the x and y location in that order.</p>
   23879      *
   23880      * @param outLocation an array of two integers in which to hold the coordinates
   23881      */
   23882     public void getLocationOnScreen(@Size(2) int[] outLocation) {
   23883         getLocationInWindow(outLocation);
   23884 
   23885         final AttachInfo info = mAttachInfo;
   23886         if (info != null) {
   23887             outLocation[0] += info.mWindowLeft;
   23888             outLocation[1] += info.mWindowTop;
   23889         }
   23890     }
   23891 
   23892     /**
   23893      * <p>Computes the coordinates of this view in its window. The argument
   23894      * must be an array of two integers. After the method returns, the array
   23895      * contains the x and y location in that order.</p>
   23896      *
   23897      * @param outLocation an array of two integers in which to hold the coordinates
   23898      */
   23899     public void getLocationInWindow(@Size(2) int[] outLocation) {
   23900         if (outLocation == null || outLocation.length < 2) {
   23901             throw new IllegalArgumentException("outLocation must be an array of two integers");
   23902         }
   23903 
   23904         outLocation[0] = 0;
   23905         outLocation[1] = 0;
   23906 
   23907         transformFromViewToWindowSpace(outLocation);
   23908     }
   23909 
   23910     /** @hide */
   23911     public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
   23912         if (inOutLocation == null || inOutLocation.length < 2) {
   23913             throw new IllegalArgumentException("inOutLocation must be an array of two integers");
   23914         }
   23915 
   23916         if (mAttachInfo == null) {
   23917             // When the view is not attached to a window, this method does not make sense
   23918             inOutLocation[0] = inOutLocation[1] = 0;
   23919             return;
   23920         }
   23921 
   23922         float position[] = mAttachInfo.mTmpTransformLocation;
   23923         position[0] = inOutLocation[0];
   23924         position[1] = inOutLocation[1];
   23925 
   23926         if (!hasIdentityMatrix()) {
   23927             getMatrix().mapPoints(position);
   23928         }
   23929 
   23930         position[0] += mLeft;
   23931         position[1] += mTop;
   23932 
   23933         ViewParent viewParent = mParent;
   23934         while (viewParent instanceof View) {
   23935             final View view = (View) viewParent;
   23936 
   23937             position[0] -= view.mScrollX;
   23938             position[1] -= view.mScrollY;
   23939 
   23940             if (!view.hasIdentityMatrix()) {
   23941                 view.getMatrix().mapPoints(position);
   23942             }
   23943 
   23944             position[0] += view.mLeft;
   23945             position[1] += view.mTop;
   23946 
   23947             viewParent = view.mParent;
   23948          }
   23949 
   23950         if (viewParent instanceof ViewRootImpl) {
   23951             // *cough*
   23952             final ViewRootImpl vr = (ViewRootImpl) viewParent;
   23953             position[1] -= vr.mCurScrollY;
   23954         }
   23955 
   23956         inOutLocation[0] = Math.round(position[0]);
   23957         inOutLocation[1] = Math.round(position[1]);
   23958     }
   23959 
   23960     /**
   23961      * @param id the id of the view to be found
   23962      * @return the view of the specified id, null if cannot be found
   23963      * @hide
   23964      */
   23965     protected <T extends View> T findViewTraversal(@IdRes int id) {
   23966         if (id == mID) {
   23967             return (T) this;
   23968         }
   23969         return null;
   23970     }
   23971 
   23972     /**
   23973      * @param tag the tag of the view to be found
   23974      * @return the view of specified tag, null if cannot be found
   23975      * @hide
   23976      */
   23977     protected <T extends View> T findViewWithTagTraversal(Object tag) {
   23978         if (tag != null && tag.equals(mTag)) {
   23979             return (T) this;
   23980         }
   23981         return null;
   23982     }
   23983 
   23984     /**
   23985      * @param predicate The predicate to evaluate.
   23986      * @param childToSkip If not null, ignores this child during the recursive traversal.
   23987      * @return The first view that matches the predicate or null.
   23988      * @hide
   23989      */
   23990     protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
   23991             View childToSkip) {
   23992         if (predicate.test(this)) {
   23993             return (T) this;
   23994         }
   23995         return null;
   23996     }
   23997 
   23998     /**
   23999      * Finds the first descendant view with the given ID, the view itself if
   24000      * the ID matches {@link #getId()}, or {@code null} if the ID is invalid
   24001      * (< 0) or there is no matching view in the hierarchy.
   24002      * <p>
   24003      * <strong>Note:</strong> In most cases -- depending on compiler support --
   24004      * the resulting view is automatically cast to the target class type. If
   24005      * the target class type is unconstrained, an explicit cast may be
   24006      * necessary.
   24007      *
   24008      * @param id the ID to search for
   24009      * @return a view with given ID if found, or {@code null} otherwise
   24010      * @see View#requireViewById(int)
   24011      */
   24012     @Nullable
   24013     public final <T extends View> T findViewById(@IdRes int id) {
   24014         if (id == NO_ID) {
   24015             return null;
   24016         }
   24017         return findViewTraversal(id);
   24018     }
   24019 
   24020     /**
   24021      * Finds the first descendant view with the given ID, the view itself if the ID matches
   24022      * {@link #getId()}, or throws an IllegalArgumentException if the ID is invalid or there is no
   24023      * matching view in the hierarchy.
   24024      * <p>
   24025      * <strong>Note:</strong> In most cases -- depending on compiler support --
   24026      * the resulting view is automatically cast to the target class type. If
   24027      * the target class type is unconstrained, an explicit cast may be
   24028      * necessary.
   24029      *
   24030      * @param id the ID to search for
   24031      * @return a view with given ID
   24032      * @see View#findViewById(int)
   24033      */
   24034     @NonNull
   24035     public final <T extends View> T requireViewById(@IdRes int id) {
   24036         T view = findViewById(id);
   24037         if (view == null) {
   24038             throw new IllegalArgumentException("ID does not reference a View inside this View");
   24039         }
   24040         return view;
   24041     }
   24042 
   24043     /**
   24044      * Performs the traversal to find a view by its unique and stable accessibility id.
   24045      *
   24046      * <strong>Note:</strong>This method does not stop at the root namespace
   24047      * boundary since the user can touch the screen at an arbitrary location
   24048      * potentially crossing the root namespace boundary which will send an
   24049      * accessibility event to accessibility services and they should be able
   24050      * to obtain the event source. Also accessibility ids are guaranteed to be
   24051      * unique in the window.
   24052      *
   24053      * @param accessibilityId The accessibility id.
   24054      * @return The found view.
   24055      * @hide
   24056      */
   24057     public <T extends View> T findViewByAccessibilityIdTraversal(int accessibilityId) {
   24058         if (getAccessibilityViewId() == accessibilityId) {
   24059             return (T) this;
   24060         }
   24061         return null;
   24062     }
   24063 
   24064     /**
   24065      * Performs the traversal to find a view by its autofill id.
   24066      *
   24067      * <strong>Note:</strong>This method does not stop at the root namespace
   24068      * boundary.
   24069      *
   24070      * @param autofillId The autofill id.
   24071      * @return The found view.
   24072      * @hide
   24073      */
   24074     public <T extends View> T findViewByAutofillIdTraversal(int autofillId) {
   24075         if (getAutofillViewId() == autofillId) {
   24076             return (T) this;
   24077         }
   24078         return null;
   24079     }
   24080 
   24081     /**
   24082      * Look for a child view with the given tag.  If this view has the given
   24083      * tag, return this view.
   24084      *
   24085      * @param tag The tag to search for, using "tag.equals(getTag())".
   24086      * @return The View that has the given tag in the hierarchy or null
   24087      */
   24088     public final <T extends View> T findViewWithTag(Object tag) {
   24089         if (tag == null) {
   24090             return null;
   24091         }
   24092         return findViewWithTagTraversal(tag);
   24093     }
   24094 
   24095     /**
   24096      * Look for a child view that matches the specified predicate.
   24097      * If this view matches the predicate, return this view.
   24098      *
   24099      * @param predicate The predicate to evaluate.
   24100      * @return The first view that matches the predicate or null.
   24101      * @hide
   24102      */
   24103     public final <T extends View> T findViewByPredicate(Predicate<View> predicate) {
   24104         return findViewByPredicateTraversal(predicate, null);
   24105     }
   24106 
   24107     /**
   24108      * Look for a child view that matches the specified predicate,
   24109      * starting with the specified view and its descendents and then
   24110      * recusively searching the ancestors and siblings of that view
   24111      * until this view is reached.
   24112      *
   24113      * This method is useful in cases where the predicate does not match
   24114      * a single unique view (perhaps multiple views use the same id)
   24115      * and we are trying to find the view that is "closest" in scope to the
   24116      * starting view.
   24117      *
   24118      * @param start The view to start from.
   24119      * @param predicate The predicate to evaluate.
   24120      * @return The first view that matches the predicate or null.
   24121      * @hide
   24122      */
   24123     public final <T extends View> T findViewByPredicateInsideOut(
   24124             View start, Predicate<View> predicate) {
   24125         View childToSkip = null;
   24126         for (;;) {
   24127             T view = start.findViewByPredicateTraversal(predicate, childToSkip);
   24128             if (view != null || start == this) {
   24129                 return view;
   24130             }
   24131 
   24132             ViewParent parent = start.getParent();
   24133             if (parent == null || !(parent instanceof View)) {
   24134                 return null;
   24135             }
   24136 
   24137             childToSkip = start;
   24138             start = (View) parent;
   24139         }
   24140     }
   24141 
   24142     /**
   24143      * Sets the identifier for this view. The identifier does not have to be
   24144      * unique in this view's hierarchy. The identifier should be a positive
   24145      * number.
   24146      *
   24147      * @see #NO_ID
   24148      * @see #getId()
   24149      * @see #findViewById(int)
   24150      *
   24151      * @param id a number used to identify the view
   24152      *
   24153      * @attr ref android.R.styleable#View_id
   24154      */
   24155     public void setId(@IdRes int id) {
   24156         mID = id;
   24157         if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
   24158             mID = generateViewId();
   24159         }
   24160     }
   24161 
   24162     /**
   24163      * {@hide}
   24164      *
   24165      * @param isRoot true if the view belongs to the root namespace, false
   24166      *        otherwise
   24167      */
   24168     @TestApi
   24169     public void setIsRootNamespace(boolean isRoot) {
   24170         if (isRoot) {
   24171             mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
   24172         } else {
   24173             mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
   24174         }
   24175     }
   24176 
   24177     /**
   24178      * {@hide}
   24179      *
   24180      * @return true if the view belongs to the root namespace, false otherwise
   24181      */
   24182     @UnsupportedAppUsage
   24183     public boolean isRootNamespace() {
   24184         return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
   24185     }
   24186 
   24187     /**
   24188      * Returns this view's identifier.
   24189      *
   24190      * @return a positive integer used to identify the view or {@link #NO_ID}
   24191      *         if the view has no ID
   24192      *
   24193      * @see #setId(int)
   24194      * @see #findViewById(int)
   24195      * @attr ref android.R.styleable#View_id
   24196      */
   24197     @IdRes
   24198     @ViewDebug.CapturedViewProperty
   24199     @InspectableProperty
   24200     public int getId() {
   24201         return mID;
   24202     }
   24203 
   24204     /**
   24205      * Get the identifier used for this view by the drawing system.
   24206      *
   24207      * @see RenderNode#getUniqueId()
   24208      * @return A long that uniquely identifies this view's drawing component
   24209      */
   24210     public long getUniqueDrawingId() {
   24211         return mRenderNode.getUniqueId();
   24212     }
   24213 
   24214     /**
   24215      * Returns this view's tag.
   24216      *
   24217      * @return the Object stored in this view as a tag, or {@code null} if not
   24218      *         set
   24219      *
   24220      * @see #setTag(Object)
   24221      * @see #getTag(int)
   24222      */
   24223     @ViewDebug.ExportedProperty
   24224     @InspectableProperty
   24225     public Object getTag() {
   24226         return mTag;
   24227     }
   24228 
   24229     /**
   24230      * Sets the tag associated with this view. A tag can be used to mark
   24231      * a view in its hierarchy and does not have to be unique within the
   24232      * hierarchy. Tags can also be used to store data within a view without
   24233      * resorting to another data structure.
   24234      *
   24235      * @param tag an Object to tag the view with
   24236      *
   24237      * @see #getTag()
   24238      * @see #setTag(int, Object)
   24239      */
   24240     public void setTag(final Object tag) {
   24241         mTag = tag;
   24242     }
   24243 
   24244     /**
   24245      * Returns the tag associated with this view and the specified key.
   24246      *
   24247      * @param key The key identifying the tag
   24248      *
   24249      * @return the Object stored in this view as a tag, or {@code null} if not
   24250      *         set
   24251      *
   24252      * @see #setTag(int, Object)
   24253      * @see #getTag()
   24254      */
   24255     public Object getTag(int key) {
   24256         if (mKeyedTags != null) return mKeyedTags.get(key);
   24257         return null;
   24258     }
   24259 
   24260     /**
   24261      * Sets a tag associated with this view and a key. A tag can be used
   24262      * to mark a view in its hierarchy and does not have to be unique within
   24263      * the hierarchy. Tags can also be used to store data within a view
   24264      * without resorting to another data structure.
   24265      *
   24266      * The specified key should be an id declared in the resources of the
   24267      * application to ensure it is unique (see the <a
   24268      * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
   24269      * Keys identified as belonging to
   24270      * the Android framework or not associated with any package will cause
   24271      * an {@link IllegalArgumentException} to be thrown.
   24272      *
   24273      * @param key The key identifying the tag
   24274      * @param tag An Object to tag the view with
   24275      *
   24276      * @throws IllegalArgumentException If they specified key is not valid
   24277      *
   24278      * @see #setTag(Object)
   24279      * @see #getTag(int)
   24280      */
   24281     public void setTag(int key, final Object tag) {
   24282         // If the package id is 0x00 or 0x01, it's either an undefined package
   24283         // or a framework id
   24284         if ((key >>> 24) < 2) {
   24285             throw new IllegalArgumentException("The key must be an application-specific "
   24286                     + "resource id.");
   24287         }
   24288 
   24289         setKeyedTag(key, tag);
   24290     }
   24291 
   24292     /**
   24293      * Variation of {@link #setTag(int, Object)} that enforces the key to be a
   24294      * framework id.
   24295      *
   24296      * @hide
   24297      */
   24298     @UnsupportedAppUsage
   24299     public void setTagInternal(int key, Object tag) {
   24300         if ((key >>> 24) != 0x1) {
   24301             throw new IllegalArgumentException("The key must be a framework-specific "
   24302                     + "resource id.");
   24303         }
   24304 
   24305         setKeyedTag(key, tag);
   24306     }
   24307 
   24308     private void setKeyedTag(int key, Object tag) {
   24309         if (mKeyedTags == null) {
   24310             mKeyedTags = new SparseArray<Object>(2);
   24311         }
   24312 
   24313         mKeyedTags.put(key, tag);
   24314     }
   24315 
   24316     /**
   24317      * Prints information about this view in the log output, with the tag
   24318      * {@link #VIEW_LOG_TAG}.
   24319      *
   24320      * @hide
   24321      */
   24322     @UnsupportedAppUsage
   24323     public void debug() {
   24324         debug(0);
   24325     }
   24326 
   24327     /**
   24328      * Prints information about this view in the log output, with the tag
   24329      * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
   24330      * indentation defined by the <code>depth</code>.
   24331      *
   24332      * @param depth the indentation level
   24333      *
   24334      * @hide
   24335      */
   24336     @UnsupportedAppUsage
   24337     protected void debug(int depth) {
   24338         String output = debugIndent(depth - 1);
   24339 
   24340         output += "+ " + this;
   24341         int id = getId();
   24342         if (id != -1) {
   24343             output += " (id=" + id + ")";
   24344         }
   24345         Object tag = getTag();
   24346         if (tag != null) {
   24347             output += " (tag=" + tag + ")";
   24348         }
   24349         Log.d(VIEW_LOG_TAG, output);
   24350 
   24351         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
   24352             output = debugIndent(depth) + " FOCUSED";
   24353             Log.d(VIEW_LOG_TAG, output);
   24354         }
   24355 
   24356         output = debugIndent(depth);
   24357         output += "frame={" + mLeft + ", " + mTop + ", " + mRight
   24358                 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
   24359                 + "} ";
   24360         Log.d(VIEW_LOG_TAG, output);
   24361 
   24362         if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
   24363                 || mPaddingBottom != 0) {
   24364             output = debugIndent(depth);
   24365             output += "padding={" + mPaddingLeft + ", " + mPaddingTop
   24366                     + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
   24367             Log.d(VIEW_LOG_TAG, output);
   24368         }
   24369 
   24370         output = debugIndent(depth);
   24371         output += "mMeasureWidth=" + mMeasuredWidth +
   24372                 " mMeasureHeight=" + mMeasuredHeight;
   24373         Log.d(VIEW_LOG_TAG, output);
   24374 
   24375         output = debugIndent(depth);
   24376         if (mLayoutParams == null) {
   24377             output += "BAD! no layout params";
   24378         } else {
   24379             output = mLayoutParams.debug(output);
   24380         }
   24381         Log.d(VIEW_LOG_TAG, output);
   24382 
   24383         output = debugIndent(depth);
   24384         output += "flags={";
   24385         output += View.printFlags(mViewFlags);
   24386         output += "}";
   24387         Log.d(VIEW_LOG_TAG, output);
   24388 
   24389         output = debugIndent(depth);
   24390         output += "privateFlags={";
   24391         output += View.printPrivateFlags(mPrivateFlags);
   24392         output += "}";
   24393         Log.d(VIEW_LOG_TAG, output);
   24394     }
   24395 
   24396     /**
   24397      * Creates a string of whitespaces used for indentation.
   24398      *
   24399      * @param depth the indentation level
   24400      * @return a String containing (depth * 2 + 3) * 2 white spaces
   24401      *
   24402      * @hide
   24403      */
   24404     protected static String debugIndent(int depth) {
   24405         StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
   24406         for (int i = 0; i < (depth * 2) + 3; i++) {
   24407             spaces.append(' ').append(' ');
   24408         }
   24409         return spaces.toString();
   24410     }
   24411 
   24412     /**
   24413      * <p>Return the offset of the widget's text baseline from the widget's top
   24414      * boundary. If this widget does not support baseline alignment, this
   24415      * method returns -1. </p>
   24416      *
   24417      * @return the offset of the baseline within the widget's bounds or -1
   24418      *         if baseline alignment is not supported
   24419      */
   24420     @ViewDebug.ExportedProperty(category = "layout")
   24421     @InspectableProperty
   24422     public int getBaseline() {
   24423         return -1;
   24424     }
   24425 
   24426     /**
   24427      * Returns whether the view hierarchy is currently undergoing a layout pass. This
   24428      * information is useful to avoid situations such as calling {@link #requestLayout()} during
   24429      * a layout pass.
   24430      *
   24431      * @return whether the view hierarchy is currently undergoing a layout pass
   24432      */
   24433     public boolean isInLayout() {
   24434         ViewRootImpl viewRoot = getViewRootImpl();
   24435         return (viewRoot != null && viewRoot.isInLayout());
   24436     }
   24437 
   24438     /**
   24439      * Call this when something has changed which has invalidated the
   24440      * layout of this view. This will schedule a layout pass of the view
   24441      * tree. This should not be called while the view hierarchy is currently in a layout
   24442      * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
   24443      * end of the current layout pass (and then layout will run again) or after the current
   24444      * frame is drawn and the next layout occurs.
   24445      *
   24446      * <p>Subclasses which override this method should call the superclass method to
   24447      * handle possible request-during-layout errors correctly.</p>
   24448      */
   24449     @CallSuper
   24450     public void requestLayout() {
   24451         if (mMeasureCache != null) mMeasureCache.clear();
   24452 
   24453         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
   24454             // Only trigger request-during-layout logic if this is the view requesting it,
   24455             // not the views in its parent hierarchy
   24456             ViewRootImpl viewRoot = getViewRootImpl();
   24457             if (viewRoot != null && viewRoot.isInLayout()) {
   24458                 if (!viewRoot.requestLayoutDuringLayout(this)) {
   24459                     return;
   24460                 }
   24461             }
   24462             mAttachInfo.mViewRequestingLayout = this;
   24463         }
   24464 
   24465         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
   24466         mPrivateFlags |= PFLAG_INVALIDATED;
   24467 
   24468         if (mParent != null && !mParent.isLayoutRequested()) {
   24469             mParent.requestLayout();
   24470         }
   24471         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
   24472             mAttachInfo.mViewRequestingLayout = null;
   24473         }
   24474     }
   24475 
   24476     /**
   24477      * Forces this view to be laid out during the next layout pass.
   24478      * This method does not call requestLayout() or forceLayout()
   24479      * on the parent.
   24480      */
   24481     public void forceLayout() {
   24482         if (mMeasureCache != null) mMeasureCache.clear();
   24483 
   24484         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
   24485         mPrivateFlags |= PFLAG_INVALIDATED;
   24486     }
   24487 
   24488     /**
   24489      * <p>
   24490      * This is called to find out how big a view should be. The parent
   24491      * supplies constraint information in the width and height parameters.
   24492      * </p>
   24493      *
   24494      * <p>
   24495      * The actual measurement work of a view is performed in
   24496      * {@link #onMeasure(int, int)}, called by this method. Therefore, only
   24497      * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
   24498      * </p>
   24499      *
   24500      *
   24501      * @param widthMeasureSpec Horizontal space requirements as imposed by the
   24502      *        parent
   24503      * @param heightMeasureSpec Vertical space requirements as imposed by the
   24504      *        parent
   24505      *
   24506      * @see #onMeasure(int, int)
   24507      */
   24508     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
   24509         boolean optical = isLayoutModeOptical(this);
   24510         if (optical != isLayoutModeOptical(mParent)) {
   24511             Insets insets = getOpticalInsets();
   24512             int oWidth  = insets.left + insets.right;
   24513             int oHeight = insets.top  + insets.bottom;
   24514             widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
   24515             heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
   24516         }
   24517 
   24518         // Suppress sign extension for the low bytes
   24519         long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
   24520         if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
   24521 
   24522         final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
   24523 
   24524         // Optimize layout by avoiding an extra EXACTLY pass when the view is
   24525         // already measured as the correct size. In API 23 and below, this
   24526         // extra pass is required to make LinearLayout re-distribute weight.
   24527         final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
   24528                 || heightMeasureSpec != mOldHeightMeasureSpec;
   24529         final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
   24530                 && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
   24531         final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
   24532                 && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
   24533         final boolean needsLayout = specChanged
   24534                 && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
   24535 
   24536         if (forceLayout || needsLayout) {
   24537             // first clears the measured dimension flag
   24538             mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
   24539 
   24540             resolveRtlPropertiesIfNeeded();
   24541 
   24542             int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
   24543             if (cacheIndex < 0 || sIgnoreMeasureCache) {
   24544                 // measure ourselves, this should set the measured dimension flag back
   24545                 onMeasure(widthMeasureSpec, heightMeasureSpec);
   24546                 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
   24547             } else {
   24548                 long value = mMeasureCache.valueAt(cacheIndex);
   24549                 // Casting a long to int drops the high 32 bits, no mask needed
   24550                 setMeasuredDimensionRaw((int) (value >> 32), (int) value);
   24551                 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
   24552             }
   24553 
   24554             // flag not set, setMeasuredDimension() was not invoked, we raise
   24555             // an exception to warn the developer
   24556             if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
   24557                 throw new IllegalStateException("View with id " + getId() + ": "
   24558                         + getClass().getName() + "#onMeasure() did not set the"
   24559                         + " measured dimension by calling"
   24560                         + " setMeasuredDimension()");
   24561             }
   24562 
   24563             mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
   24564         }
   24565 
   24566         mOldWidthMeasureSpec = widthMeasureSpec;
   24567         mOldHeightMeasureSpec = heightMeasureSpec;
   24568 
   24569         mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
   24570                 (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
   24571     }
   24572 
   24573     /**
   24574      * <p>
   24575      * Measure the view and its content to determine the measured width and the
   24576      * measured height. This method is invoked by {@link #measure(int, int)} and
   24577      * should be overridden by subclasses to provide accurate and efficient
   24578      * measurement of their contents.
   24579      * </p>
   24580      *
   24581      * <p>
   24582      * <strong>CONTRACT:</strong> When overriding this method, you
   24583      * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
   24584      * measured width and height of this view. Failure to do so will trigger an
   24585      * <code>IllegalStateException</code>, thrown by
   24586      * {@link #measure(int, int)}. Calling the superclass'
   24587      * {@link #onMeasure(int, int)} is a valid use.
   24588      * </p>
   24589      *
   24590      * <p>
   24591      * The base class implementation of measure defaults to the background size,
   24592      * unless a larger size is allowed by the MeasureSpec. Subclasses should
   24593      * override {@link #onMeasure(int, int)} to provide better measurements of
   24594      * their content.
   24595      * </p>
   24596      *
   24597      * <p>
   24598      * If this method is overridden, it is the subclass's responsibility to make
   24599      * sure the measured height and width are at least the view's minimum height
   24600      * and width ({@link #getSuggestedMinimumHeight()} and
   24601      * {@link #getSuggestedMinimumWidth()}).
   24602      * </p>
   24603      *
   24604      * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
   24605      *                         The requirements are encoded with
   24606      *                         {@link android.view.View.MeasureSpec}.
   24607      * @param heightMeasureSpec vertical space requirements as imposed by the parent.
   24608      *                         The requirements are encoded with
   24609      *                         {@link android.view.View.MeasureSpec}.
   24610      *
   24611      * @see #getMeasuredWidth()
   24612      * @see #getMeasuredHeight()
   24613      * @see #setMeasuredDimension(int, int)
   24614      * @see #getSuggestedMinimumHeight()
   24615      * @see #getSuggestedMinimumWidth()
   24616      * @see android.view.View.MeasureSpec#getMode(int)
   24617      * @see android.view.View.MeasureSpec#getSize(int)
   24618      */
   24619     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
   24620         setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
   24621                 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
   24622     }
   24623 
   24624     /**
   24625      * <p>This method must be called by {@link #onMeasure(int, int)} to store the
   24626      * measured width and measured height. Failing to do so will trigger an
   24627      * exception at measurement time.</p>
   24628      *
   24629      * @param measuredWidth The measured width of this view.  May be a complex
   24630      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
   24631      * {@link #MEASURED_STATE_TOO_SMALL}.
   24632      * @param measuredHeight The measured height of this view.  May be a complex
   24633      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
   24634      * {@link #MEASURED_STATE_TOO_SMALL}.
   24635      */
   24636     protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
   24637         boolean optical = isLayoutModeOptical(this);
   24638         if (optical != isLayoutModeOptical(mParent)) {
   24639             Insets insets = getOpticalInsets();
   24640             int opticalWidth  = insets.left + insets.right;
   24641             int opticalHeight = insets.top  + insets.bottom;
   24642 
   24643             measuredWidth  += optical ? opticalWidth  : -opticalWidth;
   24644             measuredHeight += optical ? opticalHeight : -opticalHeight;
   24645         }
   24646         setMeasuredDimensionRaw(measuredWidth, measuredHeight);
   24647     }
   24648 
   24649     /**
   24650      * Sets the measured dimension without extra processing for things like optical bounds.
   24651      * Useful for reapplying consistent values that have already been cooked with adjustments
   24652      * for optical bounds, etc. such as those from the measurement cache.
   24653      *
   24654      * @param measuredWidth The measured width of this view.  May be a complex
   24655      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
   24656      * {@link #MEASURED_STATE_TOO_SMALL}.
   24657      * @param measuredHeight The measured height of this view.  May be a complex
   24658      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
   24659      * {@link #MEASURED_STATE_TOO_SMALL}.
   24660      */
   24661     private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
   24662         mMeasuredWidth = measuredWidth;
   24663         mMeasuredHeight = measuredHeight;
   24664 
   24665         mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
   24666     }
   24667 
   24668     /**
   24669      * Merge two states as returned by {@link #getMeasuredState()}.
   24670      * @param curState The current state as returned from a view or the result
   24671      * of combining multiple views.
   24672      * @param newState The new view state to combine.
   24673      * @return Returns a new integer reflecting the combination of the two
   24674      * states.
   24675      */
   24676     public static int combineMeasuredStates(int curState, int newState) {
   24677         return curState | newState;
   24678     }
   24679 
   24680     /**
   24681      * Version of {@link #resolveSizeAndState(int, int, int)}
   24682      * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
   24683      */
   24684     public static int resolveSize(int size, int measureSpec) {
   24685         return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
   24686     }
   24687 
   24688     /**
   24689      * Utility to reconcile a desired size and state, with constraints imposed
   24690      * by a MeasureSpec. Will take the desired size, unless a different size
   24691      * is imposed by the constraints. The returned value is a compound integer,
   24692      * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
   24693      * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
   24694      * resulting size is smaller than the size the view wants to be.
   24695      *
   24696      * @param size How big the view wants to be.
   24697      * @param measureSpec Constraints imposed by the parent.
   24698      * @param childMeasuredState Size information bit mask for the view's
   24699      *                           children.
   24700      * @return Size information bit mask as defined by
   24701      *         {@link #MEASURED_SIZE_MASK} and
   24702      *         {@link #MEASURED_STATE_TOO_SMALL}.
   24703      */
   24704     public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
   24705         final int specMode = MeasureSpec.getMode(measureSpec);
   24706         final int specSize = MeasureSpec.getSize(measureSpec);
   24707         final int result;
   24708         switch (specMode) {
   24709             case MeasureSpec.AT_MOST:
   24710                 if (specSize < size) {
   24711                     result = specSize | MEASURED_STATE_TOO_SMALL;
   24712                 } else {
   24713                     result = size;
   24714                 }
   24715                 break;
   24716             case MeasureSpec.EXACTLY:
   24717                 result = specSize;
   24718                 break;
   24719             case MeasureSpec.UNSPECIFIED:
   24720             default:
   24721                 result = size;
   24722         }
   24723         return result | (childMeasuredState & MEASURED_STATE_MASK);
   24724     }
   24725 
   24726     /**
   24727      * Utility to return a default size. Uses the supplied size if the
   24728      * MeasureSpec imposed no constraints. Will get larger if allowed
   24729      * by the MeasureSpec.
   24730      *
   24731      * @param size Default size for this view
   24732      * @param measureSpec Constraints imposed by the parent
   24733      * @return The size this view should be.
   24734      */
   24735     public static int getDefaultSize(int size, int measureSpec) {
   24736         int result = size;
   24737         int specMode = MeasureSpec.getMode(measureSpec);
   24738         int specSize = MeasureSpec.getSize(measureSpec);
   24739 
   24740         switch (specMode) {
   24741         case MeasureSpec.UNSPECIFIED:
   24742             result = size;
   24743             break;
   24744         case MeasureSpec.AT_MOST:
   24745         case MeasureSpec.EXACTLY:
   24746             result = specSize;
   24747             break;
   24748         }
   24749         return result;
   24750     }
   24751 
   24752     /**
   24753      * Returns the suggested minimum height that the view should use. This
   24754      * returns the maximum of the view's minimum height
   24755      * and the background's minimum height
   24756      * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
   24757      * <p>
   24758      * When being used in {@link #onMeasure(int, int)}, the caller should still
   24759      * ensure the returned height is within the requirements of the parent.
   24760      *
   24761      * @return The suggested minimum height of the view.
   24762      */
   24763     protected int getSuggestedMinimumHeight() {
   24764         return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
   24765 
   24766     }
   24767 
   24768     /**
   24769      * Returns the suggested minimum width that the view should use. This
   24770      * returns the maximum of the view's minimum width
   24771      * and the background's minimum width
   24772      *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
   24773      * <p>
   24774      * When being used in {@link #onMeasure(int, int)}, the caller should still
   24775      * ensure the returned width is within the requirements of the parent.
   24776      *
   24777      * @return The suggested minimum width of the view.
   24778      */
   24779     protected int getSuggestedMinimumWidth() {
   24780         return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
   24781     }
   24782 
   24783     /**
   24784      * Returns the minimum height of the view.
   24785      *
   24786      * @return the minimum height the view will try to be, in pixels
   24787      *
   24788      * @see #setMinimumHeight(int)
   24789      *
   24790      * @attr ref android.R.styleable#View_minHeight
   24791      */
   24792     @InspectableProperty(name = "minHeight")
   24793     public int getMinimumHeight() {
   24794         return mMinHeight;
   24795     }
   24796 
   24797     /**
   24798      * Sets the minimum height of the view. It is not guaranteed the view will
   24799      * be able to achieve this minimum height (for example, if its parent layout
   24800      * constrains it with less available height).
   24801      *
   24802      * @param minHeight The minimum height the view will try to be, in pixels
   24803      *
   24804      * @see #getMinimumHeight()
   24805      *
   24806      * @attr ref android.R.styleable#View_minHeight
   24807      */
   24808     @RemotableViewMethod
   24809     public void setMinimumHeight(int minHeight) {
   24810         mMinHeight = minHeight;
   24811         requestLayout();
   24812     }
   24813 
   24814     /**
   24815      * Returns the minimum width of the view.
   24816      *
   24817      * @return the minimum width the view will try to be, in pixels
   24818      *
   24819      * @see #setMinimumWidth(int)
   24820      *
   24821      * @attr ref android.R.styleable#View_minWidth
   24822      */
   24823     @InspectableProperty(name = "minWidth")
   24824     public int getMinimumWidth() {
   24825         return mMinWidth;
   24826     }
   24827 
   24828     /**
   24829      * Sets the minimum width of the view. It is not guaranteed the view will
   24830      * be able to achieve this minimum width (for example, if its parent layout
   24831      * constrains it with less available width).
   24832      *
   24833      * @param minWidth The minimum width the view will try to be, in pixels
   24834      *
   24835      * @see #getMinimumWidth()
   24836      *
   24837      * @attr ref android.R.styleable#View_minWidth
   24838      */
   24839     public void setMinimumWidth(int minWidth) {
   24840         mMinWidth = minWidth;
   24841         requestLayout();
   24842 
   24843     }
   24844 
   24845     /**
   24846      * Get the animation currently associated with this view.
   24847      *
   24848      * @return The animation that is currently playing or
   24849      *         scheduled to play for this view.
   24850      */
   24851     public Animation getAnimation() {
   24852         return mCurrentAnimation;
   24853     }
   24854 
   24855     /**
   24856      * Start the specified animation now.
   24857      *
   24858      * @param animation the animation to start now
   24859      */
   24860     public void startAnimation(Animation animation) {
   24861         animation.setStartTime(Animation.START_ON_FIRST_FRAME);
   24862         setAnimation(animation);
   24863         invalidateParentCaches();
   24864         invalidate(true);
   24865     }
   24866 
   24867     /**
   24868      * Cancels any animations for this view.
   24869      */
   24870     public void clearAnimation() {
   24871         if (mCurrentAnimation != null) {
   24872             mCurrentAnimation.detach();
   24873         }
   24874         mCurrentAnimation = null;
   24875         invalidateParentIfNeeded();
   24876     }
   24877 
   24878     /**
   24879      * Sets the next animation to play for this view.
   24880      * If you want the animation to play immediately, use
   24881      * {@link #startAnimation(android.view.animation.Animation)} instead.
   24882      * This method provides allows fine-grained
   24883      * control over the start time and invalidation, but you
   24884      * must make sure that 1) the animation has a start time set, and
   24885      * 2) the view's parent (which controls animations on its children)
   24886      * will be invalidated when the animation is supposed to
   24887      * start.
   24888      *
   24889      * @param animation The next animation, or null.
   24890      */
   24891     public void setAnimation(Animation animation) {
   24892         mCurrentAnimation = animation;
   24893 
   24894         if (animation != null) {
   24895             // If the screen is off assume the animation start time is now instead of
   24896             // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
   24897             // would cause the animation to start when the screen turns back on
   24898             if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
   24899                     && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
   24900                 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
   24901             }
   24902             animation.reset();
   24903         }
   24904     }
   24905 
   24906     /**
   24907      * Invoked by a parent ViewGroup to notify the start of the animation
   24908      * currently associated with this view. If you override this method,
   24909      * always call super.onAnimationStart();
   24910      *
   24911      * @see #setAnimation(android.view.animation.Animation)
   24912      * @see #getAnimation()
   24913      */
   24914     @CallSuper
   24915     protected void onAnimationStart() {
   24916         mPrivateFlags |= PFLAG_ANIMATION_STARTED;
   24917     }
   24918 
   24919     /**
   24920      * Invoked by a parent ViewGroup to notify the end of the animation
   24921      * currently associated with this view. If you override this method,
   24922      * always call super.onAnimationEnd();
   24923      *
   24924      * @see #setAnimation(android.view.animation.Animation)
   24925      * @see #getAnimation()
   24926      */
   24927     @CallSuper
   24928     protected void onAnimationEnd() {
   24929         mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
   24930     }
   24931 
   24932     /**
   24933      * Invoked if there is a Transform that involves alpha. Subclass that can
   24934      * draw themselves with the specified alpha should return true, and then
   24935      * respect that alpha when their onDraw() is called. If this returns false
   24936      * then the view may be redirected to draw into an offscreen buffer to
   24937      * fulfill the request, which will look fine, but may be slower than if the
   24938      * subclass handles it internally. The default implementation returns false.
   24939      *
   24940      * @param alpha The alpha (0..255) to apply to the view's drawing
   24941      * @return true if the view can draw with the specified alpha.
   24942      */
   24943     protected boolean onSetAlpha(int alpha) {
   24944         return false;
   24945     }
   24946 
   24947     /**
   24948      * This is used by the RootView to perform an optimization when
   24949      * the view hierarchy contains one or several SurfaceView.
   24950      * SurfaceView is always considered transparent, but its children are not,
   24951      * therefore all View objects remove themselves from the global transparent
   24952      * region (passed as a parameter to this function).
   24953      *
   24954      * @param region The transparent region for this ViewAncestor (window).
   24955      *
   24956      * @return Returns true if the effective visibility of the view at this
   24957      * point is opaque, regardless of the transparent region; returns false
   24958      * if it is possible for underlying windows to be seen behind the view.
   24959      *
   24960      * {@hide}
   24961      */
   24962     @UnsupportedAppUsage
   24963     public boolean gatherTransparentRegion(Region region) {
   24964         final AttachInfo attachInfo = mAttachInfo;
   24965         if (region != null && attachInfo != null) {
   24966             final int pflags = mPrivateFlags;
   24967             if ((pflags & PFLAG_SKIP_DRAW) == 0) {
   24968                 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
   24969                 // remove it from the transparent region.
   24970                 final int[] location = attachInfo.mTransparentLocation;
   24971                 getLocationInWindow(location);
   24972                 // When a view has Z value, then it will be better to leave some area below the view
   24973                 // for drawing shadow. The shadow outset is proportional to the Z value. Note that
   24974                 // the bottom part needs more offset than the left, top and right parts due to the
   24975                 // spot light effects.
   24976                 int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
   24977                 region.op(location[0] - shadowOffset, location[1] - shadowOffset,
   24978                         location[0] + mRight - mLeft + shadowOffset,
   24979                         location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
   24980             } else {
   24981                 if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
   24982                     // The SKIP_DRAW flag IS set and the background drawable exists, we remove
   24983                     // the background drawable's non-transparent parts from this transparent region.
   24984                     applyDrawableToTransparentRegion(mBackground, region);
   24985                 }
   24986                 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
   24987                         && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
   24988                     // Similarly, we remove the foreground drawable's non-transparent parts.
   24989                     applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
   24990                 }
   24991                 if (mDefaultFocusHighlight != null
   24992                         && mDefaultFocusHighlight.getOpacity() != PixelFormat.TRANSPARENT) {
   24993                     // Similarly, we remove the default focus highlight's non-transparent parts.
   24994                     applyDrawableToTransparentRegion(mDefaultFocusHighlight, region);
   24995                 }
   24996             }
   24997         }
   24998         return true;
   24999     }
   25000 
   25001     /**
   25002      * Play a sound effect for this view.
   25003      *
   25004      * <p>The framework will play sound effects for some built in actions, such as
   25005      * clicking, but you may wish to play these effects in your widget,
   25006      * for instance, for internal navigation.
   25007      *
   25008      * <p>The sound effect will only be played if sound effects are enabled by the user, and
   25009      * {@link #isSoundEffectsEnabled()} is true.
   25010      *
   25011      * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
   25012      */
   25013     public void playSoundEffect(int soundConstant) {
   25014         if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
   25015             return;
   25016         }
   25017         mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
   25018     }
   25019 
   25020     /**
   25021      * BZZZTT!!1!
   25022      *
   25023      * <p>Provide haptic feedback to the user for this view.
   25024      *
   25025      * <p>The framework will provide haptic feedback for some built in actions,
   25026      * such as long presses, but you may wish to provide feedback for your
   25027      * own widget.
   25028      *
   25029      * <p>The feedback will only be performed if
   25030      * {@link #isHapticFeedbackEnabled()} is true.
   25031      *
   25032      * @param feedbackConstant One of the constants defined in
   25033      * {@link HapticFeedbackConstants}
   25034      */
   25035     public boolean performHapticFeedback(int feedbackConstant) {
   25036         return performHapticFeedback(feedbackConstant, 0);
   25037     }
   25038 
   25039     /**
   25040      * BZZZTT!!1!
   25041      *
   25042      * <p>Like {@link #performHapticFeedback(int)}, with additional options.
   25043      *
   25044      * @param feedbackConstant One of the constants defined in
   25045      * {@link HapticFeedbackConstants}
   25046      * @param flags Additional flags as per {@link HapticFeedbackConstants}.
   25047      */
   25048     public boolean performHapticFeedback(int feedbackConstant, int flags) {
   25049         if (mAttachInfo == null) {
   25050             return false;
   25051         }
   25052         //noinspection SimplifiableIfStatement
   25053         if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
   25054                 && !isHapticFeedbackEnabled()) {
   25055             return false;
   25056         }
   25057         return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
   25058                 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
   25059     }
   25060 
   25061     /**
   25062      * Request that the visibility of the status bar or other screen/window
   25063      * decorations be changed.
   25064      *
   25065      * <p>This method is used to put the over device UI into temporary modes
   25066      * where the user's attention is focused more on the application content,
   25067      * by dimming or hiding surrounding system affordances.  This is typically
   25068      * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
   25069      * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
   25070      * to be placed behind the action bar (and with these flags other system
   25071      * affordances) so that smooth transitions between hiding and showing them
   25072      * can be done.
   25073      *
   25074      * <p>Two representative examples of the use of system UI visibility is
   25075      * implementing a content browsing application (like a magazine reader)
   25076      * and a video playing application.
   25077      *
   25078      * <p>The first code shows a typical implementation of a View in a content
   25079      * browsing application.  In this implementation, the application goes
   25080      * into a content-oriented mode by hiding the status bar and action bar,
   25081      * and putting the navigation elements into lights out mode.  The user can
   25082      * then interact with content while in this mode.  Such an application should
   25083      * provide an easy way for the user to toggle out of the mode (such as to
   25084      * check information in the status bar or access notifications).  In the
   25085      * implementation here, this is done simply by tapping on the content.
   25086      *
   25087      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
   25088      *      content}
   25089      *
   25090      * <p>This second code sample shows a typical implementation of a View
   25091      * in a video playing application.  In this situation, while the video is
   25092      * playing the application would like to go into a complete full-screen mode,
   25093      * to use as much of the display as possible for the video.  When in this state
   25094      * the user can not interact with the application; the system intercepts
   25095      * touching on the screen to pop the UI out of full screen mode.  See
   25096      * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
   25097      *
   25098      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
   25099      *      content}
   25100      *
   25101      * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
   25102      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
   25103      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
   25104      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
   25105      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
   25106      */
   25107     public void setSystemUiVisibility(int visibility) {
   25108         if (visibility != mSystemUiVisibility) {
   25109             mSystemUiVisibility = visibility;
   25110             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
   25111                 mParent.recomputeViewAttributes(this);
   25112             }
   25113         }
   25114     }
   25115 
   25116     /**
   25117      * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
   25118      * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
   25119      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
   25120      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
   25121      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
   25122      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
   25123      */
   25124     public int getSystemUiVisibility() {
   25125         return mSystemUiVisibility;
   25126     }
   25127 
   25128     /**
   25129      * Returns the current system UI visibility that is currently set for
   25130      * the entire window.  This is the combination of the
   25131      * {@link #setSystemUiVisibility(int)} values supplied by all of the
   25132      * views in the window.
   25133      */
   25134     public int getWindowSystemUiVisibility() {
   25135         return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
   25136     }
   25137 
   25138     /**
   25139      * Override to find out when the window's requested system UI visibility
   25140      * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
   25141      * This is different from the callbacks received through
   25142      * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
   25143      * in that this is only telling you about the local request of the window,
   25144      * not the actual values applied by the system.
   25145      */
   25146     public void onWindowSystemUiVisibilityChanged(int visible) {
   25147     }
   25148 
   25149     /**
   25150      * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
   25151      * the view hierarchy.
   25152      */
   25153     public void dispatchWindowSystemUiVisiblityChanged(int visible) {
   25154         onWindowSystemUiVisibilityChanged(visible);
   25155     }
   25156 
   25157     /**
   25158      * Set a listener to receive callbacks when the visibility of the system bar changes.
   25159      * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
   25160      */
   25161     public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
   25162         getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
   25163         if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
   25164             mParent.recomputeViewAttributes(this);
   25165         }
   25166     }
   25167 
   25168     /**
   25169      * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
   25170      * the view hierarchy.
   25171      */
   25172     public void dispatchSystemUiVisibilityChanged(int visibility) {
   25173         ListenerInfo li = mListenerInfo;
   25174         if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
   25175             li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
   25176                     visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
   25177         }
   25178     }
   25179 
   25180     boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
   25181         int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
   25182         if (val != mSystemUiVisibility) {
   25183             setSystemUiVisibility(val);
   25184             return true;
   25185         }
   25186         return false;
   25187     }
   25188 
   25189     /** @hide */
   25190     @UnsupportedAppUsage
   25191     public void setDisabledSystemUiVisibility(int flags) {
   25192         if (mAttachInfo != null) {
   25193             if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
   25194                 mAttachInfo.mDisabledSystemUiVisibility = flags;
   25195                 if (mParent != null) {
   25196                     mParent.recomputeViewAttributes(this);
   25197                 }
   25198             }
   25199         }
   25200     }
   25201 
   25202     /**
   25203      * Creates an image that the system displays during the drag and drop
   25204      * operation. This is called a &quot;drag shadow&quot;. The default implementation
   25205      * for a DragShadowBuilder based on a View returns an image that has exactly the same
   25206      * appearance as the given View. The default also positions the center of the drag shadow
   25207      * directly under the touch point. If no View is provided (the constructor with no parameters
   25208      * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
   25209      * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
   25210      * default is an invisible drag shadow.
   25211      * <p>
   25212      * You are not required to use the View you provide to the constructor as the basis of the
   25213      * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
   25214      * anything you want as the drag shadow.
   25215      * </p>
   25216      * <p>
   25217      *  You pass a DragShadowBuilder object to the system when you start the drag. The system
   25218      *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
   25219      *  size and position of the drag shadow. It uses this data to construct a
   25220      *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
   25221      *  so that your application can draw the shadow image in the Canvas.
   25222      * </p>
   25223      *
   25224      * <div class="special reference">
   25225      * <h3>Developer Guides</h3>
   25226      * <p>For a guide to implementing drag and drop features, read the
   25227      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
   25228      * </div>
   25229      */
   25230     public static class DragShadowBuilder {
   25231         @UnsupportedAppUsage
   25232         private final WeakReference<View> mView;
   25233 
   25234         /**
   25235          * Constructs a shadow image builder based on a View. By default, the resulting drag
   25236          * shadow will have the same appearance and dimensions as the View, with the touch point
   25237          * over the center of the View.
   25238          * @param view A View. Any View in scope can be used.
   25239          */
   25240         public DragShadowBuilder(View view) {
   25241             mView = new WeakReference<View>(view);
   25242         }
   25243 
   25244         /**
   25245          * Construct a shadow builder object with no associated View.  This
   25246          * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
   25247          * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
   25248          * to supply the drag shadow's dimensions and appearance without
   25249          * reference to any View object.
   25250          */
   25251         public DragShadowBuilder() {
   25252             mView = new WeakReference<View>(null);
   25253         }
   25254 
   25255         /**
   25256          * Returns the View object that had been passed to the
   25257          * {@link #View.DragShadowBuilder(View)}
   25258          * constructor.  If that View parameter was {@code null} or if the
   25259          * {@link #View.DragShadowBuilder()}
   25260          * constructor was used to instantiate the builder object, this method will return
   25261          * null.
   25262          *
   25263          * @return The View object associate with this builder object.
   25264          */
   25265         @SuppressWarnings({"JavadocReference"})
   25266         final public View getView() {
   25267             return mView.get();
   25268         }
   25269 
   25270         /**
   25271          * Provides the metrics for the shadow image. These include the dimensions of
   25272          * the shadow image, and the point within that shadow that should
   25273          * be centered under the touch location while dragging.
   25274          * <p>
   25275          * The default implementation sets the dimensions of the shadow to be the
   25276          * same as the dimensions of the View itself and centers the shadow under
   25277          * the touch point.
   25278          * </p>
   25279          *
   25280          * @param outShadowSize A {@link android.graphics.Point} containing the width and height
   25281          * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
   25282          * desired width and must set {@link android.graphics.Point#y} to the desired height of the
   25283          * image. Since Android P, the width and height must be positive values.
   25284          *
   25285          * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
   25286          * shadow image that should be underneath the touch point during the drag and drop
   25287          * operation. Your application must set {@link android.graphics.Point#x} to the
   25288          * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
   25289          */
   25290         public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
   25291             final View view = mView.get();
   25292             if (view != null) {
   25293                 outShadowSize.set(view.getWidth(), view.getHeight());
   25294                 outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
   25295             } else {
   25296                 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
   25297             }
   25298         }
   25299 
   25300         /**
   25301          * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
   25302          * based on the dimensions it received from the
   25303          * {@link #onProvideShadowMetrics(Point, Point)} callback.
   25304          *
   25305          * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
   25306          */
   25307         public void onDrawShadow(Canvas canvas) {
   25308             final View view = mView.get();
   25309             if (view != null) {
   25310                 view.draw(canvas);
   25311             } else {
   25312                 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
   25313             }
   25314         }
   25315     }
   25316 
   25317     /**
   25318      * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
   25319      * startDragAndDrop()} for newer platform versions.
   25320      */
   25321     @Deprecated
   25322     public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
   25323                                    Object myLocalState, int flags) {
   25324         return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
   25325     }
   25326 
   25327     /**
   25328      * Starts a drag and drop operation. When your application calls this method, it passes a
   25329      * {@link android.view.View.DragShadowBuilder} object to the system. The
   25330      * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
   25331      * to get metrics for the drag shadow, and then calls the object's
   25332      * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
   25333      * <p>
   25334      *  Once the system has the drag shadow, it begins the drag and drop operation by sending
   25335      *  drag events to all the View objects in your application that are currently visible. It does
   25336      *  this either by calling the View object's drag listener (an implementation of
   25337      *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
   25338      *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
   25339      *  Both are passed a {@link android.view.DragEvent} object that has a
   25340      *  {@link android.view.DragEvent#getAction()} value of
   25341      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
   25342      * </p>
   25343      * <p>
   25344      * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
   25345      * int) startDragAndDrop()} on any attached View object. The View object does not need to be
   25346      * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
   25347      * to the View the user selected for dragging.
   25348      * </p>
   25349      * @param data A {@link android.content.ClipData} object pointing to the data to be
   25350      * transferred by the drag and drop operation.
   25351      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
   25352      * drag shadow.
   25353      * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
   25354      * drop operation. When dispatching drag events to views in the same activity this object
   25355      * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other
   25356      * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()}
   25357      * will return null).
   25358      * <p>
   25359      * myLocalState is a lightweight mechanism for the sending information from the dragged View
   25360      * to the target Views. For example, it can contain flags that differentiate between a
   25361      * a copy operation and a move operation.
   25362      * </p>
   25363      * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
   25364      * flags, or any combination of the following:
   25365      *     <ul>
   25366      *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
   25367      *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
   25368      *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
   25369      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
   25370      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
   25371      *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
   25372      *     </ul>
   25373      * @return {@code true} if the method completes successfully, or
   25374      * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
   25375      * do a drag because of another ongoing operation or some other reasons.
   25376      */
   25377     public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
   25378             Object myLocalState, int flags) {
   25379         if (ViewDebug.DEBUG_DRAG) {
   25380             Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
   25381         }
   25382         if (mAttachInfo == null) {
   25383             Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
   25384             return false;
   25385         }
   25386         if (!mAttachInfo.mViewRootImpl.mSurface.isValid()) {
   25387             Log.w(VIEW_LOG_TAG, "startDragAndDrop called with an invalid surface.");
   25388             return false;
   25389         }
   25390 
   25391         if (data != null) {
   25392             data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0);
   25393         }
   25394 
   25395         Point shadowSize = new Point();
   25396         Point shadowTouchPoint = new Point();
   25397         shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
   25398 
   25399         if ((shadowSize.x < 0) || (shadowSize.y < 0)
   25400                 || (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
   25401             throw new IllegalStateException("Drag shadow dimensions must not be negative");
   25402         }
   25403 
   25404         // Create 1x1 surface when zero surface size is specified because SurfaceControl.Builder
   25405         // does not accept zero size surface.
   25406         if (shadowSize.x == 0  || shadowSize.y == 0) {
   25407             if (!sAcceptZeroSizeDragShadow) {
   25408                 throw new IllegalStateException("Drag shadow dimensions must be positive");
   25409             }
   25410             shadowSize.x = 1;
   25411             shadowSize.y = 1;
   25412         }
   25413 
   25414         if (ViewDebug.DEBUG_DRAG) {
   25415             Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
   25416                     + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
   25417         }
   25418 
   25419         final ViewRootImpl root = mAttachInfo.mViewRootImpl;
   25420         final SurfaceSession session = new SurfaceSession();
   25421         final SurfaceControl surfaceControl = new SurfaceControl.Builder(session)
   25422                 .setName("drag surface")
   25423                 .setParent(root.getSurfaceControl())
   25424                 .setBufferSize(shadowSize.x, shadowSize.y)
   25425                 .setFormat(PixelFormat.TRANSLUCENT)
   25426                 .build();
   25427         final Surface surface = new Surface();
   25428         surface.copyFrom(surfaceControl);
   25429         IBinder token = null;
   25430         try {
   25431             final Canvas canvas = surface.lockCanvas(null);
   25432             try {
   25433                 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
   25434                 shadowBuilder.onDrawShadow(canvas);
   25435             } finally {
   25436                 surface.unlockCanvasAndPost(canvas);
   25437             }
   25438 
   25439             // repurpose 'shadowSize' for the last touch point
   25440             root.getLastTouchPoint(shadowSize);
   25441 
   25442             token = mAttachInfo.mSession.performDrag(
   25443                     mAttachInfo.mWindow, flags, surfaceControl, root.getLastTouchSource(),
   25444                     shadowSize.x, shadowSize.y, shadowTouchPoint.x, shadowTouchPoint.y, data);
   25445             if (ViewDebug.DEBUG_DRAG) {
   25446                 Log.d(VIEW_LOG_TAG, "performDrag returned " + token);
   25447             }
   25448             if (token != null) {
   25449                 if (mAttachInfo.mDragSurface != null) {
   25450                     mAttachInfo.mDragSurface.release();
   25451                 }
   25452                 mAttachInfo.mDragSurface = surface;
   25453                 mAttachInfo.mDragToken = token;
   25454                 // Cache the local state object for delivery with DragEvents
   25455                 root.setLocalDragState(myLocalState);
   25456             }
   25457             return token != null;
   25458         } catch (Exception e) {
   25459             Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
   25460             return false;
   25461         } finally {
   25462             if (token == null) {
   25463                 surface.destroy();
   25464             }
   25465             session.kill();
   25466         }
   25467     }
   25468 
   25469     /**
   25470      * Cancels an ongoing drag and drop operation.
   25471      * <p>
   25472      * A {@link android.view.DragEvent} object with
   25473      * {@link android.view.DragEvent#getAction()} value of
   25474      * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
   25475      * {@link android.view.DragEvent#getResult()} value of {@code false}
   25476      * will be sent to every
   25477      * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
   25478      * even if they are not currently visible.
   25479      * </p>
   25480      * <p>
   25481      * This method can be called on any View in the same window as the View on which
   25482      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
   25483      * was called.
   25484      * </p>
   25485      */
   25486     public final void cancelDragAndDrop() {
   25487         if (ViewDebug.DEBUG_DRAG) {
   25488             Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
   25489         }
   25490         if (mAttachInfo == null) {
   25491             Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
   25492             return;
   25493         }
   25494         if (mAttachInfo.mDragToken != null) {
   25495             try {
   25496                 mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken, false);
   25497             } catch (Exception e) {
   25498                 Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
   25499             }
   25500             mAttachInfo.mDragToken = null;
   25501         } else {
   25502             Log.e(VIEW_LOG_TAG, "No active drag to cancel");
   25503         }
   25504     }
   25505 
   25506     /**
   25507      * Updates the drag shadow for the ongoing drag and drop operation.
   25508      *
   25509      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
   25510      * new drag shadow.
   25511      */
   25512     public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
   25513         if (ViewDebug.DEBUG_DRAG) {
   25514             Log.d(VIEW_LOG_TAG, "updateDragShadow");
   25515         }
   25516         if (mAttachInfo == null) {
   25517             Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
   25518             return;
   25519         }
   25520         if (mAttachInfo.mDragToken != null) {
   25521             try {
   25522                 Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
   25523                 try {
   25524                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
   25525                     shadowBuilder.onDrawShadow(canvas);
   25526                 } finally {
   25527                     mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
   25528                 }
   25529             } catch (Exception e) {
   25530                 Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
   25531             }
   25532         } else {
   25533             Log.e(VIEW_LOG_TAG, "No active drag");
   25534         }
   25535     }
   25536 
   25537     /**
   25538      * Starts a move from {startX, startY}, the amount of the movement will be the offset
   25539      * between {startX, startY} and the new cursor positon.
   25540      * @param startX horizontal coordinate where the move started.
   25541      * @param startY vertical coordinate where the move started.
   25542      * @return whether moving was started successfully.
   25543      * @hide
   25544      */
   25545     public final boolean startMovingTask(float startX, float startY) {
   25546         if (ViewDebug.DEBUG_POSITIONING) {
   25547             Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
   25548         }
   25549         try {
   25550             return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
   25551         } catch (RemoteException e) {
   25552             Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
   25553         }
   25554         return false;
   25555     }
   25556 
   25557     /**
   25558      * Finish a window move task.
   25559      * @hide
   25560      */
   25561     public void finishMovingTask() {
   25562         if (ViewDebug.DEBUG_POSITIONING) {
   25563             Log.d(VIEW_LOG_TAG, "finishMovingTask");
   25564         }
   25565         try {
   25566             mAttachInfo.mSession.finishMovingTask(mAttachInfo.mWindow);
   25567         } catch (RemoteException e) {
   25568             Log.e(VIEW_LOG_TAG, "Unable to finish moving", e);
   25569         }
   25570     }
   25571 
   25572     /**
   25573      * Handles drag events sent by the system following a call to
   25574      * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
   25575      * startDragAndDrop()}.
   25576      *<p>
   25577      * When the system calls this method, it passes a
   25578      * {@link android.view.DragEvent} object. A call to
   25579      * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
   25580      * in DragEvent. The method uses these to determine what is happening in the drag and drop
   25581      * operation.
   25582      * @param event The {@link android.view.DragEvent} sent by the system.
   25583      * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
   25584      * in DragEvent, indicating the type of drag event represented by this object.
   25585      * @return {@code true} if the method was successful, otherwise {@code false}.
   25586      * <p>
   25587      *  The method should return {@code true} in response to an action type of
   25588      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
   25589      *  operation.
   25590      * </p>
   25591      * <p>
   25592      *  The method should also return {@code true} in response to an action type of
   25593      *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
   25594      *  {@code false} if it didn't.
   25595      * </p>
   25596      * <p>
   25597      *  For all other events, the return value is ignored.
   25598      * </p>
   25599      */
   25600     public boolean onDragEvent(DragEvent event) {
   25601         return false;
   25602     }
   25603 
   25604     // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps.
   25605     boolean dispatchDragEnterExitInPreN(DragEvent event) {
   25606         return callDragEventHandler(event);
   25607     }
   25608 
   25609     /**
   25610      * Detects if this View is enabled and has a drag event listener.
   25611      * If both are true, then it calls the drag event listener with the
   25612      * {@link android.view.DragEvent} it received. If the drag event listener returns
   25613      * {@code true}, then dispatchDragEvent() returns {@code true}.
   25614      * <p>
   25615      * For all other cases, the method calls the
   25616      * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
   25617      * method and returns its result.
   25618      * </p>
   25619      * <p>
   25620      * This ensures that a drag event is always consumed, even if the View does not have a drag
   25621      * event listener. However, if the View has a listener and the listener returns true, then
   25622      * onDragEvent() is not called.
   25623      * </p>
   25624      */
   25625     public boolean dispatchDragEvent(DragEvent event) {
   25626         event.mEventHandlerWasCalled = true;
   25627         if (event.mAction == DragEvent.ACTION_DRAG_LOCATION ||
   25628             event.mAction == DragEvent.ACTION_DROP) {
   25629             // About to deliver an event with coordinates to this view. Notify that now this view
   25630             // has drag focus. This will send exit/enter events as needed.
   25631             getViewRootImpl().setDragFocus(this, event);
   25632         }
   25633         return callDragEventHandler(event);
   25634     }
   25635 
   25636     final boolean callDragEventHandler(DragEvent event) {
   25637         final boolean result;
   25638 
   25639         ListenerInfo li = mListenerInfo;
   25640         //noinspection SimplifiableIfStatement
   25641         if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
   25642                 && li.mOnDragListener.onDrag(this, event)) {
   25643             result = true;
   25644         } else {
   25645             result = onDragEvent(event);
   25646         }
   25647 
   25648         switch (event.mAction) {
   25649             case DragEvent.ACTION_DRAG_ENTERED: {
   25650                 mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
   25651                 refreshDrawableState();
   25652             } break;
   25653             case DragEvent.ACTION_DRAG_EXITED: {
   25654                 mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
   25655                 refreshDrawableState();
   25656             } break;
   25657             case DragEvent.ACTION_DRAG_ENDED: {
   25658                 mPrivateFlags2 &= ~View.DRAG_MASK;
   25659                 refreshDrawableState();
   25660             } break;
   25661         }
   25662 
   25663         return result;
   25664     }
   25665 
   25666     boolean canAcceptDrag() {
   25667         return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
   25668     }
   25669 
   25670     /**
   25671      * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
   25672      * it is ever exposed at all.
   25673      * @hide
   25674      */
   25675     @UnsupportedAppUsage
   25676     public void onCloseSystemDialogs(String reason) {
   25677     }
   25678 
   25679     /**
   25680      * Given a Drawable whose bounds have been set to draw into this view,
   25681      * update a Region being computed for
   25682      * {@link #gatherTransparentRegion(android.graphics.Region)} so
   25683      * that any non-transparent parts of the Drawable are removed from the
   25684      * given transparent region.
   25685      *
   25686      * @param dr The Drawable whose transparency is to be applied to the region.
   25687      * @param region A Region holding the current transparency information,
   25688      * where any parts of the region that are set are considered to be
   25689      * transparent.  On return, this region will be modified to have the
   25690      * transparency information reduced by the corresponding parts of the
   25691      * Drawable that are not transparent.
   25692      * {@hide}
   25693      */
   25694     @UnsupportedAppUsage
   25695     public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
   25696         if (DBG) {
   25697             Log.i("View", "Getting transparent region for: " + this);
   25698         }
   25699         final Region r = dr.getTransparentRegion();
   25700         final Rect db = dr.getBounds();
   25701         final AttachInfo attachInfo = mAttachInfo;
   25702         if (r != null && attachInfo != null) {
   25703             final int w = getRight()-getLeft();
   25704             final int h = getBottom()-getTop();
   25705             if (db.left > 0) {
   25706                 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
   25707                 r.op(0, 0, db.left, h, Region.Op.UNION);
   25708             }
   25709             if (db.right < w) {
   25710                 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
   25711                 r.op(db.right, 0, w, h, Region.Op.UNION);
   25712             }
   25713             if (db.top > 0) {
   25714                 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
   25715                 r.op(0, 0, w, db.top, Region.Op.UNION);
   25716             }
   25717             if (db.bottom < h) {
   25718                 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
   25719                 r.op(0, db.bottom, w, h, Region.Op.UNION);
   25720             }
   25721             final int[] location = attachInfo.mTransparentLocation;
   25722             getLocationInWindow(location);
   25723             r.translate(location[0], location[1]);
   25724             region.op(r, Region.Op.INTERSECT);
   25725         } else {
   25726             region.op(db, Region.Op.DIFFERENCE);
   25727         }
   25728     }
   25729 
   25730     private void checkForLongClick(long delay, float x, float y, int classification) {
   25731         if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
   25732             mHasPerformedLongPress = false;
   25733 
   25734             if (mPendingCheckForLongPress == null) {
   25735                 mPendingCheckForLongPress = new CheckForLongPress();
   25736             }
   25737             mPendingCheckForLongPress.setAnchor(x, y);
   25738             mPendingCheckForLongPress.rememberWindowAttachCount();
   25739             mPendingCheckForLongPress.rememberPressedState();
   25740             mPendingCheckForLongPress.setClassification(classification);
   25741             postDelayed(mPendingCheckForLongPress, delay);
   25742         }
   25743     }
   25744 
   25745     /**
   25746      * Inflate a view from an XML resource.  This convenience method wraps the {@link
   25747      * LayoutInflater} class, which provides a full range of options for view inflation.
   25748      *
   25749      * @param context The Context object for your activity or application.
   25750      * @param resource The resource ID to inflate
   25751      * @param root A view group that will be the parent.  Used to properly inflate the
   25752      * layout_* parameters.
   25753      * @see LayoutInflater
   25754      */
   25755     public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
   25756         LayoutInflater factory = LayoutInflater.from(context);
   25757         return factory.inflate(resource, root);
   25758     }
   25759 
   25760     /**
   25761      * Scroll the view with standard behavior for scrolling beyond the normal
   25762      * content boundaries. Views that call this method should override
   25763      * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
   25764      * results of an over-scroll operation.
   25765      *
   25766      * Views can use this method to handle any touch or fling-based scrolling.
   25767      *
   25768      * @param deltaX Change in X in pixels
   25769      * @param deltaY Change in Y in pixels
   25770      * @param scrollX Current X scroll value in pixels before applying deltaX
   25771      * @param scrollY Current Y scroll value in pixels before applying deltaY
   25772      * @param scrollRangeX Maximum content scroll range along the X axis
   25773      * @param scrollRangeY Maximum content scroll range along the Y axis
   25774      * @param maxOverScrollX Number of pixels to overscroll by in either direction
   25775      *          along the X axis.
   25776      * @param maxOverScrollY Number of pixels to overscroll by in either direction
   25777      *          along the Y axis.
   25778      * @param isTouchEvent true if this scroll operation is the result of a touch event.
   25779      * @return true if scrolling was clamped to an over-scroll boundary along either
   25780      *          axis, false otherwise.
   25781      */
   25782     @SuppressWarnings({"UnusedParameters"})
   25783     protected boolean overScrollBy(int deltaX, int deltaY,
   25784             int scrollX, int scrollY,
   25785             int scrollRangeX, int scrollRangeY,
   25786             int maxOverScrollX, int maxOverScrollY,
   25787             boolean isTouchEvent) {
   25788         final int overScrollMode = mOverScrollMode;
   25789         final boolean canScrollHorizontal =
   25790                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
   25791         final boolean canScrollVertical =
   25792                 computeVerticalScrollRange() > computeVerticalScrollExtent();
   25793         final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
   25794                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
   25795         final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
   25796                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
   25797 
   25798         int newScrollX = scrollX + deltaX;
   25799         if (!overScrollHorizontal) {
   25800             maxOverScrollX = 0;
   25801         }
   25802 
   25803         int newScrollY = scrollY + deltaY;
   25804         if (!overScrollVertical) {
   25805             maxOverScrollY = 0;
   25806         }
   25807 
   25808         // Clamp values if at the limits and record
   25809         final int left = -maxOverScrollX;
   25810         final int right = maxOverScrollX + scrollRangeX;
   25811         final int top = -maxOverScrollY;
   25812         final int bottom = maxOverScrollY + scrollRangeY;
   25813 
   25814         boolean clampedX = false;
   25815         if (newScrollX > right) {
   25816             newScrollX = right;
   25817             clampedX = true;
   25818         } else if (newScrollX < left) {
   25819             newScrollX = left;
   25820             clampedX = true;
   25821         }
   25822 
   25823         boolean clampedY = false;
   25824         if (newScrollY > bottom) {
   25825             newScrollY = bottom;
   25826             clampedY = true;
   25827         } else if (newScrollY < top) {
   25828             newScrollY = top;
   25829             clampedY = true;
   25830         }
   25831 
   25832         onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
   25833 
   25834         return clampedX || clampedY;
   25835     }
   25836 
   25837     /**
   25838      * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
   25839      * respond to the results of an over-scroll operation.
   25840      *
   25841      * @param scrollX New X scroll value in pixels
   25842      * @param scrollY New Y scroll value in pixels
   25843      * @param clampedX True if scrollX was clamped to an over-scroll boundary
   25844      * @param clampedY True if scrollY was clamped to an over-scroll boundary
   25845      */
   25846     protected void onOverScrolled(int scrollX, int scrollY,
   25847             boolean clampedX, boolean clampedY) {
   25848         // Intentionally empty.
   25849     }
   25850 
   25851     /**
   25852      * Returns the over-scroll mode for this view. The result will be
   25853      * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
   25854      * (allow over-scrolling only if the view content is larger than the container),
   25855      * or {@link #OVER_SCROLL_NEVER}.
   25856      *
   25857      * @return This view's over-scroll mode.
   25858      */
   25859     @InspectableProperty(enumMapping = {
   25860             @EnumEntry(value = OVER_SCROLL_ALWAYS, name = "always"),
   25861             @EnumEntry(value = OVER_SCROLL_IF_CONTENT_SCROLLS, name = "ifContentScrolls"),
   25862             @EnumEntry(value = OVER_SCROLL_NEVER, name = "never")
   25863     })
   25864     public int getOverScrollMode() {
   25865         return mOverScrollMode;
   25866     }
   25867 
   25868     /**
   25869      * Set the over-scroll mode for this view. Valid over-scroll modes are
   25870      * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
   25871      * (allow over-scrolling only if the view content is larger than the container),
   25872      * or {@link #OVER_SCROLL_NEVER}.
   25873      *
   25874      * Setting the over-scroll mode of a view will have an effect only if the
   25875      * view is capable of scrolling.
   25876      *
   25877      * @param overScrollMode The new over-scroll mode for this view.
   25878      */
   25879     public void setOverScrollMode(int overScrollMode) {
   25880         if (overScrollMode != OVER_SCROLL_ALWAYS &&
   25881                 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
   25882                 overScrollMode != OVER_SCROLL_NEVER) {
   25883             throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
   25884         }
   25885         mOverScrollMode = overScrollMode;
   25886     }
   25887 
   25888     /**
   25889      * Enable or disable nested scrolling for this view.
   25890      *
   25891      * <p>If this property is set to true the view will be permitted to initiate nested
   25892      * scrolling operations with a compatible parent view in the current hierarchy. If this
   25893      * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
   25894      * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
   25895      * the nested scroll.</p>
   25896      *
   25897      * @param enabled true to enable nested scrolling, false to disable
   25898      *
   25899      * @see #isNestedScrollingEnabled()
   25900      */
   25901     public void setNestedScrollingEnabled(boolean enabled) {
   25902         if (enabled) {
   25903             mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
   25904         } else {
   25905             stopNestedScroll();
   25906             mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
   25907         }
   25908     }
   25909 
   25910     /**
   25911      * Returns true if nested scrolling is enabled for this view.
   25912      *
   25913      * <p>If nested scrolling is enabled and this View class implementation supports it,
   25914      * this view will act as a nested scrolling child view when applicable, forwarding data
   25915      * about the scroll operation in progress to a compatible and cooperating nested scrolling
   25916      * parent.</p>
   25917      *
   25918      * @return true if nested scrolling is enabled
   25919      *
   25920      * @see #setNestedScrollingEnabled(boolean)
   25921      */
   25922     @InspectableProperty
   25923     public boolean isNestedScrollingEnabled() {
   25924         return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
   25925                 PFLAG3_NESTED_SCROLLING_ENABLED;
   25926     }
   25927 
   25928     /**
   25929      * Begin a nestable scroll operation along the given axes.
   25930      *
   25931      * <p>A view starting a nested scroll promises to abide by the following contract:</p>
   25932      *
   25933      * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
   25934      * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
   25935      * In the case of touch scrolling the nested scroll will be terminated automatically in
   25936      * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
   25937      * In the event of programmatic scrolling the caller must explicitly call
   25938      * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
   25939      *
   25940      * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
   25941      * If it returns false the caller may ignore the rest of this contract until the next scroll.
   25942      * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
   25943      *
   25944      * <p>At each incremental step of the scroll the caller should invoke
   25945      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
   25946      * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
   25947      * parent at least partially consumed the scroll and the caller should adjust the amount it
   25948      * scrolls by.</p>
   25949      *
   25950      * <p>After applying the remainder of the scroll delta the caller should invoke
   25951      * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
   25952      * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
   25953      * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
   25954      * </p>
   25955      *
   25956      * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
   25957      *             {@link #SCROLL_AXIS_VERTICAL}.
   25958      * @return true if a cooperative parent was found and nested scrolling has been enabled for
   25959      *         the current gesture.
   25960      *
   25961      * @see #stopNestedScroll()
   25962      * @see #dispatchNestedPreScroll(int, int, int[], int[])
   25963      * @see #dispatchNestedScroll(int, int, int, int, int[])
   25964      */
   25965     public boolean startNestedScroll(int axes) {
   25966         if (hasNestedScrollingParent()) {
   25967             // Already in progress
   25968             return true;
   25969         }
   25970         if (isNestedScrollingEnabled()) {
   25971             ViewParent p = getParent();
   25972             View child = this;
   25973             while (p != null) {
   25974                 try {
   25975                     if (p.onStartNestedScroll(child, this, axes)) {
   25976                         mNestedScrollingParent = p;
   25977                         p.onNestedScrollAccepted(child, this, axes);
   25978                         return true;
   25979                     }
   25980                 } catch (AbstractMethodError e) {
   25981                     Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
   25982                             "method onStartNestedScroll", e);
   25983                     // Allow the search upward to continue
   25984                 }
   25985                 if (p instanceof View) {
   25986                     child = (View) p;
   25987                 }
   25988                 p = p.getParent();
   25989             }
   25990         }
   25991         return false;
   25992     }
   25993 
   25994     /**
   25995      * Stop a nested scroll in progress.
   25996      *
   25997      * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
   25998      *
   25999      * @see #startNestedScroll(int)
   26000      */
   26001     public void stopNestedScroll() {
   26002         if (mNestedScrollingParent != null) {
   26003             mNestedScrollingParent.onStopNestedScroll(this);
   26004             mNestedScrollingParent = null;
   26005         }
   26006     }
   26007 
   26008     /**
   26009      * Returns true if this view has a nested scrolling parent.
   26010      *
   26011      * <p>The presence of a nested scrolling parent indicates that this view has initiated
   26012      * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
   26013      *
   26014      * @return whether this view has a nested scrolling parent
   26015      */
   26016     public boolean hasNestedScrollingParent() {
   26017         return mNestedScrollingParent != null;
   26018     }
   26019 
   26020     /**
   26021      * Dispatch one step of a nested scroll in progress.
   26022      *
   26023      * <p>Implementations of views that support nested scrolling should call this to report
   26024      * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
   26025      * is not currently in progress or nested scrolling is not
   26026      * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
   26027      *
   26028      * <p>Compatible View implementations should also call
   26029      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
   26030      * consuming a component of the scroll event themselves.</p>
   26031      *
   26032      * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
   26033      * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
   26034      * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
   26035      * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
   26036      * @param offsetInWindow Optional. If not null, on return this will contain the offset
   26037      *                       in local view coordinates of this view from before this operation
   26038      *                       to after it completes. View implementations may use this to adjust
   26039      *                       expected input coordinate tracking.
   26040      * @return true if the event was dispatched, false if it could not be dispatched.
   26041      * @see #dispatchNestedPreScroll(int, int, int[], int[])
   26042      */
   26043     public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
   26044             int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
   26045         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
   26046             if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
   26047                 int startX = 0;
   26048                 int startY = 0;
   26049                 if (offsetInWindow != null) {
   26050                     getLocationInWindow(offsetInWindow);
   26051                     startX = offsetInWindow[0];
   26052                     startY = offsetInWindow[1];
   26053                 }
   26054 
   26055                 mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
   26056                         dxUnconsumed, dyUnconsumed);
   26057 
   26058                 if (offsetInWindow != null) {
   26059                     getLocationInWindow(offsetInWindow);
   26060                     offsetInWindow[0] -= startX;
   26061                     offsetInWindow[1] -= startY;
   26062                 }
   26063                 return true;
   26064             } else if (offsetInWindow != null) {
   26065                 // No motion, no dispatch. Keep offsetInWindow up to date.
   26066                 offsetInWindow[0] = 0;
   26067                 offsetInWindow[1] = 0;
   26068             }
   26069         }
   26070         return false;
   26071     }
   26072 
   26073     /**
   26074      * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
   26075      *
   26076      * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
   26077      * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
   26078      * scrolling operation to consume some or all of the scroll operation before the child view
   26079      * consumes it.</p>
   26080      *
   26081      * @param dx Horizontal scroll distance in pixels
   26082      * @param dy Vertical scroll distance in pixels
   26083      * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
   26084      *                 and consumed[1] the consumed dy.
   26085      * @param offsetInWindow Optional. If not null, on return this will contain the offset
   26086      *                       in local view coordinates of this view from before this operation
   26087      *                       to after it completes. View implementations may use this to adjust
   26088      *                       expected input coordinate tracking.
   26089      * @return true if the parent consumed some or all of the scroll delta
   26090      * @see #dispatchNestedScroll(int, int, int, int, int[])
   26091      */
   26092     public boolean dispatchNestedPreScroll(int dx, int dy,
   26093             @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
   26094         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
   26095             if (dx != 0 || dy != 0) {
   26096                 int startX = 0;
   26097                 int startY = 0;
   26098                 if (offsetInWindow != null) {
   26099                     getLocationInWindow(offsetInWindow);
   26100                     startX = offsetInWindow[0];
   26101                     startY = offsetInWindow[1];
   26102                 }
   26103 
   26104                 if (consumed == null) {
   26105                     if (mTempNestedScrollConsumed == null) {
   26106                         mTempNestedScrollConsumed = new int[2];
   26107                     }
   26108                     consumed = mTempNestedScrollConsumed;
   26109                 }
   26110                 consumed[0] = 0;
   26111                 consumed[1] = 0;
   26112                 mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
   26113 
   26114                 if (offsetInWindow != null) {
   26115                     getLocationInWindow(offsetInWindow);
   26116                     offsetInWindow[0] -= startX;
   26117                     offsetInWindow[1] -= startY;
   26118                 }
   26119                 return consumed[0] != 0 || consumed[1] != 0;
   26120             } else if (offsetInWindow != null) {
   26121                 offsetInWindow[0] = 0;
   26122                 offsetInWindow[1] = 0;
   26123             }
   26124         }
   26125         return false;
   26126     }
   26127 
   26128     /**
   26129      * Dispatch a fling to a nested scrolling parent.
   26130      *
   26131      * <p>This method should be used to indicate that a nested scrolling child has detected
   26132      * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
   26133      * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
   26134      * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
   26135      * along a scrollable axis.</p>
   26136      *
   26137      * <p>If a nested scrolling child view would normally fling but it is at the edge of
   26138      * its own content, it can use this method to delegate the fling to its nested scrolling
   26139      * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
   26140      *
   26141      * @param velocityX Horizontal fling velocity in pixels per second
   26142      * @param velocityY Vertical fling velocity in pixels per second
   26143      * @param consumed true if the child consumed the fling, false otherwise
   26144      * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
   26145      */
   26146     public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
   26147         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
   26148             return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
   26149         }
   26150         return false;
   26151     }
   26152 
   26153     /**
   26154      * Dispatch a fling to a nested scrolling parent before it is processed by this view.
   26155      *
   26156      * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
   26157      * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
   26158      * offsets an opportunity for the parent view in a nested fling to fully consume the fling
   26159      * before the child view consumes it. If this method returns <code>true</code>, a nested
   26160      * parent view consumed the fling and this view should not scroll as a result.</p>
   26161      *
   26162      * <p>For a better user experience, only one view in a nested scrolling chain should consume
   26163      * the fling at a time. If a parent view consumed the fling this method will return false.
   26164      * Custom view implementations should account for this in two ways:</p>
   26165      *
   26166      * <ul>
   26167      *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
   26168      *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
   26169      *     position regardless.</li>
   26170      *     <li>If a nested parent does consume the fling, this view should not scroll at all,
   26171      *     even to settle back to a valid idle position.</li>
   26172      * </ul>
   26173      *
   26174      * <p>Views should also not offer fling velocities to nested parent views along an axis
   26175      * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
   26176      * should not offer a horizontal fling velocity to its parents since scrolling along that
   26177      * axis is not permitted and carrying velocity along that motion does not make sense.</p>
   26178      *
   26179      * @param velocityX Horizontal fling velocity in pixels per second
   26180      * @param velocityY Vertical fling velocity in pixels per second
   26181      * @return true if a nested scrolling parent consumed the fling
   26182      */
   26183     public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
   26184         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
   26185             return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
   26186         }
   26187         return false;
   26188     }
   26189 
   26190     /**
   26191      * Gets a scale factor that determines the distance the view should scroll
   26192      * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
   26193      * @return The vertical scroll scale factor.
   26194      * @hide
   26195      */
   26196     @UnsupportedAppUsage
   26197     protected float getVerticalScrollFactor() {
   26198         if (mVerticalScrollFactor == 0) {
   26199             TypedValue outValue = new TypedValue();
   26200             if (!mContext.getTheme().resolveAttribute(
   26201                     com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
   26202                 throw new IllegalStateException(
   26203                         "Expected theme to define listPreferredItemHeight.");
   26204             }
   26205             mVerticalScrollFactor = outValue.getDimension(
   26206                     mContext.getResources().getDisplayMetrics());
   26207         }
   26208         return mVerticalScrollFactor;
   26209     }
   26210 
   26211     /**
   26212      * Gets a scale factor that determines the distance the view should scroll
   26213      * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
   26214      * @return The horizontal scroll scale factor.
   26215      * @hide
   26216      */
   26217     @UnsupportedAppUsage
   26218     protected float getHorizontalScrollFactor() {
   26219         // TODO: Should use something else.
   26220         return getVerticalScrollFactor();
   26221     }
   26222 
   26223     /**
   26224      * Return the value specifying the text direction or policy that was set with
   26225      * {@link #setTextDirection(int)}.
   26226      *
   26227      * @return the defined text direction. It can be one of:
   26228      *
   26229      * {@link #TEXT_DIRECTION_INHERIT},
   26230      * {@link #TEXT_DIRECTION_FIRST_STRONG},
   26231      * {@link #TEXT_DIRECTION_ANY_RTL},
   26232      * {@link #TEXT_DIRECTION_LTR},
   26233      * {@link #TEXT_DIRECTION_RTL},
   26234      * {@link #TEXT_DIRECTION_LOCALE},
   26235      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
   26236      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
   26237      *
   26238      * @attr ref android.R.styleable#View_textDirection
   26239      *
   26240      * @hide
   26241      */
   26242     @ViewDebug.ExportedProperty(category = "text", mapping = {
   26243             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
   26244             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
   26245             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
   26246             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
   26247             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
   26248             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
   26249             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
   26250             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
   26251     })
   26252     @InspectableProperty(hasAttributeId = false, enumMapping = {
   26253             @EnumEntry(value = TEXT_DIRECTION_INHERIT, name = "inherit"),
   26254             @EnumEntry(value = TEXT_DIRECTION_LOCALE, name = "locale"),
   26255             @EnumEntry(value = TEXT_DIRECTION_ANY_RTL, name = "anyRtl"),
   26256             @EnumEntry(value = TEXT_DIRECTION_LTR, name = "ltr"),
   26257             @EnumEntry(value = TEXT_DIRECTION_RTL, name = "rtl"),
   26258             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG, name = "firstStrong"),
   26259             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_LTR, name = "firstStrongLtr"),
   26260             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_RTL, name = "firstStrongRtl"),
   26261     })
   26262     @UnsupportedAppUsage
   26263     public int getRawTextDirection() {
   26264         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
   26265     }
   26266 
   26267     /**
   26268      * Set the text direction.
   26269      *
   26270      * @param textDirection the direction to set. Should be one of:
   26271      *
   26272      * {@link #TEXT_DIRECTION_INHERIT},
   26273      * {@link #TEXT_DIRECTION_FIRST_STRONG},
   26274      * {@link #TEXT_DIRECTION_ANY_RTL},
   26275      * {@link #TEXT_DIRECTION_LTR},
   26276      * {@link #TEXT_DIRECTION_RTL},
   26277      * {@link #TEXT_DIRECTION_LOCALE}
   26278      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
   26279      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
   26280      *
   26281      * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
   26282      * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
   26283      * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
   26284      *
   26285      * @attr ref android.R.styleable#View_textDirection
   26286      */
   26287     public void setTextDirection(int textDirection) {
   26288         if (getRawTextDirection() != textDirection) {
   26289             // Reset the current text direction and the resolved one
   26290             mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
   26291             resetResolvedTextDirection();
   26292             // Set the new text direction
   26293             mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
   26294             // Do resolution
   26295             resolveTextDirection();
   26296             // Notify change
   26297             onRtlPropertiesChanged(getLayoutDirection());
   26298             // Refresh
   26299             requestLayout();
   26300             invalidate(true);
   26301         }
   26302     }
   26303 
   26304     /**
   26305      * Return the resolved text direction.
   26306      *
   26307      * @return the resolved text direction. Returns one of:
   26308      *
   26309      * {@link #TEXT_DIRECTION_FIRST_STRONG},
   26310      * {@link #TEXT_DIRECTION_ANY_RTL},
   26311      * {@link #TEXT_DIRECTION_LTR},
   26312      * {@link #TEXT_DIRECTION_RTL},
   26313      * {@link #TEXT_DIRECTION_LOCALE},
   26314      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
   26315      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
   26316      *
   26317      * @attr ref android.R.styleable#View_textDirection
   26318      */
   26319     @ViewDebug.ExportedProperty(category = "text", mapping = {
   26320             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
   26321             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
   26322             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
   26323             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
   26324             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
   26325             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
   26326             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
   26327             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
   26328     })
   26329     @InspectableProperty(hasAttributeId = false, enumMapping = {
   26330             @EnumEntry(value = TEXT_DIRECTION_LOCALE, name = "locale"),
   26331             @EnumEntry(value = TEXT_DIRECTION_ANY_RTL, name = "anyRtl"),
   26332             @EnumEntry(value = TEXT_DIRECTION_LTR, name = "ltr"),
   26333             @EnumEntry(value = TEXT_DIRECTION_RTL, name = "rtl"),
   26334             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG, name = "firstStrong"),
   26335             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_LTR, name = "firstStrongLtr"),
   26336             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_RTL, name = "firstStrongRtl"),
   26337     })
   26338     public int getTextDirection() {
   26339         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
   26340     }
   26341 
   26342     /**
   26343      * Resolve the text direction.
   26344      *
   26345      * @return true if resolution has been done, false otherwise.
   26346      *
   26347      * @hide
   26348      */
   26349     public boolean resolveTextDirection() {
   26350         // Reset any previous text direction resolution
   26351         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
   26352 
   26353         if (hasRtlSupport()) {
   26354             // Set resolved text direction flag depending on text direction flag
   26355             final int textDirection = getRawTextDirection();
   26356             switch(textDirection) {
   26357                 case TEXT_DIRECTION_INHERIT:
   26358                     if (!canResolveTextDirection()) {
   26359                         // We cannot do the resolution if there is no parent, so use the default one
   26360                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   26361                         // Resolution will need to happen again later
   26362                         return false;
   26363                     }
   26364 
   26365                     // Parent has not yet resolved, so we still return the default
   26366                     try {
   26367                         if (!mParent.isTextDirectionResolved()) {
   26368                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   26369                             // Resolution will need to happen again later
   26370                             return false;
   26371                         }
   26372                     } catch (AbstractMethodError e) {
   26373                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   26374                                 " does not fully implement ViewParent", e);
   26375                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
   26376                                 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   26377                         return true;
   26378                     }
   26379 
   26380                     // Set current resolved direction to the same value as the parent's one
   26381                     int parentResolvedDirection;
   26382                     try {
   26383                         parentResolvedDirection = mParent.getTextDirection();
   26384                     } catch (AbstractMethodError e) {
   26385                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   26386                                 " does not fully implement ViewParent", e);
   26387                         parentResolvedDirection = TEXT_DIRECTION_LTR;
   26388                     }
   26389                     switch (parentResolvedDirection) {
   26390                         case TEXT_DIRECTION_FIRST_STRONG:
   26391                         case TEXT_DIRECTION_ANY_RTL:
   26392                         case TEXT_DIRECTION_LTR:
   26393                         case TEXT_DIRECTION_RTL:
   26394                         case TEXT_DIRECTION_LOCALE:
   26395                         case TEXT_DIRECTION_FIRST_STRONG_LTR:
   26396                         case TEXT_DIRECTION_FIRST_STRONG_RTL:
   26397                             mPrivateFlags2 |=
   26398                                     (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
   26399                             break;
   26400                         default:
   26401                             // Default resolved direction is "first strong" heuristic
   26402                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   26403                     }
   26404                     break;
   26405                 case TEXT_DIRECTION_FIRST_STRONG:
   26406                 case TEXT_DIRECTION_ANY_RTL:
   26407                 case TEXT_DIRECTION_LTR:
   26408                 case TEXT_DIRECTION_RTL:
   26409                 case TEXT_DIRECTION_LOCALE:
   26410                 case TEXT_DIRECTION_FIRST_STRONG_LTR:
   26411                 case TEXT_DIRECTION_FIRST_STRONG_RTL:
   26412                     // Resolved direction is the same as text direction
   26413                     mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
   26414                     break;
   26415                 default:
   26416                     // Default resolved direction is "first strong" heuristic
   26417                     mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   26418             }
   26419         } else {
   26420             // Default resolved direction is "first strong" heuristic
   26421             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   26422         }
   26423 
   26424         // Set to resolved
   26425         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
   26426         return true;
   26427     }
   26428 
   26429     /**
   26430      * Check if text direction resolution can be done.
   26431      *
   26432      * @return true if text direction resolution can be done otherwise return false.
   26433      */
   26434     public boolean canResolveTextDirection() {
   26435         switch (getRawTextDirection()) {
   26436             case TEXT_DIRECTION_INHERIT:
   26437                 if (mParent != null) {
   26438                     try {
   26439                         return mParent.canResolveTextDirection();
   26440                     } catch (AbstractMethodError e) {
   26441                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   26442                                 " does not fully implement ViewParent", e);
   26443                     }
   26444                 }
   26445                 return false;
   26446 
   26447             default:
   26448                 return true;
   26449         }
   26450     }
   26451 
   26452     /**
   26453      * Reset resolved text direction. Text direction will be resolved during a call to
   26454      * {@link #onMeasure(int, int)}.
   26455      *
   26456      * @hide
   26457      */
   26458     @TestApi
   26459     public void resetResolvedTextDirection() {
   26460         // Reset any previous text direction resolution
   26461         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
   26462         // Set to default value
   26463         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   26464     }
   26465 
   26466     /**
   26467      * @return true if text direction is inherited.
   26468      *
   26469      * @hide
   26470      */
   26471     public boolean isTextDirectionInherited() {
   26472         return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
   26473     }
   26474 
   26475     /**
   26476      * @return true if text direction is resolved.
   26477      */
   26478     public boolean isTextDirectionResolved() {
   26479         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
   26480     }
   26481 
   26482     /**
   26483      * Return the value specifying the text alignment or policy that was set with
   26484      * {@link #setTextAlignment(int)}.
   26485      *
   26486      * @return the defined text alignment. It can be one of:
   26487      *
   26488      * {@link #TEXT_ALIGNMENT_INHERIT},
   26489      * {@link #TEXT_ALIGNMENT_GRAVITY},
   26490      * {@link #TEXT_ALIGNMENT_CENTER},
   26491      * {@link #TEXT_ALIGNMENT_TEXT_START},
   26492      * {@link #TEXT_ALIGNMENT_TEXT_END},
   26493      * {@link #TEXT_ALIGNMENT_VIEW_START},
   26494      * {@link #TEXT_ALIGNMENT_VIEW_END}
   26495      *
   26496      * @attr ref android.R.styleable#View_textAlignment
   26497      *
   26498      * @hide
   26499      */
   26500     @ViewDebug.ExportedProperty(category = "text", mapping = {
   26501             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
   26502             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
   26503             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
   26504             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
   26505             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
   26506             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
   26507             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
   26508     })
   26509     @InspectableProperty(hasAttributeId = false, enumMapping = {
   26510             @EnumEntry(value = TEXT_ALIGNMENT_INHERIT, name = "inherit"),
   26511             @EnumEntry(value = TEXT_ALIGNMENT_GRAVITY, name = "gravity"),
   26512             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_START, name = "textStart"),
   26513             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_END, name = "textEnd"),
   26514             @EnumEntry(value = TEXT_ALIGNMENT_CENTER, name = "center"),
   26515             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_START, name = "viewStart"),
   26516             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_END, name = "viewEnd")
   26517     })
   26518     @TextAlignment
   26519     @UnsupportedAppUsage
   26520     public int getRawTextAlignment() {
   26521         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
   26522     }
   26523 
   26524     /**
   26525      * Set the text alignment.
   26526      *
   26527      * @param textAlignment The text alignment to set. Should be one of
   26528      *
   26529      * {@link #TEXT_ALIGNMENT_INHERIT},
   26530      * {@link #TEXT_ALIGNMENT_GRAVITY},
   26531      * {@link #TEXT_ALIGNMENT_CENTER},
   26532      * {@link #TEXT_ALIGNMENT_TEXT_START},
   26533      * {@link #TEXT_ALIGNMENT_TEXT_END},
   26534      * {@link #TEXT_ALIGNMENT_VIEW_START},
   26535      * {@link #TEXT_ALIGNMENT_VIEW_END}
   26536      *
   26537      * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
   26538      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
   26539      * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
   26540      *
   26541      * @attr ref android.R.styleable#View_textAlignment
   26542      */
   26543     public void setTextAlignment(@TextAlignment int textAlignment) {
   26544         if (textAlignment != getRawTextAlignment()) {
   26545             // Reset the current and resolved text alignment
   26546             mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
   26547             resetResolvedTextAlignment();
   26548             // Set the new text alignment
   26549             mPrivateFlags2 |=
   26550                     ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
   26551             // Do resolution
   26552             resolveTextAlignment();
   26553             // Notify change
   26554             onRtlPropertiesChanged(getLayoutDirection());
   26555             // Refresh
   26556             requestLayout();
   26557             invalidate(true);
   26558         }
   26559     }
   26560 
   26561     /**
   26562      * Return the resolved text alignment.
   26563      *
   26564      * @return the resolved text alignment. Returns one of:
   26565      *
   26566      * {@link #TEXT_ALIGNMENT_GRAVITY},
   26567      * {@link #TEXT_ALIGNMENT_CENTER},
   26568      * {@link #TEXT_ALIGNMENT_TEXT_START},
   26569      * {@link #TEXT_ALIGNMENT_TEXT_END},
   26570      * {@link #TEXT_ALIGNMENT_VIEW_START},
   26571      * {@link #TEXT_ALIGNMENT_VIEW_END}
   26572      *
   26573      * @attr ref android.R.styleable#View_textAlignment
   26574      */
   26575     @ViewDebug.ExportedProperty(category = "text", mapping = {
   26576             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
   26577             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
   26578             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
   26579             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
   26580             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
   26581             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
   26582             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
   26583     })
   26584     @InspectableProperty(enumMapping = {
   26585             @EnumEntry(value = TEXT_ALIGNMENT_GRAVITY, name = "gravity"),
   26586             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_START, name = "textStart"),
   26587             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_END, name = "textEnd"),
   26588             @EnumEntry(value = TEXT_ALIGNMENT_CENTER, name = "center"),
   26589             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_START, name = "viewStart"),
   26590             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_END, name = "viewEnd")
   26591     })
   26592     @TextAlignment
   26593     public int getTextAlignment() {
   26594         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
   26595                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
   26596     }
   26597 
   26598     /**
   26599      * Resolve the text alignment.
   26600      *
   26601      * @return true if resolution has been done, false otherwise.
   26602      *
   26603      * @hide
   26604      */
   26605     public boolean resolveTextAlignment() {
   26606         // Reset any previous text alignment resolution
   26607         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
   26608 
   26609         if (hasRtlSupport()) {
   26610             // Set resolved text alignment flag depending on text alignment flag
   26611             final int textAlignment = getRawTextAlignment();
   26612             switch (textAlignment) {
   26613                 case TEXT_ALIGNMENT_INHERIT:
   26614                     // Check if we can resolve the text alignment
   26615                     if (!canResolveTextAlignment()) {
   26616                         // We cannot do the resolution if there is no parent so use the default
   26617                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   26618                         // Resolution will need to happen again later
   26619                         return false;
   26620                     }
   26621 
   26622                     // Parent has not yet resolved, so we still return the default
   26623                     try {
   26624                         if (!mParent.isTextAlignmentResolved()) {
   26625                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   26626                             // Resolution will need to happen again later
   26627                             return false;
   26628                         }
   26629                     } catch (AbstractMethodError e) {
   26630                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   26631                                 " does not fully implement ViewParent", e);
   26632                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
   26633                                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   26634                         return true;
   26635                     }
   26636 
   26637                     int parentResolvedTextAlignment;
   26638                     try {
   26639                         parentResolvedTextAlignment = mParent.getTextAlignment();
   26640                     } catch (AbstractMethodError e) {
   26641                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   26642                                 " does not fully implement ViewParent", e);
   26643                         parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
   26644                     }
   26645                     switch (parentResolvedTextAlignment) {
   26646                         case TEXT_ALIGNMENT_GRAVITY:
   26647                         case TEXT_ALIGNMENT_TEXT_START:
   26648                         case TEXT_ALIGNMENT_TEXT_END:
   26649                         case TEXT_ALIGNMENT_CENTER:
   26650                         case TEXT_ALIGNMENT_VIEW_START:
   26651                         case TEXT_ALIGNMENT_VIEW_END:
   26652                             // Resolved text alignment is the same as the parent resolved
   26653                             // text alignment
   26654                             mPrivateFlags2 |=
   26655                                     (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
   26656                             break;
   26657                         default:
   26658                             // Use default resolved text alignment
   26659                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   26660                     }
   26661                     break;
   26662                 case TEXT_ALIGNMENT_GRAVITY:
   26663                 case TEXT_ALIGNMENT_TEXT_START:
   26664                 case TEXT_ALIGNMENT_TEXT_END:
   26665                 case TEXT_ALIGNMENT_CENTER:
   26666                 case TEXT_ALIGNMENT_VIEW_START:
   26667                 case TEXT_ALIGNMENT_VIEW_END:
   26668                     // Resolved text alignment is the same as text alignment
   26669                     mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
   26670                     break;
   26671                 default:
   26672                     // Use default resolved text alignment
   26673                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   26674             }
   26675         } else {
   26676             // Use default resolved text alignment
   26677             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   26678         }
   26679 
   26680         // Set the resolved
   26681         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
   26682         return true;
   26683     }
   26684 
   26685     /**
   26686      * Check if text alignment resolution can be done.
   26687      *
   26688      * @return true if text alignment resolution can be done otherwise return false.
   26689      */
   26690     public boolean canResolveTextAlignment() {
   26691         switch (getRawTextAlignment()) {
   26692             case TEXT_DIRECTION_INHERIT:
   26693                 if (mParent != null) {
   26694                     try {
   26695                         return mParent.canResolveTextAlignment();
   26696                     } catch (AbstractMethodError e) {
   26697                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   26698                                 " does not fully implement ViewParent", e);
   26699                     }
   26700                 }
   26701                 return false;
   26702 
   26703             default:
   26704                 return true;
   26705         }
   26706     }
   26707 
   26708     /**
   26709      * Reset resolved text alignment. Text alignment will be resolved during a call to
   26710      * {@link #onMeasure(int, int)}.
   26711      *
   26712      * @hide
   26713      */
   26714     @TestApi
   26715     public void resetResolvedTextAlignment() {
   26716         // Reset any previous text alignment resolution
   26717         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
   26718         // Set to default
   26719         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   26720     }
   26721 
   26722     /**
   26723      * @return true if text alignment is inherited.
   26724      *
   26725      * @hide
   26726      */
   26727     public boolean isTextAlignmentInherited() {
   26728         return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
   26729     }
   26730 
   26731     /**
   26732      * @return true if text alignment is resolved.
   26733      */
   26734     public boolean isTextAlignmentResolved() {
   26735         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
   26736     }
   26737 
   26738     /**
   26739      * Generate a value suitable for use in {@link #setId(int)}.
   26740      * This value will not collide with ID values generated at build time by aapt for R.id.
   26741      *
   26742      * @return a generated ID value
   26743      */
   26744     public static int generateViewId() {
   26745         for (;;) {
   26746             final int result = sNextGeneratedId.get();
   26747             // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
   26748             int newValue = result + 1;
   26749             if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
   26750             if (sNextGeneratedId.compareAndSet(result, newValue)) {
   26751                 return result;
   26752             }
   26753         }
   26754     }
   26755 
   26756     private static boolean isViewIdGenerated(int id) {
   26757         return (id & 0xFF000000) == 0 && (id & 0x00FFFFFF) != 0;
   26758     }
   26759 
   26760     /**
   26761      * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
   26762      * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
   26763      *                           a normal View or a ViewGroup with
   26764      *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
   26765      * @hide
   26766      */
   26767     public void captureTransitioningViews(List<View> transitioningViews) {
   26768         if (getVisibility() == View.VISIBLE) {
   26769             transitioningViews.add(this);
   26770         }
   26771     }
   26772 
   26773     /**
   26774      * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
   26775      * @param namedElements Will contain all Views in the hierarchy having a transitionName.
   26776      * @hide
   26777      */
   26778     public void findNamedViews(Map<String, View> namedElements) {
   26779         if (getVisibility() == VISIBLE || mGhostView != null) {
   26780             String transitionName = getTransitionName();
   26781             if (transitionName != null) {
   26782                 namedElements.put(transitionName, this);
   26783             }
   26784         }
   26785     }
   26786 
   26787     /**
   26788      * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
   26789      * The default implementation does not care the location or event types, but some subclasses
   26790      * may use it (such as WebViews).
   26791      * @param event The MotionEvent from a mouse
   26792      * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
   26793      *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
   26794      * @see PointerIcon
   26795      */
   26796     public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
   26797         final float x = event.getX(pointerIndex);
   26798         final float y = event.getY(pointerIndex);
   26799         if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
   26800             return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
   26801         }
   26802         return mPointerIcon;
   26803     }
   26804 
   26805     /**
   26806      * Set the pointer icon for the current view.
   26807      * Passing {@code null} will restore the pointer icon to its default value.
   26808      * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
   26809      */
   26810     public void setPointerIcon(PointerIcon pointerIcon) {
   26811         mPointerIcon = pointerIcon;
   26812         if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
   26813             return;
   26814         }
   26815         try {
   26816             mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
   26817         } catch (RemoteException e) {
   26818         }
   26819     }
   26820 
   26821     /**
   26822      * Gets the pointer icon for the current view.
   26823      */
   26824     @InspectableProperty
   26825     public PointerIcon getPointerIcon() {
   26826         return mPointerIcon;
   26827     }
   26828 
   26829     /**
   26830      * Checks pointer capture status.
   26831      *
   26832      * @return true if the view has pointer capture.
   26833      * @see #requestPointerCapture()
   26834      * @see #hasPointerCapture()
   26835      */
   26836     public boolean hasPointerCapture() {
   26837         final ViewRootImpl viewRootImpl = getViewRootImpl();
   26838         if (viewRootImpl == null) {
   26839             return false;
   26840         }
   26841         return viewRootImpl.hasPointerCapture();
   26842     }
   26843 
   26844     /**
   26845      * Requests pointer capture mode.
   26846      * <p>
   26847      * When the window has pointer capture, the mouse pointer icon will disappear and will not
   26848      * change its position. Further mouse will be dispatched with the source
   26849      * {@link InputDevice#SOURCE_MOUSE_RELATIVE}, and relative position changes will be available
   26850      * through {@link MotionEvent#getX} and {@link MotionEvent#getY}. Non-mouse events
   26851      * (touchscreens, or stylus) will not be affected.
   26852      * <p>
   26853      * If the window already has pointer capture, this call does nothing.
   26854      * <p>
   26855      * The capture may be released through {@link #releasePointerCapture()}, or will be lost
   26856      * automatically when the window loses focus.
   26857      *
   26858      * @see #releasePointerCapture()
   26859      * @see #hasPointerCapture()
   26860      */
   26861     public void requestPointerCapture() {
   26862         final ViewRootImpl viewRootImpl = getViewRootImpl();
   26863         if (viewRootImpl != null) {
   26864             viewRootImpl.requestPointerCapture(true);
   26865         }
   26866     }
   26867 
   26868 
   26869     /**
   26870      * Releases the pointer capture.
   26871      * <p>
   26872      * If the window does not have pointer capture, this call will do nothing.
   26873      * @see #requestPointerCapture()
   26874      * @see #hasPointerCapture()
   26875      */
   26876     public void releasePointerCapture() {
   26877         final ViewRootImpl viewRootImpl = getViewRootImpl();
   26878         if (viewRootImpl != null) {
   26879             viewRootImpl.requestPointerCapture(false);
   26880         }
   26881     }
   26882 
   26883     /**
   26884      * Called when the window has just acquired or lost pointer capture.
   26885      *
   26886      * @param hasCapture True if the view now has pointerCapture, false otherwise.
   26887      */
   26888     @CallSuper
   26889     public void onPointerCaptureChange(boolean hasCapture) {
   26890     }
   26891 
   26892     /**
   26893      * @see #onPointerCaptureChange
   26894      */
   26895     public void dispatchPointerCaptureChanged(boolean hasCapture) {
   26896         onPointerCaptureChange(hasCapture);
   26897     }
   26898 
   26899     /**
   26900      * Implement this method to handle captured pointer events
   26901      *
   26902      * @param event The captured pointer event.
   26903      * @return True if the event was handled, false otherwise.
   26904      * @see #requestPointerCapture()
   26905      */
   26906     public boolean onCapturedPointerEvent(MotionEvent event) {
   26907         return false;
   26908     }
   26909 
   26910     /**
   26911      * Interface definition for a callback to be invoked when a captured pointer event
   26912      * is being dispatched this view. The callback will be invoked before the event is
   26913      * given to the view.
   26914      */
   26915     public interface OnCapturedPointerListener {
   26916         /**
   26917          * Called when a captured pointer event is dispatched to a view.
   26918          * @param view The view this event has been dispatched to.
   26919          * @param event The captured event.
   26920          * @return True if the listener has consumed the event, false otherwise.
   26921          */
   26922         boolean onCapturedPointer(View view, MotionEvent event);
   26923     }
   26924 
   26925     /**
   26926      * Set a listener to receive callbacks when the pointer capture state of a view changes.
   26927      * @param l  The {@link OnCapturedPointerListener} to receive callbacks.
   26928      */
   26929     public void setOnCapturedPointerListener(OnCapturedPointerListener l) {
   26930         getListenerInfo().mOnCapturedPointerListener = l;
   26931     }
   26932 
   26933     // Properties
   26934     //
   26935     /**
   26936      * A Property wrapper around the <code>alpha</code> functionality handled by the
   26937      * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
   26938      */
   26939     public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
   26940         @Override
   26941         public void setValue(View object, float value) {
   26942             object.setAlpha(value);
   26943         }
   26944 
   26945         @Override
   26946         public Float get(View object) {
   26947             return object.getAlpha();
   26948         }
   26949     };
   26950 
   26951     /**
   26952      * A Property wrapper around the <code>translationX</code> functionality handled by the
   26953      * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
   26954      */
   26955     public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
   26956         @Override
   26957         public void setValue(View object, float value) {
   26958             object.setTranslationX(value);
   26959         }
   26960 
   26961                 @Override
   26962         public Float get(View object) {
   26963             return object.getTranslationX();
   26964         }
   26965     };
   26966 
   26967     /**
   26968      * A Property wrapper around the <code>translationY</code> functionality handled by the
   26969      * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
   26970      */
   26971     public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
   26972         @Override
   26973         public void setValue(View object, float value) {
   26974             object.setTranslationY(value);
   26975         }
   26976 
   26977         @Override
   26978         public Float get(View object) {
   26979             return object.getTranslationY();
   26980         }
   26981     };
   26982 
   26983     /**
   26984      * A Property wrapper around the <code>translationZ</code> functionality handled by the
   26985      * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
   26986      */
   26987     public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
   26988         @Override
   26989         public void setValue(View object, float value) {
   26990             object.setTranslationZ(value);
   26991         }
   26992 
   26993         @Override
   26994         public Float get(View object) {
   26995             return object.getTranslationZ();
   26996         }
   26997     };
   26998 
   26999     /**
   27000      * A Property wrapper around the <code>x</code> functionality handled by the
   27001      * {@link View#setX(float)} and {@link View#getX()} methods.
   27002      */
   27003     public static final Property<View, Float> X = new FloatProperty<View>("x") {
   27004         @Override
   27005         public void setValue(View object, float value) {
   27006             object.setX(value);
   27007         }
   27008 
   27009         @Override
   27010         public Float get(View object) {
   27011             return object.getX();
   27012         }
   27013     };
   27014 
   27015     /**
   27016      * A Property wrapper around the <code>y</code> functionality handled by the
   27017      * {@link View#setY(float)} and {@link View#getY()} methods.
   27018      */
   27019     public static final Property<View, Float> Y = new FloatProperty<View>("y") {
   27020         @Override
   27021         public void setValue(View object, float value) {
   27022             object.setY(value);
   27023         }
   27024 
   27025         @Override
   27026         public Float get(View object) {
   27027             return object.getY();
   27028         }
   27029     };
   27030 
   27031     /**
   27032      * A Property wrapper around the <code>z</code> functionality handled by the
   27033      * {@link View#setZ(float)} and {@link View#getZ()} methods.
   27034      */
   27035     public static final Property<View, Float> Z = new FloatProperty<View>("z") {
   27036         @Override
   27037         public void setValue(View object, float value) {
   27038             object.setZ(value);
   27039         }
   27040 
   27041         @Override
   27042         public Float get(View object) {
   27043             return object.getZ();
   27044         }
   27045     };
   27046 
   27047     /**
   27048      * A Property wrapper around the <code>rotation</code> functionality handled by the
   27049      * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
   27050      */
   27051     public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
   27052         @Override
   27053         public void setValue(View object, float value) {
   27054             object.setRotation(value);
   27055         }
   27056 
   27057         @Override
   27058         public Float get(View object) {
   27059             return object.getRotation();
   27060         }
   27061     };
   27062 
   27063     /**
   27064      * A Property wrapper around the <code>rotationX</code> functionality handled by the
   27065      * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
   27066      */
   27067     public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
   27068         @Override
   27069         public void setValue(View object, float value) {
   27070             object.setRotationX(value);
   27071         }
   27072 
   27073         @Override
   27074         public Float get(View object) {
   27075             return object.getRotationX();
   27076         }
   27077     };
   27078 
   27079     /**
   27080      * A Property wrapper around the <code>rotationY</code> functionality handled by the
   27081      * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
   27082      */
   27083     public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
   27084         @Override
   27085         public void setValue(View object, float value) {
   27086             object.setRotationY(value);
   27087         }
   27088 
   27089         @Override
   27090         public Float get(View object) {
   27091             return object.getRotationY();
   27092         }
   27093     };
   27094 
   27095     /**
   27096      * A Property wrapper around the <code>scaleX</code> functionality handled by the
   27097      * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
   27098      */
   27099     public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
   27100         @Override
   27101         public void setValue(View object, float value) {
   27102             object.setScaleX(value);
   27103         }
   27104 
   27105         @Override
   27106         public Float get(View object) {
   27107             return object.getScaleX();
   27108         }
   27109     };
   27110 
   27111     /**
   27112      * A Property wrapper around the <code>scaleY</code> functionality handled by the
   27113      * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
   27114      */
   27115     public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
   27116         @Override
   27117         public void setValue(View object, float value) {
   27118             object.setScaleY(value);
   27119         }
   27120 
   27121         @Override
   27122         public Float get(View object) {
   27123             return object.getScaleY();
   27124         }
   27125     };
   27126 
   27127     /**
   27128      * A MeasureSpec encapsulates the layout requirements passed from parent to child.
   27129      * Each MeasureSpec represents a requirement for either the width or the height.
   27130      * A MeasureSpec is comprised of a size and a mode. There are three possible
   27131      * modes:
   27132      * <dl>
   27133      * <dt>UNSPECIFIED</dt>
   27134      * <dd>
   27135      * The parent has not imposed any constraint on the child. It can be whatever size
   27136      * it wants.
   27137      * </dd>
   27138      *
   27139      * <dt>EXACTLY</dt>
   27140      * <dd>
   27141      * The parent has determined an exact size for the child. The child is going to be
   27142      * given those bounds regardless of how big it wants to be.
   27143      * </dd>
   27144      *
   27145      * <dt>AT_MOST</dt>
   27146      * <dd>
   27147      * The child can be as large as it wants up to the specified size.
   27148      * </dd>
   27149      * </dl>
   27150      *
   27151      * MeasureSpecs are implemented as ints to reduce object allocation. This class
   27152      * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
   27153      */
   27154     public static class MeasureSpec {
   27155         private static final int MODE_SHIFT = 30;
   27156         private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
   27157 
   27158         /** @hide */
   27159         @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
   27160         @Retention(RetentionPolicy.SOURCE)
   27161         public @interface MeasureSpecMode {}
   27162 
   27163         /**
   27164          * Measure specification mode: The parent has not imposed any constraint
   27165          * on the child. It can be whatever size it wants.
   27166          */
   27167         public static final int UNSPECIFIED = 0 << MODE_SHIFT;
   27168 
   27169         /**
   27170          * Measure specification mode: The parent has determined an exact size
   27171          * for the child. The child is going to be given those bounds regardless
   27172          * of how big it wants to be.
   27173          */
   27174         public static final int EXACTLY     = 1 << MODE_SHIFT;
   27175 
   27176         /**
   27177          * Measure specification mode: The child can be as large as it wants up
   27178          * to the specified size.
   27179          */
   27180         public static final int AT_MOST     = 2 << MODE_SHIFT;
   27181 
   27182         /**
   27183          * Creates a measure specification based on the supplied size and mode.
   27184          *
   27185          * The mode must always be one of the following:
   27186          * <ul>
   27187          *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
   27188          *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
   27189          *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
   27190          * </ul>
   27191          *
   27192          * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
   27193          * implementation was such that the order of arguments did not matter
   27194          * and overflow in either value could impact the resulting MeasureSpec.
   27195          * {@link android.widget.RelativeLayout} was affected by this bug.
   27196          * Apps targeting API levels greater than 17 will get the fixed, more strict
   27197          * behavior.</p>
   27198          *
   27199          * @param size the size of the measure specification
   27200          * @param mode the mode of the measure specification
   27201          * @return the measure specification based on size and mode
   27202          */
   27203         public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
   27204                                           @MeasureSpecMode int mode) {
   27205             if (sUseBrokenMakeMeasureSpec) {
   27206                 return size + mode;
   27207             } else {
   27208                 return (size & ~MODE_MASK) | (mode & MODE_MASK);
   27209             }
   27210         }
   27211 
   27212         /**
   27213          * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
   27214          * will automatically get a size of 0. Older apps expect this.
   27215          *
   27216          * @hide internal use only for compatibility with system widgets and older apps
   27217          */
   27218         @UnsupportedAppUsage
   27219         public static int makeSafeMeasureSpec(int size, int mode) {
   27220             if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
   27221                 return 0;
   27222             }
   27223             return makeMeasureSpec(size, mode);
   27224         }
   27225 
   27226         /**
   27227          * Extracts the mode from the supplied measure specification.
   27228          *
   27229          * @param measureSpec the measure specification to extract the mode from
   27230          * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
   27231          *         {@link android.view.View.MeasureSpec#AT_MOST} or
   27232          *         {@link android.view.View.MeasureSpec#EXACTLY}
   27233          */
   27234         @MeasureSpecMode
   27235         public static int getMode(int measureSpec) {
   27236             //noinspection ResourceType
   27237             return (measureSpec & MODE_MASK);
   27238         }
   27239 
   27240         /**
   27241          * Extracts the size from the supplied measure specification.
   27242          *
   27243          * @param measureSpec the measure specification to extract the size from
   27244          * @return the size in pixels defined in the supplied measure specification
   27245          */
   27246         public static int getSize(int measureSpec) {
   27247             return (measureSpec & ~MODE_MASK);
   27248         }
   27249 
   27250         static int adjust(int measureSpec, int delta) {
   27251             final int mode = getMode(measureSpec);
   27252             int size = getSize(measureSpec);
   27253             if (mode == UNSPECIFIED) {
   27254                 // No need to adjust size for UNSPECIFIED mode.
   27255                 return makeMeasureSpec(size, UNSPECIFIED);
   27256             }
   27257             size += delta;
   27258             if (size < 0) {
   27259                 Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
   27260                         ") spec: " + toString(measureSpec) + " delta: " + delta);
   27261                 size = 0;
   27262             }
   27263             return makeMeasureSpec(size, mode);
   27264         }
   27265 
   27266         /**
   27267          * Returns a String representation of the specified measure
   27268          * specification.
   27269          *
   27270          * @param measureSpec the measure specification to convert to a String
   27271          * @return a String with the following format: "MeasureSpec: MODE SIZE"
   27272          */
   27273         public static String toString(int measureSpec) {
   27274             int mode = getMode(measureSpec);
   27275             int size = getSize(measureSpec);
   27276 
   27277             StringBuilder sb = new StringBuilder("MeasureSpec: ");
   27278 
   27279             if (mode == UNSPECIFIED)
   27280                 sb.append("UNSPECIFIED ");
   27281             else if (mode == EXACTLY)
   27282                 sb.append("EXACTLY ");
   27283             else if (mode == AT_MOST)
   27284                 sb.append("AT_MOST ");
   27285             else
   27286                 sb.append(mode).append(" ");
   27287 
   27288             sb.append(size);
   27289             return sb.toString();
   27290         }
   27291     }
   27292 
   27293     private final class CheckForLongPress implements Runnable {
   27294         private int mOriginalWindowAttachCount;
   27295         private float mX;
   27296         private float mY;
   27297         private boolean mOriginalPressedState;
   27298         /**
   27299          * The classification of the long click being checked: one of the
   27300          * StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__* constants.
   27301          */
   27302         private int mClassification;
   27303 
   27304         @Override
   27305         public void run() {
   27306             if ((mOriginalPressedState == isPressed()) && (mParent != null)
   27307                     && mOriginalWindowAttachCount == mWindowAttachCount) {
   27308                 recordGestureClassification(mClassification);
   27309                 if (performLongClick(mX, mY)) {
   27310                     mHasPerformedLongPress = true;
   27311                 }
   27312             }
   27313         }
   27314 
   27315         public void setAnchor(float x, float y) {
   27316             mX = x;
   27317             mY = y;
   27318         }
   27319 
   27320         public void rememberWindowAttachCount() {
   27321             mOriginalWindowAttachCount = mWindowAttachCount;
   27322         }
   27323 
   27324         public void rememberPressedState() {
   27325             mOriginalPressedState = isPressed();
   27326         }
   27327 
   27328         public void setClassification(int classification) {
   27329             mClassification = classification;
   27330         }
   27331     }
   27332 
   27333     private final class CheckForTap implements Runnable {
   27334         public float x;
   27335         public float y;
   27336 
   27337         @Override
   27338         public void run() {
   27339             mPrivateFlags &= ~PFLAG_PREPRESSED;
   27340             setPressed(true, x, y);
   27341             final long delay =
   27342                     ViewConfiguration.getLongPressTimeout() - ViewConfiguration.getTapTimeout();
   27343             checkForLongClick(delay, x, y, TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
   27344         }
   27345     }
   27346 
   27347     private final class PerformClick implements Runnable {
   27348         @Override
   27349         public void run() {
   27350             recordGestureClassification(TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP);
   27351             performClickInternal();
   27352         }
   27353     }
   27354 
   27355     /** Records a classification for the current event stream. */
   27356     private void recordGestureClassification(int classification) {
   27357         if (classification == TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION) {
   27358             return;
   27359         }
   27360         // To avoid negatively impacting View performance, the latency and displacement metrics
   27361         // are omitted.
   27362         StatsLog.write(StatsLog.TOUCH_GESTURE_CLASSIFIED, getClass().getName(), classification);
   27363     }
   27364 
   27365     /**
   27366      * This method returns a ViewPropertyAnimator object, which can be used to animate
   27367      * specific properties on this View.
   27368      *
   27369      * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
   27370      */
   27371     public ViewPropertyAnimator animate() {
   27372         if (mAnimator == null) {
   27373             mAnimator = new ViewPropertyAnimator(this);
   27374         }
   27375         return mAnimator;
   27376     }
   27377 
   27378     /**
   27379      * Sets the name of the View to be used to identify Views in Transitions.
   27380      * Names should be unique in the View hierarchy.
   27381      *
   27382      * @param transitionName The name of the View to uniquely identify it for Transitions.
   27383      */
   27384     public final void setTransitionName(String transitionName) {
   27385         mTransitionName = transitionName;
   27386     }
   27387 
   27388     /**
   27389      * Returns the name of the View to be used to identify Views in Transitions.
   27390      * Names should be unique in the View hierarchy.
   27391      *
   27392      * <p>This returns null if the View has not been given a name.</p>
   27393      *
   27394      * @return The name used of the View to be used to identify Views in Transitions or null
   27395      * if no name has been given.
   27396      */
   27397     @ViewDebug.ExportedProperty
   27398     @InspectableProperty
   27399     public String getTransitionName() {
   27400         return mTransitionName;
   27401     }
   27402 
   27403     /**
   27404      * @hide
   27405      */
   27406     public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
   27407         // Do nothing.
   27408     }
   27409 
   27410     /**
   27411      * Interface definition for a callback to be invoked when a hardware key event is
   27412      * dispatched to this view. The callback will be invoked before the key event is
   27413      * given to the view. This is only useful for hardware keyboards; a software input
   27414      * method has no obligation to trigger this listener.
   27415      */
   27416     public interface OnKeyListener {
   27417         /**
   27418          * Called when a hardware key is dispatched to a view. This allows listeners to
   27419          * get a chance to respond before the target view.
   27420          * <p>Key presses in software keyboards will generally NOT trigger this method,
   27421          * although some may elect to do so in some situations. Do not assume a
   27422          * software input method has to be key-based; even if it is, it may use key presses
   27423          * in a different way than you expect, so there is no way to reliably catch soft
   27424          * input key presses.
   27425          *
   27426          * @param v The view the key has been dispatched to.
   27427          * @param keyCode The code for the physical key that was pressed
   27428          * @param event The KeyEvent object containing full information about
   27429          *        the event.
   27430          * @return True if the listener has consumed the event, false otherwise.
   27431          */
   27432         boolean onKey(View v, int keyCode, KeyEvent event);
   27433     }
   27434 
   27435     /**
   27436      * Interface definition for a callback to be invoked when a hardware key event hasn't
   27437      * been handled by the view hierarchy.
   27438      */
   27439     public interface OnUnhandledKeyEventListener {
   27440         /**
   27441          * Called when a hardware key is dispatched to a view after being unhandled during normal
   27442          * {@link KeyEvent} dispatch.
   27443          *
   27444          * @param v The view the key has been dispatched to.
   27445          * @param event The KeyEvent object containing information about the event.
   27446          * @return {@code true} if the listener has consumed the event, {@code false} otherwise.
   27447          */
   27448         boolean onUnhandledKeyEvent(View v, KeyEvent event);
   27449     }
   27450 
   27451     /**
   27452      * Interface definition for a callback to be invoked when a touch event is
   27453      * dispatched to this view. The callback will be invoked before the touch
   27454      * event is given to the view.
   27455      */
   27456     public interface OnTouchListener {
   27457         /**
   27458          * Called when a touch event is dispatched to a view. This allows listeners to
   27459          * get a chance to respond before the target view.
   27460          *
   27461          * @param v The view the touch event has been dispatched to.
   27462          * @param event The MotionEvent object containing full information about
   27463          *        the event.
   27464          * @return True if the listener has consumed the event, false otherwise.
   27465          */
   27466         boolean onTouch(View v, MotionEvent event);
   27467     }
   27468 
   27469     /**
   27470      * Interface definition for a callback to be invoked when a hover event is
   27471      * dispatched to this view. The callback will be invoked before the hover
   27472      * event is given to the view.
   27473      */
   27474     public interface OnHoverListener {
   27475         /**
   27476          * Called when a hover event is dispatched to a view. This allows listeners to
   27477          * get a chance to respond before the target view.
   27478          *
   27479          * @param v The view the hover event has been dispatched to.
   27480          * @param event The MotionEvent object containing full information about
   27481          *        the event.
   27482          * @return True if the listener has consumed the event, false otherwise.
   27483          */
   27484         boolean onHover(View v, MotionEvent event);
   27485     }
   27486 
   27487     /**
   27488      * Interface definition for a callback to be invoked when a generic motion event is
   27489      * dispatched to this view. The callback will be invoked before the generic motion
   27490      * event is given to the view.
   27491      */
   27492     public interface OnGenericMotionListener {
   27493         /**
   27494          * Called when a generic motion event is dispatched to a view. This allows listeners to
   27495          * get a chance to respond before the target view.
   27496          *
   27497          * @param v The view the generic motion event has been dispatched to.
   27498          * @param event The MotionEvent object containing full information about
   27499          *        the event.
   27500          * @return True if the listener has consumed the event, false otherwise.
   27501          */
   27502         boolean onGenericMotion(View v, MotionEvent event);
   27503     }
   27504 
   27505     /**
   27506      * Interface definition for a callback to be invoked when a view has been clicked and held.
   27507      */
   27508     public interface OnLongClickListener {
   27509         /**
   27510          * Called when a view has been clicked and held.
   27511          *
   27512          * @param v The view that was clicked and held.
   27513          *
   27514          * @return true if the callback consumed the long click, false otherwise.
   27515          */
   27516         boolean onLongClick(View v);
   27517     }
   27518 
   27519     /**
   27520      * Interface definition for a callback to be invoked when a drag is being dispatched
   27521      * to this view.  The callback will be invoked before the hosting view's own
   27522      * onDrag(event) method.  If the listener wants to fall back to the hosting view's
   27523      * onDrag(event) behavior, it should return 'false' from this callback.
   27524      *
   27525      * <div class="special reference">
   27526      * <h3>Developer Guides</h3>
   27527      * <p>For a guide to implementing drag and drop features, read the
   27528      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
   27529      * </div>
   27530      */
   27531     public interface OnDragListener {
   27532         /**
   27533          * Called when a drag event is dispatched to a view. This allows listeners
   27534          * to get a chance to override base View behavior.
   27535          *
   27536          * @param v The View that received the drag event.
   27537          * @param event The {@link android.view.DragEvent} object for the drag event.
   27538          * @return {@code true} if the drag event was handled successfully, or {@code false}
   27539          * if the drag event was not handled. Note that {@code false} will trigger the View
   27540          * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
   27541          */
   27542         boolean onDrag(View v, DragEvent event);
   27543     }
   27544 
   27545     /**
   27546      * Interface definition for a callback to be invoked when the focus state of
   27547      * a view changed.
   27548      */
   27549     public interface OnFocusChangeListener {
   27550         /**
   27551          * Called when the focus state of a view has changed.
   27552          *
   27553          * @param v The view whose state has changed.
   27554          * @param hasFocus The new focus state of v.
   27555          */
   27556         void onFocusChange(View v, boolean hasFocus);
   27557     }
   27558 
   27559     /**
   27560      * Interface definition for a callback to be invoked when a view is clicked.
   27561      */
   27562     public interface OnClickListener {
   27563         /**
   27564          * Called when a view has been clicked.
   27565          *
   27566          * @param v The view that was clicked.
   27567          */
   27568         void onClick(View v);
   27569     }
   27570 
   27571     /**
   27572      * Interface definition for a callback to be invoked when a view is context clicked.
   27573      */
   27574     public interface OnContextClickListener {
   27575         /**
   27576          * Called when a view is context clicked.
   27577          *
   27578          * @param v The view that has been context clicked.
   27579          * @return true if the callback consumed the context click, false otherwise.
   27580          */
   27581         boolean onContextClick(View v);
   27582     }
   27583 
   27584     /**
   27585      * Interface definition for a callback to be invoked when the context menu
   27586      * for this view is being built.
   27587      */
   27588     public interface OnCreateContextMenuListener {
   27589         /**
   27590          * Called when the context menu for this view is being built. It is not
   27591          * safe to hold onto the menu after this method returns.
   27592          *
   27593          * @param menu The context menu that is being built
   27594          * @param v The view for which the context menu is being built
   27595          * @param menuInfo Extra information about the item for which the
   27596          *            context menu should be shown. This information will vary
   27597          *            depending on the class of v.
   27598          */
   27599         void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
   27600     }
   27601 
   27602     /**
   27603      * Interface definition for a callback to be invoked when the status bar changes
   27604      * visibility.  This reports <strong>global</strong> changes to the system UI
   27605      * state, not what the application is requesting.
   27606      *
   27607      * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
   27608      */
   27609     public interface OnSystemUiVisibilityChangeListener {
   27610         /**
   27611          * Called when the status bar changes visibility because of a call to
   27612          * {@link View#setSystemUiVisibility(int)}.
   27613          *
   27614          * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
   27615          * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
   27616          * This tells you the <strong>global</strong> state of these UI visibility
   27617          * flags, not what your app is currently applying.
   27618          */
   27619         public void onSystemUiVisibilityChange(int visibility);
   27620     }
   27621 
   27622     /**
   27623      * Interface definition for a callback to be invoked when this view is attached
   27624      * or detached from its window.
   27625      */
   27626     public interface OnAttachStateChangeListener {
   27627         /**
   27628          * Called when the view is attached to a window.
   27629          * @param v The view that was attached
   27630          */
   27631         public void onViewAttachedToWindow(View v);
   27632         /**
   27633          * Called when the view is detached from a window.
   27634          * @param v The view that was detached
   27635          */
   27636         public void onViewDetachedFromWindow(View v);
   27637     }
   27638 
   27639     /**
   27640      * Listener for applying window insets on a view in a custom way.
   27641      *
   27642      * <p>Apps may choose to implement this interface if they want to apply custom policy
   27643      * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
   27644      * is set, its
   27645      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
   27646      * method will be called instead of the View's own
   27647      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
   27648      * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
   27649      * the View's normal behavior as part of its own.</p>
   27650      */
   27651     public interface OnApplyWindowInsetsListener {
   27652         /**
   27653          * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
   27654          * on a View, this listener method will be called instead of the view's own
   27655          * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
   27656          *
   27657          * @param v The view applying window insets
   27658          * @param insets The insets to apply
   27659          * @return The insets supplied, minus any insets that were consumed
   27660          */
   27661         public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
   27662     }
   27663 
   27664     private final class UnsetPressedState implements Runnable {
   27665         @Override
   27666         public void run() {
   27667             setPressed(false);
   27668         }
   27669     }
   27670 
   27671     /**
   27672      * When a view becomes invisible checks if autofill considers the view invisible too. This
   27673      * happens after the regular removal operation to make sure the operation is finished by the
   27674      * time this is called.
   27675      */
   27676     private static class VisibilityChangeForAutofillHandler extends Handler {
   27677         private final AutofillManager mAfm;
   27678         private final View mView;
   27679 
   27680         private VisibilityChangeForAutofillHandler(@NonNull AutofillManager afm,
   27681                 @NonNull View view) {
   27682             mAfm = afm;
   27683             mView = view;
   27684         }
   27685 
   27686         @Override
   27687         public void handleMessage(Message msg) {
   27688             mAfm.notifyViewVisibilityChanged(mView, mView.isShown());
   27689         }
   27690     }
   27691 
   27692     /**
   27693      * Base class for derived classes that want to save and restore their own
   27694      * state in {@link android.view.View#onSaveInstanceState()}.
   27695      */
   27696     public static class BaseSavedState extends AbsSavedState {
   27697         static final int START_ACTIVITY_REQUESTED_WHO_SAVED = 0b1;
   27698         static final int IS_AUTOFILLED = 0b10;
   27699         static final int AUTOFILL_ID = 0b100;
   27700 
   27701         // Flags that describe what data in this state is valid
   27702         int mSavedData;
   27703         String mStartActivityRequestWhoSaved;
   27704         boolean mIsAutofilled;
   27705         int mAutofillViewId;
   27706 
   27707         /**
   27708          * Constructor used when reading from a parcel. Reads the state of the superclass.
   27709          *
   27710          * @param source parcel to read from
   27711          */
   27712         public BaseSavedState(Parcel source) {
   27713             this(source, null);
   27714         }
   27715 
   27716         /**
   27717          * Constructor used when reading from a parcel using a given class loader.
   27718          * Reads the state of the superclass.
   27719          *
   27720          * @param source parcel to read from
   27721          * @param loader ClassLoader to use for reading
   27722          */
   27723         public BaseSavedState(Parcel source, ClassLoader loader) {
   27724             super(source, loader);
   27725             mSavedData = source.readInt();
   27726             mStartActivityRequestWhoSaved = source.readString();
   27727             mIsAutofilled = source.readBoolean();
   27728             mAutofillViewId = source.readInt();
   27729         }
   27730 
   27731         /**
   27732          * Constructor called by derived classes when creating their SavedState objects
   27733          *
   27734          * @param superState The state of the superclass of this view
   27735          */
   27736         public BaseSavedState(Parcelable superState) {
   27737             super(superState);
   27738         }
   27739 
   27740         @Override
   27741         public void writeToParcel(Parcel out, int flags) {
   27742             super.writeToParcel(out, flags);
   27743 
   27744             out.writeInt(mSavedData);
   27745             out.writeString(mStartActivityRequestWhoSaved);
   27746             out.writeBoolean(mIsAutofilled);
   27747             out.writeInt(mAutofillViewId);
   27748         }
   27749 
   27750         public static final @android.annotation.NonNull Parcelable.Creator<BaseSavedState> CREATOR
   27751                 = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
   27752             @Override
   27753             public BaseSavedState createFromParcel(Parcel in) {
   27754                 return new BaseSavedState(in);
   27755             }
   27756 
   27757             @Override
   27758             public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
   27759                 return new BaseSavedState(in, loader);
   27760             }
   27761 
   27762             @Override
   27763             public BaseSavedState[] newArray(int size) {
   27764                 return new BaseSavedState[size];
   27765             }
   27766         };
   27767     }
   27768 
   27769     /**
   27770      * A set of information given to a view when it is attached to its parent
   27771      * window.
   27772      */
   27773     final static class AttachInfo {
   27774         interface Callbacks {
   27775             void playSoundEffect(int effectId);
   27776             boolean performHapticFeedback(int effectId, boolean always);
   27777         }
   27778 
   27779         /**
   27780          * InvalidateInfo is used to post invalidate(int, int, int, int) messages
   27781          * to a Handler. This class contains the target (View) to invalidate and
   27782          * the coordinates of the dirty rectangle.
   27783          *
   27784          * For performance purposes, this class also implements a pool of up to
   27785          * POOL_LIMIT objects that get reused. This reduces memory allocations
   27786          * whenever possible.
   27787          */
   27788         static class InvalidateInfo {
   27789             private static final int POOL_LIMIT = 10;
   27790 
   27791             private static final SynchronizedPool<InvalidateInfo> sPool =
   27792                     new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
   27793 
   27794             @UnsupportedAppUsage
   27795             View target;
   27796 
   27797             @UnsupportedAppUsage
   27798             int left;
   27799             @UnsupportedAppUsage
   27800             int top;
   27801             @UnsupportedAppUsage
   27802             int right;
   27803             @UnsupportedAppUsage
   27804             int bottom;
   27805 
   27806             public static InvalidateInfo obtain() {
   27807                 InvalidateInfo instance = sPool.acquire();
   27808                 return (instance != null) ? instance : new InvalidateInfo();
   27809             }
   27810 
   27811             public void recycle() {
   27812                 target = null;
   27813                 sPool.release(this);
   27814             }
   27815         }
   27816 
   27817         @UnsupportedAppUsage
   27818         final IWindowSession mSession;
   27819 
   27820         @UnsupportedAppUsage
   27821         final IWindow mWindow;
   27822 
   27823         final IBinder mWindowToken;
   27824 
   27825         Display mDisplay;
   27826 
   27827         final Callbacks mRootCallbacks;
   27828 
   27829         IWindowId mIWindowId;
   27830         WindowId mWindowId;
   27831 
   27832         /**
   27833          * The top view of the hierarchy.
   27834          */
   27835         View mRootView;
   27836 
   27837         IBinder mPanelParentWindowToken;
   27838 
   27839         boolean mHardwareAccelerated;
   27840         boolean mHardwareAccelerationRequested;
   27841         ThreadedRenderer mThreadedRenderer;
   27842         List<RenderNode> mPendingAnimatingRenderNodes;
   27843 
   27844         /**
   27845          * The state of the display to which the window is attached, as reported
   27846          * by {@link Display#getState()}.  Note that the display state constants
   27847          * declared by {@link Display} do not exactly line up with the screen state
   27848          * constants declared by {@link View} (there are more display states than
   27849          * screen states).
   27850          */
   27851         @UnsupportedAppUsage
   27852         int mDisplayState = Display.STATE_UNKNOWN;
   27853 
   27854         /**
   27855          * Scale factor used by the compatibility mode
   27856          */
   27857         @UnsupportedAppUsage
   27858         float mApplicationScale;
   27859 
   27860         /**
   27861          * Indicates whether the application is in compatibility mode
   27862          */
   27863         @UnsupportedAppUsage
   27864         boolean mScalingRequired;
   27865 
   27866         /**
   27867          * Left position of this view's window
   27868          */
   27869         int mWindowLeft;
   27870 
   27871         /**
   27872          * Top position of this view's window
   27873          */
   27874         int mWindowTop;
   27875 
   27876         /**
   27877          * Indicates whether views need to use 32-bit drawing caches
   27878          */
   27879         boolean mUse32BitDrawingCache;
   27880 
   27881         /**
   27882          * For windows that are full-screen but using insets to layout inside
   27883          * of the screen areas, these are the current insets to appear inside
   27884          * the overscan area of the display.
   27885          */
   27886         final Rect mOverscanInsets = new Rect();
   27887 
   27888         /**
   27889          * For windows that are full-screen but using insets to layout inside
   27890          * of the screen decorations, these are the current insets for the
   27891          * content of the window.
   27892          */
   27893         @UnsupportedAppUsage
   27894         final Rect mContentInsets = new Rect();
   27895 
   27896         /**
   27897          * For windows that are full-screen but using insets to layout inside
   27898          * of the screen decorations, these are the current insets for the
   27899          * actual visible parts of the window.
   27900          */
   27901         @UnsupportedAppUsage
   27902         final Rect mVisibleInsets = new Rect();
   27903 
   27904         /**
   27905          * For windows that are full-screen but using insets to layout inside
   27906          * of the screen decorations, these are the current insets for the
   27907          * stable system windows.
   27908          */
   27909         @UnsupportedAppUsage
   27910         final Rect mStableInsets = new Rect();
   27911 
   27912         final DisplayCutout.ParcelableWrapper mDisplayCutout =
   27913                 new DisplayCutout.ParcelableWrapper(DisplayCutout.NO_CUTOUT);
   27914 
   27915         /**
   27916          * For windows that include areas that are not covered by real surface these are the outsets
   27917          * for real surface.
   27918          */
   27919         final Rect mOutsets = new Rect();
   27920 
   27921         /**
   27922          * In multi-window we force show the system bars. Because we don't want that the surface
   27923          * size changes in this mode, we instead have a flag whether the system bars sizes should
   27924          * always be consumed, so the app is treated like there are no virtual system bars at all.
   27925          */
   27926         boolean mAlwaysConsumeSystemBars;
   27927 
   27928         /**
   27929          * The internal insets given by this window.  This value is
   27930          * supplied by the client (through
   27931          * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
   27932          * be given to the window manager when changed to be used in laying
   27933          * out windows behind it.
   27934          */
   27935         @UnsupportedAppUsage
   27936         final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
   27937                 = new ViewTreeObserver.InternalInsetsInfo();
   27938 
   27939         /**
   27940          * Set to true when mGivenInternalInsets is non-empty.
   27941          */
   27942         boolean mHasNonEmptyGivenInternalInsets;
   27943 
   27944         /**
   27945          * All views in the window's hierarchy that serve as scroll containers,
   27946          * used to determine if the window can be resized or must be panned
   27947          * to adjust for a soft input area.
   27948          */
   27949         @UnsupportedAppUsage
   27950         final ArrayList<View> mScrollContainers = new ArrayList<View>();
   27951 
   27952         @UnsupportedAppUsage
   27953         final KeyEvent.DispatcherState mKeyDispatchState
   27954                 = new KeyEvent.DispatcherState();
   27955 
   27956         /**
   27957          * Indicates whether the view's window currently has the focus.
   27958          */
   27959         @UnsupportedAppUsage
   27960         boolean mHasWindowFocus;
   27961 
   27962         /**
   27963          * The current visibility of the window.
   27964          */
   27965         int mWindowVisibility;
   27966 
   27967         /**
   27968          * Indicates the time at which drawing started to occur.
   27969          */
   27970         @UnsupportedAppUsage
   27971         long mDrawingTime;
   27972 
   27973         /**
   27974          * Indicates whether the view's window is currently in touch mode.
   27975          */
   27976         @UnsupportedAppUsage
   27977         boolean mInTouchMode;
   27978 
   27979         /**
   27980          * Indicates whether the view has requested unbuffered input dispatching for the current
   27981          * event stream.
   27982          */
   27983         boolean mUnbufferedDispatchRequested;
   27984 
   27985         /**
   27986          * Indicates that ViewAncestor should trigger a global layout change
   27987          * the next time it performs a traversal
   27988          */
   27989         @UnsupportedAppUsage
   27990         boolean mRecomputeGlobalAttributes;
   27991 
   27992         /**
   27993          * Always report new attributes at next traversal.
   27994          */
   27995         boolean mForceReportNewAttributes;
   27996 
   27997         /**
   27998          * Set during a traveral if any views want to keep the screen on.
   27999          */
   28000         @UnsupportedAppUsage
   28001         boolean mKeepScreenOn;
   28002 
   28003         /**
   28004          * Set during a traveral if the light center needs to be updated.
   28005          */
   28006         boolean mNeedsUpdateLightCenter;
   28007 
   28008         /**
   28009          * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
   28010          */
   28011         int mSystemUiVisibility;
   28012 
   28013         /**
   28014          * Hack to force certain system UI visibility flags to be cleared.
   28015          */
   28016         int mDisabledSystemUiVisibility;
   28017 
   28018         /**
   28019          * Last global system UI visibility reported by the window manager.
   28020          */
   28021         int mGlobalSystemUiVisibility = -1;
   28022 
   28023         /**
   28024          * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
   28025          * attached.
   28026          */
   28027         boolean mHasSystemUiListeners;
   28028 
   28029         /**
   28030          * Set if the window has requested to extend into the overscan region
   28031          * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
   28032          */
   28033         boolean mOverscanRequested;
   28034 
   28035         /**
   28036          * Set if the visibility of any views has changed.
   28037          */
   28038         @UnsupportedAppUsage
   28039         boolean mViewVisibilityChanged;
   28040 
   28041         /**
   28042          * Set to true if a view has been scrolled.
   28043          */
   28044         @UnsupportedAppUsage
   28045         boolean mViewScrollChanged;
   28046 
   28047         /**
   28048          * Set to true if a pointer event is currently being handled.
   28049          */
   28050         boolean mHandlingPointerEvent;
   28051 
   28052         /**
   28053          * Global to the view hierarchy used as a temporary for dealing with
   28054          * x/y points in the transparent region computations.
   28055          */
   28056         final int[] mTransparentLocation = new int[2];
   28057 
   28058         /**
   28059          * Global to the view hierarchy used as a temporary for dealing with
   28060          * x/y points in the ViewGroup.invalidateChild implementation.
   28061          */
   28062         final int[] mInvalidateChildLocation = new int[2];
   28063 
   28064         /**
   28065          * Global to the view hierarchy used as a temporary for dealing with
   28066          * computing absolute on-screen location.
   28067          */
   28068         final int[] mTmpLocation = new int[2];
   28069 
   28070         /**
   28071          * Global to the view hierarchy used as a temporary for dealing with
   28072          * x/y location when view is transformed.
   28073          */
   28074         final float[] mTmpTransformLocation = new float[2];
   28075 
   28076         /**
   28077          * The view tree observer used to dispatch global events like
   28078          * layout, pre-draw, touch mode change, etc.
   28079          */
   28080         @UnsupportedAppUsage
   28081         final ViewTreeObserver mTreeObserver;
   28082 
   28083         /**
   28084          * A Canvas used by the view hierarchy to perform bitmap caching.
   28085          */
   28086         Canvas mCanvas;
   28087 
   28088         /**
   28089          * The view root impl.
   28090          */
   28091         final ViewRootImpl mViewRootImpl;
   28092 
   28093         /**
   28094          * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
   28095          * handler can be used to pump events in the UI events queue.
   28096          */
   28097         @UnsupportedAppUsage
   28098         final Handler mHandler;
   28099 
   28100         /**
   28101          * Temporary for use in computing invalidate rectangles while
   28102          * calling up the hierarchy.
   28103          */
   28104         final Rect mTmpInvalRect = new Rect();
   28105 
   28106         /**
   28107          * Temporary for use in computing hit areas with transformed views
   28108          */
   28109         final RectF mTmpTransformRect = new RectF();
   28110 
   28111         /**
   28112          * Temporary for use in computing hit areas with transformed views
   28113          */
   28114         final RectF mTmpTransformRect1 = new RectF();
   28115 
   28116         /**
   28117          * Temporary list of rectanges.
   28118          */
   28119         final List<RectF> mTmpRectList = new ArrayList<>();
   28120 
   28121         /**
   28122          * Temporary for use in transforming invalidation rect
   28123          */
   28124         final Matrix mTmpMatrix = new Matrix();
   28125 
   28126         /**
   28127          * Temporary for use in transforming invalidation rect
   28128          */
   28129         final Transformation mTmpTransformation = new Transformation();
   28130 
   28131         /**
   28132          * Temporary for use in querying outlines from OutlineProviders
   28133          */
   28134         final Outline mTmpOutline = new Outline();
   28135 
   28136         /**
   28137          * Temporary list for use in collecting focusable descendents of a view.
   28138          */
   28139         final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
   28140 
   28141         /**
   28142          * The id of the window for accessibility purposes.
   28143          */
   28144         int mAccessibilityWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
   28145 
   28146         /**
   28147          * Flags related to accessibility processing.
   28148          *
   28149          * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
   28150          * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
   28151          */
   28152         int mAccessibilityFetchFlags;
   28153 
   28154         /**
   28155          * The drawable for highlighting accessibility focus.
   28156          */
   28157         Drawable mAccessibilityFocusDrawable;
   28158 
   28159         /**
   28160          * The drawable for highlighting autofilled views.
   28161          *
   28162          * @see #isAutofilled()
   28163          */
   28164         Drawable mAutofilledDrawable;
   28165 
   28166         /**
   28167          * Show where the margins, bounds and layout bounds are for each view.
   28168          */
   28169         boolean mDebugLayout = DisplayProperties.debug_layout().orElse(false);
   28170 
   28171         /**
   28172          * Point used to compute visible regions.
   28173          */
   28174         final Point mPoint = new Point();
   28175 
   28176         /**
   28177          * Used to track which View originated a requestLayout() call, used when
   28178          * requestLayout() is called during layout.
   28179          */
   28180         View mViewRequestingLayout;
   28181 
   28182         /**
   28183          * Used to track the identity of the current drag operation.
   28184          */
   28185         IBinder mDragToken;
   28186 
   28187         /**
   28188          * The drag shadow surface for the current drag operation.
   28189          */
   28190         public Surface mDragSurface;
   28191 
   28192 
   28193         /**
   28194          * The view that currently has a tooltip displayed.
   28195          */
   28196         View mTooltipHost;
   28197 
   28198         /**
   28199          * Creates a new set of attachment information with the specified
   28200          * events handler and thread.
   28201          *
   28202          * @param handler the events handler the view must use
   28203          */
   28204         AttachInfo(IWindowSession session, IWindow window, Display display,
   28205                 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer,
   28206                 Context context) {
   28207             mSession = session;
   28208             mWindow = window;
   28209             mWindowToken = window.asBinder();
   28210             mDisplay = display;
   28211             mViewRootImpl = viewRootImpl;
   28212             mHandler = handler;
   28213             mRootCallbacks = effectPlayer;
   28214             mTreeObserver = new ViewTreeObserver(context);
   28215         }
   28216     }
   28217 
   28218     /**
   28219      * <p>ScrollabilityCache holds various fields used by a View when scrolling
   28220      * is supported. This avoids keeping too many unused fields in most
   28221      * instances of View.</p>
   28222      */
   28223     private static class ScrollabilityCache implements Runnable {
   28224 
   28225         /**
   28226          * Scrollbars are not visible
   28227          */
   28228         public static final int OFF = 0;
   28229 
   28230         /**
   28231          * Scrollbars are visible
   28232          */
   28233         public static final int ON = 1;
   28234 
   28235         /**
   28236          * Scrollbars are fading away
   28237          */
   28238         public static final int FADING = 2;
   28239 
   28240         public boolean fadeScrollBars;
   28241 
   28242         public int fadingEdgeLength;
   28243         public int scrollBarDefaultDelayBeforeFade;
   28244         public int scrollBarFadeDuration;
   28245 
   28246         public int scrollBarSize;
   28247         public int scrollBarMinTouchTarget;
   28248         @UnsupportedAppUsage
   28249         public ScrollBarDrawable scrollBar;
   28250         public float[] interpolatorValues;
   28251         @UnsupportedAppUsage
   28252         public View host;
   28253 
   28254         public final Paint paint;
   28255         public final Matrix matrix;
   28256         public Shader shader;
   28257 
   28258         public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
   28259 
   28260         private static final float[] OPAQUE = { 255 };
   28261         private static final float[] TRANSPARENT = { 0.0f };
   28262 
   28263         /**
   28264          * When fading should start. This time moves into the future every time
   28265          * a new scroll happens. Measured based on SystemClock.uptimeMillis()
   28266          */
   28267         public long fadeStartTime;
   28268 
   28269 
   28270         /**
   28271          * The current state of the scrollbars: ON, OFF, or FADING
   28272          */
   28273         @UnsupportedAppUsage
   28274         public int state = OFF;
   28275 
   28276         private int mLastColor;
   28277 
   28278         public final Rect mScrollBarBounds = new Rect();
   28279         public final Rect mScrollBarTouchBounds = new Rect();
   28280 
   28281         public static final int NOT_DRAGGING = 0;
   28282         public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
   28283         public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
   28284         public int mScrollBarDraggingState = NOT_DRAGGING;
   28285 
   28286         public float mScrollBarDraggingPos = 0;
   28287 
   28288         public ScrollabilityCache(ViewConfiguration configuration, View host) {
   28289             fadingEdgeLength = configuration.getScaledFadingEdgeLength();
   28290             scrollBarSize = configuration.getScaledScrollBarSize();
   28291             scrollBarMinTouchTarget = configuration.getScaledMinScrollbarTouchTarget();
   28292             scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
   28293             scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
   28294 
   28295             paint = new Paint();
   28296             matrix = new Matrix();
   28297             // use use a height of 1, and then wack the matrix each time we
   28298             // actually use it.
   28299             shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
   28300             paint.setShader(shader);
   28301             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
   28302 
   28303             this.host = host;
   28304         }
   28305 
   28306         public void setFadeColor(int color) {
   28307             if (color != mLastColor) {
   28308                 mLastColor = color;
   28309 
   28310                 if (color != 0) {
   28311                     shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
   28312                             color & 0x00FFFFFF, Shader.TileMode.CLAMP);
   28313                     paint.setShader(shader);
   28314                     // Restore the default transfer mode (src_over)
   28315                     paint.setXfermode(null);
   28316                 } else {
   28317                     shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
   28318                     paint.setShader(shader);
   28319                     paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
   28320                 }
   28321             }
   28322         }
   28323 
   28324         public void run() {
   28325             long now = AnimationUtils.currentAnimationTimeMillis();
   28326             if (now >= fadeStartTime) {
   28327 
   28328                 // the animation fades the scrollbars out by changing
   28329                 // the opacity (alpha) from fully opaque to fully
   28330                 // transparent
   28331                 int nextFrame = (int) now;
   28332                 int framesCount = 0;
   28333 
   28334                 Interpolator interpolator = scrollBarInterpolator;
   28335 
   28336                 // Start opaque
   28337                 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
   28338 
   28339                 // End transparent
   28340                 nextFrame += scrollBarFadeDuration;
   28341                 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
   28342 
   28343                 state = FADING;
   28344 
   28345                 // Kick off the fade animation
   28346                 host.invalidate(true);
   28347             }
   28348         }
   28349     }
   28350 
   28351     /**
   28352      * Resuable callback for sending
   28353      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
   28354      */
   28355     private class SendViewScrolledAccessibilityEvent implements Runnable {
   28356         public volatile boolean mIsPending;
   28357         public int mDeltaX;
   28358         public int mDeltaY;
   28359 
   28360         public void post(int dx, int dy) {
   28361             mDeltaX += dx;
   28362             mDeltaY += dy;
   28363             if (!mIsPending) {
   28364                 mIsPending = true;
   28365                 postDelayed(this, ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
   28366             }
   28367         }
   28368 
   28369         @Override
   28370         public void run() {
   28371             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
   28372                 AccessibilityEvent event = AccessibilityEvent.obtain(
   28373                         AccessibilityEvent.TYPE_VIEW_SCROLLED);
   28374                 event.setScrollDeltaX(mDeltaX);
   28375                 event.setScrollDeltaY(mDeltaY);
   28376                 sendAccessibilityEventUnchecked(event);
   28377             }
   28378             reset();
   28379         }
   28380 
   28381         private void reset() {
   28382             mIsPending = false;
   28383             mDeltaX = 0;
   28384             mDeltaY = 0;
   28385         }
   28386     }
   28387 
   28388     /**
   28389      * Remove the pending callback for sending a
   28390      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
   28391      */
   28392     @UnsupportedAppUsage
   28393     private void cancel(@Nullable SendViewScrolledAccessibilityEvent callback) {
   28394         if (callback == null || !callback.mIsPending) return;
   28395         removeCallbacks(callback);
   28396         callback.reset();
   28397     }
   28398 
   28399     /**
   28400      * <p>
   28401      * This class represents a delegate that can be registered in a {@link View}
   28402      * to enhance accessibility support via composition rather via inheritance.
   28403      * It is specifically targeted to widget developers that extend basic View
   28404      * classes i.e. classes in package android.view, that would like their
   28405      * applications to be backwards compatible.
   28406      * </p>
   28407      * <div class="special reference">
   28408      * <h3>Developer Guides</h3>
   28409      * <p>For more information about making applications accessible, read the
   28410      * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
   28411      * developer guide.</p>
   28412      * </div>
   28413      * <p>
   28414      * A scenario in which a developer would like to use an accessibility delegate
   28415      * is overriding a method introduced in a later API version than the minimal API
   28416      * version supported by the application. For example, the method
   28417      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
   28418      * in API version 4 when the accessibility APIs were first introduced. If a
   28419      * developer would like their application to run on API version 4 devices (assuming
   28420      * all other APIs used by the application are version 4 or lower) and take advantage
   28421      * of this method, instead of overriding the method which would break the application's
   28422      * backwards compatibility, they can override the corresponding method in this
   28423      * delegate and register the delegate in the target View if the API version of
   28424      * the system is high enough, i.e. the API version is the same as or higher than the API
   28425      * version that introduced
   28426      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
   28427      * </p>
   28428      * <p>
   28429      * Here is an example implementation:
   28430      * </p>
   28431      * <code><pre><p>
   28432      * if (Build.VERSION.SDK_INT >= 14) {
   28433      *     // If the API version is equal of higher than the version in
   28434      *     // which onInitializeAccessibilityNodeInfo was introduced we
   28435      *     // register a delegate with a customized implementation.
   28436      *     View view = findViewById(R.id.view_id);
   28437      *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
   28438      *         public void onInitializeAccessibilityNodeInfo(View host,
   28439      *                 AccessibilityNodeInfo info) {
   28440      *             // Let the default implementation populate the info.
   28441      *             super.onInitializeAccessibilityNodeInfo(host, info);
   28442      *             // Set some other information.
   28443      *             info.setEnabled(host.isEnabled());
   28444      *         }
   28445      *     });
   28446      * }
   28447      * </code></pre></p>
   28448      * <p>
   28449      * This delegate contains methods that correspond to the accessibility methods
   28450      * in View. If a delegate has been specified the implementation in View hands
   28451      * off handling to the corresponding method in this delegate. The default
   28452      * implementation the delegate methods behaves exactly as the corresponding
   28453      * method in View for the case of no accessibility delegate been set. Hence,
   28454      * to customize the behavior of a View method, clients can override only the
   28455      * corresponding delegate method without altering the behavior of the rest
   28456      * accessibility related methods of the host view.
   28457      * </p>
   28458      * <p>
   28459      * <strong>Note:</strong> On platform versions prior to
   28460      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
   28461      * views in the {@code android.widget.*} package are called <i>before</i>
   28462      * host methods. This prevents certain properties such as class name from
   28463      * being modified by overriding
   28464      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
   28465      * as any changes will be overwritten by the host class.
   28466      * <p>
   28467      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
   28468      * methods are called <i>after</i> host methods, which all properties to be
   28469      * modified without being overwritten by the host class.
   28470      */
   28471     public static class AccessibilityDelegate {
   28472 
   28473         /**
   28474          * Sends an accessibility event of the given type. If accessibility is not
   28475          * enabled this method has no effect.
   28476          * <p>
   28477          * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
   28478          *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
   28479          * been set.
   28480          * </p>
   28481          *
   28482          * @param host The View hosting the delegate.
   28483          * @param eventType The type of the event to send.
   28484          *
   28485          * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
   28486          */
   28487         public void sendAccessibilityEvent(View host, int eventType) {
   28488             host.sendAccessibilityEventInternal(eventType);
   28489         }
   28490 
   28491         /**
   28492          * Performs the specified accessibility action on the view. For
   28493          * possible accessibility actions look at {@link AccessibilityNodeInfo}.
   28494          * <p>
   28495          * The default implementation behaves as
   28496          * {@link View#performAccessibilityAction(int, Bundle)
   28497          *  View#performAccessibilityAction(int, Bundle)} for the case of
   28498          *  no accessibility delegate been set.
   28499          * </p>
   28500          *
   28501          * @param action The action to perform.
   28502          * @return Whether the action was performed.
   28503          *
   28504          * @see View#performAccessibilityAction(int, Bundle)
   28505          *      View#performAccessibilityAction(int, Bundle)
   28506          */
   28507         public boolean performAccessibilityAction(View host, int action, Bundle args) {
   28508             return host.performAccessibilityActionInternal(action, args);
   28509         }
   28510 
   28511         /**
   28512          * Sends an accessibility event. This method behaves exactly as
   28513          * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
   28514          * empty {@link AccessibilityEvent} and does not perform a check whether
   28515          * accessibility is enabled.
   28516          * <p>
   28517          * The default implementation behaves as
   28518          * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
   28519          *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
   28520          * the case of no accessibility delegate been set.
   28521          * </p>
   28522          *
   28523          * @param host The View hosting the delegate.
   28524          * @param event The event to send.
   28525          *
   28526          * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
   28527          *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
   28528          */
   28529         public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
   28530             host.sendAccessibilityEventUncheckedInternal(event);
   28531         }
   28532 
   28533         /**
   28534          * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
   28535          * to its children for adding their text content to the event.
   28536          * <p>
   28537          * The default implementation behaves as
   28538          * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   28539          *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
   28540          * the case of no accessibility delegate been set.
   28541          * </p>
   28542          *
   28543          * @param host The View hosting the delegate.
   28544          * @param event The event.
   28545          * @return True if the event population was completed.
   28546          *
   28547          * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   28548          *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   28549          */
   28550         public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
   28551             return host.dispatchPopulateAccessibilityEventInternal(event);
   28552         }
   28553 
   28554         /**
   28555          * Gives a chance to the host View to populate the accessibility event with its
   28556          * text content.
   28557          * <p>
   28558          * The default implementation behaves as
   28559          * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
   28560          *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
   28561          * the case of no accessibility delegate been set.
   28562          * </p>
   28563          *
   28564          * @param host The View hosting the delegate.
   28565          * @param event The accessibility event which to populate.
   28566          *
   28567          * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
   28568          *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
   28569          */
   28570         public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
   28571             host.onPopulateAccessibilityEventInternal(event);
   28572         }
   28573 
   28574         /**
   28575          * Initializes an {@link AccessibilityEvent} with information about the
   28576          * the host View which is the event source.
   28577          * <p>
   28578          * The default implementation behaves as
   28579          * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
   28580          *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
   28581          * the case of no accessibility delegate been set.
   28582          * </p>
   28583          *
   28584          * @param host The View hosting the delegate.
   28585          * @param event The event to initialize.
   28586          *
   28587          * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
   28588          *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
   28589          */
   28590         public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
   28591             host.onInitializeAccessibilityEventInternal(event);
   28592         }
   28593 
   28594         /**
   28595          * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
   28596          * <p>
   28597          * The default implementation behaves as
   28598          * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
   28599          *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
   28600          * the case of no accessibility delegate been set.
   28601          * </p>
   28602          *
   28603          * @param host The View hosting the delegate.
   28604          * @param info The instance to initialize.
   28605          *
   28606          * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
   28607          *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
   28608          */
   28609         public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
   28610             host.onInitializeAccessibilityNodeInfoInternal(info);
   28611         }
   28612 
   28613         /**
   28614          * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
   28615          * additional data.
   28616          * <p>
   28617          * This method only needs to be implemented if the View offers to provide additional data.
   28618          * </p>
   28619          * <p>
   28620          * The default implementation behaves as
   28621          * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, String, Bundle)
   28622          * for the case where no accessibility delegate is set.
   28623          * </p>
   28624          *
   28625          * @param host The View hosting the delegate. Never {@code null}.
   28626          * @param info The info to which to add the extra data. Never {@code null}.
   28627          * @param extraDataKey A key specifying the type of extra data to add to the info. The
   28628          *                     extra data should be added to the {@link Bundle} returned by
   28629          *                     the info's {@link AccessibilityNodeInfo#getExtras} method.  Never
   28630          *                     {@code null}.
   28631          * @param arguments A {@link Bundle} holding any arguments relevant for this request.
   28632          *                  May be {@code null} if the if the service provided no arguments.
   28633          *
   28634          * @see AccessibilityNodeInfo#setAvailableExtraData(List)
   28635          */
   28636         public void addExtraDataToAccessibilityNodeInfo(@NonNull View host,
   28637                 @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
   28638                 @Nullable Bundle arguments) {
   28639             host.addExtraDataToAccessibilityNodeInfo(info, extraDataKey, arguments);
   28640         }
   28641 
   28642         /**
   28643          * Called when a child of the host View has requested sending an
   28644          * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
   28645          * to augment the event.
   28646          * <p>
   28647          * The default implementation behaves as
   28648          * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
   28649          *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
   28650          * the case of no accessibility delegate been set.
   28651          * </p>
   28652          *
   28653          * @param host The View hosting the delegate.
   28654          * @param child The child which requests sending the event.
   28655          * @param event The event to be sent.
   28656          * @return True if the event should be sent
   28657          *
   28658          * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
   28659          *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
   28660          */
   28661         public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
   28662                 AccessibilityEvent event) {
   28663             return host.onRequestSendAccessibilityEventInternal(child, event);
   28664         }
   28665 
   28666         /**
   28667          * Gets the provider for managing a virtual view hierarchy rooted at this View
   28668          * and reported to {@link android.accessibilityservice.AccessibilityService}s
   28669          * that explore the window content.
   28670          * <p>
   28671          * The default implementation behaves as
   28672          * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
   28673          * the case of no accessibility delegate been set.
   28674          * </p>
   28675          *
   28676          * @return The provider.
   28677          *
   28678          * @see AccessibilityNodeProvider
   28679          */
   28680         public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
   28681             return null;
   28682         }
   28683 
   28684         /**
   28685          * Returns an {@link AccessibilityNodeInfo} representing the host view from the
   28686          * point of view of an {@link android.accessibilityservice.AccessibilityService}.
   28687          * This method is responsible for obtaining an accessibility node info from a
   28688          * pool of reusable instances and calling
   28689          * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
   28690          * view to initialize the former.
   28691          * <p>
   28692          * <strong>Note:</strong> The client is responsible for recycling the obtained
   28693          * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
   28694          * creation.
   28695          * </p>
   28696          * <p>
   28697          * The default implementation behaves as
   28698          * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
   28699          * the case of no accessibility delegate been set.
   28700          * </p>
   28701          * @return A populated {@link AccessibilityNodeInfo}.
   28702          *
   28703          * @see AccessibilityNodeInfo
   28704          *
   28705          * @hide
   28706          */
   28707         @UnsupportedAppUsage
   28708         public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
   28709             return host.createAccessibilityNodeInfoInternal();
   28710         }
   28711     }
   28712 
   28713     private static class MatchIdPredicate implements Predicate<View> {
   28714         public int mId;
   28715 
   28716         @Override
   28717         public boolean test(View view) {
   28718             return (view.mID == mId);
   28719         }
   28720     }
   28721 
   28722     private static class MatchLabelForPredicate implements Predicate<View> {
   28723         private int mLabeledId;
   28724 
   28725         @Override
   28726         public boolean test(View view) {
   28727             return (view.mLabelForId == mLabeledId);
   28728         }
   28729     }
   28730 
   28731     /**
   28732      * Dump all private flags in readable format, useful for documentation and
   28733      * sanity checking.
   28734      */
   28735     private static void dumpFlags() {
   28736         final HashMap<String, String> found = Maps.newHashMap();
   28737         try {
   28738             for (Field field : View.class.getDeclaredFields()) {
   28739                 final int modifiers = field.getModifiers();
   28740                 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
   28741                     if (field.getType().equals(int.class)) {
   28742                         final int value = field.getInt(null);
   28743                         dumpFlag(found, field.getName(), value);
   28744                     } else if (field.getType().equals(int[].class)) {
   28745                         final int[] values = (int[]) field.get(null);
   28746                         for (int i = 0; i < values.length; i++) {
   28747                             dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
   28748                         }
   28749                     }
   28750                 }
   28751             }
   28752         } catch (IllegalAccessException e) {
   28753             throw new RuntimeException(e);
   28754         }
   28755 
   28756         final ArrayList<String> keys = Lists.newArrayList();
   28757         keys.addAll(found.keySet());
   28758         Collections.sort(keys);
   28759         for (String key : keys) {
   28760             Log.d(VIEW_LOG_TAG, found.get(key));
   28761         }
   28762     }
   28763 
   28764     private static void dumpFlag(HashMap<String, String> found, String name, int value) {
   28765         // Sort flags by prefix, then by bits, always keeping unique keys
   28766         final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
   28767         final int prefix = name.indexOf('_');
   28768         final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
   28769         final String output = bits + " " + name;
   28770         found.put(key, output);
   28771     }
   28772 
   28773     /** {@hide} */
   28774     public void encode(@NonNull ViewHierarchyEncoder stream) {
   28775         stream.beginObject(this);
   28776         encodeProperties(stream);
   28777         stream.endObject();
   28778     }
   28779 
   28780     /** {@hide} */
   28781     @CallSuper
   28782     protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
   28783         Object resolveId = ViewDebug.resolveId(getContext(), mID);
   28784         if (resolveId instanceof String) {
   28785             stream.addProperty("id", (String) resolveId);
   28786         } else {
   28787             stream.addProperty("id", mID);
   28788         }
   28789 
   28790         stream.addProperty("misc:transformation.alpha",
   28791                 mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
   28792         stream.addProperty("misc:transitionName", getTransitionName());
   28793 
   28794         // layout
   28795         stream.addProperty("layout:left", mLeft);
   28796         stream.addProperty("layout:right", mRight);
   28797         stream.addProperty("layout:top", mTop);
   28798         stream.addProperty("layout:bottom", mBottom);
   28799         stream.addProperty("layout:width", getWidth());
   28800         stream.addProperty("layout:height", getHeight());
   28801         stream.addProperty("layout:layoutDirection", getLayoutDirection());
   28802         stream.addProperty("layout:layoutRtl", isLayoutRtl());
   28803         stream.addProperty("layout:hasTransientState", hasTransientState());
   28804         stream.addProperty("layout:baseline", getBaseline());
   28805 
   28806         // layout params
   28807         ViewGroup.LayoutParams layoutParams = getLayoutParams();
   28808         if (layoutParams != null) {
   28809             stream.addPropertyKey("layoutParams");
   28810             layoutParams.encode(stream);
   28811         }
   28812 
   28813         // scrolling
   28814         stream.addProperty("scrolling:scrollX", mScrollX);
   28815         stream.addProperty("scrolling:scrollY", mScrollY);
   28816 
   28817         // padding
   28818         stream.addProperty("padding:paddingLeft", mPaddingLeft);
   28819         stream.addProperty("padding:paddingRight", mPaddingRight);
   28820         stream.addProperty("padding:paddingTop", mPaddingTop);
   28821         stream.addProperty("padding:paddingBottom", mPaddingBottom);
   28822         stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
   28823         stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
   28824         stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
   28825         stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
   28826         stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
   28827 
   28828         // measurement
   28829         stream.addProperty("measurement:minHeight", mMinHeight);
   28830         stream.addProperty("measurement:minWidth", mMinWidth);
   28831         stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
   28832         stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
   28833 
   28834         // drawing
   28835         stream.addProperty("drawing:elevation", getElevation());
   28836         stream.addProperty("drawing:translationX", getTranslationX());
   28837         stream.addProperty("drawing:translationY", getTranslationY());
   28838         stream.addProperty("drawing:translationZ", getTranslationZ());
   28839         stream.addProperty("drawing:rotation", getRotation());
   28840         stream.addProperty("drawing:rotationX", getRotationX());
   28841         stream.addProperty("drawing:rotationY", getRotationY());
   28842         stream.addProperty("drawing:scaleX", getScaleX());
   28843         stream.addProperty("drawing:scaleY", getScaleY());
   28844         stream.addProperty("drawing:pivotX", getPivotX());
   28845         stream.addProperty("drawing:pivotY", getPivotY());
   28846         stream.addProperty("drawing:clipBounds",
   28847                 mClipBounds == null ? null : mClipBounds.toString());
   28848         stream.addProperty("drawing:opaque", isOpaque());
   28849         stream.addProperty("drawing:alpha", getAlpha());
   28850         stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
   28851         stream.addProperty("drawing:shadow", hasShadow());
   28852         stream.addProperty("drawing:solidColor", getSolidColor());
   28853         stream.addProperty("drawing:layerType", mLayerType);
   28854         stream.addProperty("drawing:willNotDraw", willNotDraw());
   28855         stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
   28856         stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
   28857         stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
   28858         stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
   28859         stream.addProperty("drawing:outlineAmbientShadowColor", getOutlineAmbientShadowColor());
   28860         stream.addProperty("drawing:outlineSpotShadowColor", getOutlineSpotShadowColor());
   28861 
   28862         // focus
   28863         stream.addProperty("focus:hasFocus", hasFocus());
   28864         stream.addProperty("focus:isFocused", isFocused());
   28865         stream.addProperty("focus:focusable", getFocusable());
   28866         stream.addProperty("focus:isFocusable", isFocusable());
   28867         stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
   28868 
   28869         stream.addProperty("misc:clickable", isClickable());
   28870         stream.addProperty("misc:pressed", isPressed());
   28871         stream.addProperty("misc:selected", isSelected());
   28872         stream.addProperty("misc:touchMode", isInTouchMode());
   28873         stream.addProperty("misc:hovered", isHovered());
   28874         stream.addProperty("misc:activated", isActivated());
   28875 
   28876         stream.addProperty("misc:visibility", getVisibility());
   28877         stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
   28878         stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
   28879 
   28880         stream.addProperty("misc:enabled", isEnabled());
   28881         stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
   28882         stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
   28883 
   28884         // theme attributes
   28885         Resources.Theme theme = getContext().getTheme();
   28886         if (theme != null) {
   28887             stream.addPropertyKey("theme");
   28888             theme.encode(stream);
   28889         }
   28890 
   28891         // view attribute information
   28892         int n = mAttributes != null ? mAttributes.length : 0;
   28893         stream.addProperty("meta:__attrCount__", n/2);
   28894         for (int i = 0; i < n; i += 2) {
   28895             stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
   28896         }
   28897 
   28898         stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
   28899 
   28900         // text
   28901         stream.addProperty("text:textDirection", getTextDirection());
   28902         stream.addProperty("text:textAlignment", getTextAlignment());
   28903 
   28904         // accessibility
   28905         CharSequence contentDescription = getContentDescription();
   28906         stream.addProperty("accessibility:contentDescription",
   28907                 contentDescription == null ? "" : contentDescription.toString());
   28908         stream.addProperty("accessibility:labelFor", getLabelFor());
   28909         stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
   28910     }
   28911 
   28912     /**
   28913      * Determine if this view is rendered on a round wearable device and is the main view
   28914      * on the screen.
   28915      */
   28916     boolean shouldDrawRoundScrollbar() {
   28917         if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
   28918             return false;
   28919         }
   28920 
   28921         final View rootView = getRootView();
   28922         final WindowInsets insets = getRootWindowInsets();
   28923 
   28924         int height = getHeight();
   28925         int width = getWidth();
   28926         int displayHeight = rootView.getHeight();
   28927         int displayWidth = rootView.getWidth();
   28928 
   28929         if (height != displayHeight || width != displayWidth) {
   28930             return false;
   28931         }
   28932 
   28933         getLocationInWindow(mAttachInfo.mTmpLocation);
   28934         return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
   28935                 && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
   28936     }
   28937 
   28938     /**
   28939      * Sets the tooltip text which will be displayed in a small popup next to the view.
   28940      * <p>
   28941      * The tooltip will be displayed:
   28942      * <ul>
   28943      * <li>On long click, unless it is handled otherwise (by OnLongClickListener or a context
   28944      * menu). </li>
   28945      * <li>On hover, after a brief delay since the pointer has stopped moving </li>
   28946      * </ul>
   28947      * <p>
   28948      * <strong>Note:</strong> Do not override this method, as it will have no
   28949      * effect on the text displayed in the tooltip.
   28950      *
   28951      * @param tooltipText the tooltip text, or null if no tooltip is required
   28952      * @see #getTooltipText()
   28953      * @attr ref android.R.styleable#View_tooltipText
   28954      */
   28955     public void setTooltipText(@Nullable CharSequence tooltipText) {
   28956         if (TextUtils.isEmpty(tooltipText)) {
   28957             setFlags(0, TOOLTIP);
   28958             hideTooltip();
   28959             mTooltipInfo = null;
   28960         } else {
   28961             setFlags(TOOLTIP, TOOLTIP);
   28962             if (mTooltipInfo == null) {
   28963                 mTooltipInfo = new TooltipInfo();
   28964                 mTooltipInfo.mShowTooltipRunnable = this::showHoverTooltip;
   28965                 mTooltipInfo.mHideTooltipRunnable = this::hideTooltip;
   28966                 mTooltipInfo.mHoverSlop = ViewConfiguration.get(mContext).getScaledHoverSlop();
   28967                 mTooltipInfo.clearAnchorPos();
   28968             }
   28969             mTooltipInfo.mTooltipText = tooltipText;
   28970         }
   28971     }
   28972 
   28973     /**
   28974      * @hide Binary compatibility stub. To be removed when we finalize O APIs.
   28975      */
   28976     @UnsupportedAppUsage
   28977     public void setTooltip(@Nullable CharSequence tooltipText) {
   28978         setTooltipText(tooltipText);
   28979     }
   28980 
   28981     /**
   28982      * Returns the view's tooltip text.
   28983      *
   28984      * <strong>Note:</strong> Do not override this method, as it will have no
   28985      * effect on the text displayed in the tooltip. You must call
   28986      * {@link #setTooltipText(CharSequence)} to modify the tooltip text.
   28987      *
   28988      * @return the tooltip text
   28989      * @see #setTooltipText(CharSequence)
   28990      * @attr ref android.R.styleable#View_tooltipText
   28991      */
   28992     @InspectableProperty
   28993     @Nullable
   28994     public CharSequence getTooltipText() {
   28995         return mTooltipInfo != null ? mTooltipInfo.mTooltipText : null;
   28996     }
   28997 
   28998     /**
   28999      * @hide Binary compatibility stub. To be removed when we finalize O APIs.
   29000      */
   29001     @Nullable
   29002     public CharSequence getTooltip() {
   29003         return getTooltipText();
   29004     }
   29005 
   29006     private boolean showTooltip(int x, int y, boolean fromLongClick) {
   29007         if (mAttachInfo == null || mTooltipInfo == null) {
   29008             return false;
   29009         }
   29010         if (fromLongClick && (mViewFlags & ENABLED_MASK) != ENABLED) {
   29011             return false;
   29012         }
   29013         if (TextUtils.isEmpty(mTooltipInfo.mTooltipText)) {
   29014             return false;
   29015         }
   29016         hideTooltip();
   29017         mTooltipInfo.mTooltipFromLongClick = fromLongClick;
   29018         mTooltipInfo.mTooltipPopup = new TooltipPopup(getContext());
   29019         final boolean fromTouch = (mPrivateFlags3 & PFLAG3_FINGER_DOWN) == PFLAG3_FINGER_DOWN;
   29020         mTooltipInfo.mTooltipPopup.show(this, x, y, fromTouch, mTooltipInfo.mTooltipText);
   29021         mAttachInfo.mTooltipHost = this;
   29022         // The available accessibility actions have changed
   29023         notifyViewAccessibilityStateChangedIfNeeded(CONTENT_CHANGE_TYPE_UNDEFINED);
   29024         return true;
   29025     }
   29026 
   29027     @UnsupportedAppUsage
   29028     void hideTooltip() {
   29029         if (mTooltipInfo == null) {
   29030             return;
   29031         }
   29032         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
   29033         if (mTooltipInfo.mTooltipPopup == null) {
   29034             return;
   29035         }
   29036         mTooltipInfo.mTooltipPopup.hide();
   29037         mTooltipInfo.mTooltipPopup = null;
   29038         mTooltipInfo.mTooltipFromLongClick = false;
   29039         mTooltipInfo.clearAnchorPos();
   29040         if (mAttachInfo != null) {
   29041             mAttachInfo.mTooltipHost = null;
   29042         }
   29043         // The available accessibility actions have changed
   29044         notifyViewAccessibilityStateChangedIfNeeded(CONTENT_CHANGE_TYPE_UNDEFINED);
   29045     }
   29046 
   29047     private boolean showLongClickTooltip(int x, int y) {
   29048         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
   29049         removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
   29050         return showTooltip(x, y, true);
   29051     }
   29052 
   29053     private boolean showHoverTooltip() {
   29054         return showTooltip(mTooltipInfo.mAnchorX, mTooltipInfo.mAnchorY, false);
   29055     }
   29056 
   29057     boolean dispatchTooltipHoverEvent(MotionEvent event) {
   29058         if (mTooltipInfo == null) {
   29059             return false;
   29060         }
   29061         switch(event.getAction()) {
   29062             case MotionEvent.ACTION_HOVER_MOVE:
   29063                 if ((mViewFlags & TOOLTIP) != TOOLTIP) {
   29064                     break;
   29065                 }
   29066                 if (!mTooltipInfo.mTooltipFromLongClick && mTooltipInfo.updateAnchorPos(event)) {
   29067                     if (mTooltipInfo.mTooltipPopup == null) {
   29068                         // Schedule showing the tooltip after a timeout.
   29069                         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
   29070                         postDelayed(mTooltipInfo.mShowTooltipRunnable,
   29071                                 ViewConfiguration.getHoverTooltipShowTimeout());
   29072                     }
   29073 
   29074                     // Hide hover-triggered tooltip after a period of inactivity.
   29075                     // Match the timeout used by NativeInputManager to hide the mouse pointer
   29076                     // (depends on SYSTEM_UI_FLAG_LOW_PROFILE being set).
   29077                     final int timeout;
   29078                     if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LOW_PROFILE)
   29079                             == SYSTEM_UI_FLAG_LOW_PROFILE) {
   29080                         timeout = ViewConfiguration.getHoverTooltipHideShortTimeout();
   29081                     } else {
   29082                         timeout = ViewConfiguration.getHoverTooltipHideTimeout();
   29083                     }
   29084                     removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
   29085                     postDelayed(mTooltipInfo.mHideTooltipRunnable, timeout);
   29086                 }
   29087                 return true;
   29088 
   29089             case MotionEvent.ACTION_HOVER_EXIT:
   29090                 mTooltipInfo.clearAnchorPos();
   29091                 if (!mTooltipInfo.mTooltipFromLongClick) {
   29092                     hideTooltip();
   29093                 }
   29094                 break;
   29095         }
   29096         return false;
   29097     }
   29098 
   29099     void handleTooltipKey(KeyEvent event) {
   29100         switch (event.getAction()) {
   29101             case KeyEvent.ACTION_DOWN:
   29102                 if (event.getRepeatCount() == 0) {
   29103                     hideTooltip();
   29104                 }
   29105                 break;
   29106 
   29107             case KeyEvent.ACTION_UP:
   29108                 handleTooltipUp();
   29109                 break;
   29110         }
   29111     }
   29112 
   29113     private void handleTooltipUp() {
   29114         if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
   29115             return;
   29116         }
   29117         removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
   29118         postDelayed(mTooltipInfo.mHideTooltipRunnable,
   29119                 ViewConfiguration.getLongPressTooltipHideTimeout());
   29120     }
   29121 
   29122     private int getFocusableAttribute(TypedArray attributes) {
   29123         TypedValue val = new TypedValue();
   29124         if (attributes.getValue(com.android.internal.R.styleable.View_focusable, val)) {
   29125             if (val.type == TypedValue.TYPE_INT_BOOLEAN) {
   29126                 return (val.data == 0 ? NOT_FOCUSABLE : FOCUSABLE);
   29127             } else {
   29128                 return val.data;
   29129             }
   29130         } else {
   29131             return FOCUSABLE_AUTO;
   29132         }
   29133     }
   29134 
   29135     /**
   29136      * @return The content view of the tooltip popup currently being shown, or null if the tooltip
   29137      * is not showing.
   29138      * @hide
   29139      */
   29140     @TestApi
   29141     public View getTooltipView() {
   29142         if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
   29143             return null;
   29144         }
   29145         return mTooltipInfo.mTooltipPopup.getContentView();
   29146     }
   29147 
   29148     /**
   29149      * @return {@code true} if the default focus highlight is enabled, {@code false} otherwies.
   29150      * @hide
   29151      */
   29152     @TestApi
   29153     public static boolean isDefaultFocusHighlightEnabled() {
   29154         return sUseDefaultFocusHighlight;
   29155     }
   29156 
   29157     /**
   29158      * Dispatch a previously unhandled {@link KeyEvent} to this view. Unlike normal key dispatch,
   29159      * this dispatches to ALL child views until it is consumed. The dispatch order is z-order
   29160      * (visually on-top views first).
   29161      *
   29162      * @param evt the previously unhandled {@link KeyEvent}.
   29163      * @return the {@link View} which consumed the event or {@code null} if not consumed.
   29164      */
   29165     View dispatchUnhandledKeyEvent(KeyEvent evt) {
   29166         if (onUnhandledKeyEvent(evt)) {
   29167             return this;
   29168         }
   29169         return null;
   29170     }
   29171 
   29172     /**
   29173      * Allows this view to handle {@link KeyEvent}s which weren't handled by normal dispatch. This
   29174      * occurs after the normal view hierarchy dispatch, but before the window callback. By default,
   29175      * this will dispatch into all the listeners registered via
   29176      * {@link #addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener)} in last-in-first-out
   29177      * order (most recently added will receive events first).
   29178      *
   29179      * @param event An unhandled event.
   29180      * @return {@code true} if the event was handled, {@code false} otherwise.
   29181      * @see #addOnUnhandledKeyEventListener
   29182      */
   29183     boolean onUnhandledKeyEvent(@NonNull KeyEvent event) {
   29184         if (mListenerInfo != null && mListenerInfo.mUnhandledKeyListeners != null) {
   29185             for (int i = mListenerInfo.mUnhandledKeyListeners.size() - 1; i >= 0; --i) {
   29186                 if (mListenerInfo.mUnhandledKeyListeners.get(i).onUnhandledKeyEvent(this, event)) {
   29187                     return true;
   29188                 }
   29189             }
   29190         }
   29191         return false;
   29192     }
   29193 
   29194     boolean hasUnhandledKeyListener() {
   29195         return (mListenerInfo != null && mListenerInfo.mUnhandledKeyListeners != null
   29196                 && !mListenerInfo.mUnhandledKeyListeners.isEmpty());
   29197     }
   29198 
   29199     /**
   29200      * Adds a listener which will receive unhandled {@link KeyEvent}s. This must be called on the
   29201      * UI thread.
   29202      *
   29203      * @param listener a receiver of unhandled {@link KeyEvent}s.
   29204      * @see #removeOnUnhandledKeyEventListener
   29205      */
   29206     public void addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener) {
   29207         ArrayList<OnUnhandledKeyEventListener> listeners = getListenerInfo().mUnhandledKeyListeners;
   29208         if (listeners == null) {
   29209             listeners = new ArrayList<>();
   29210             getListenerInfo().mUnhandledKeyListeners = listeners;
   29211         }
   29212         listeners.add(listener);
   29213         if (listeners.size() == 1 && mParent instanceof ViewGroup) {
   29214             ((ViewGroup) mParent).incrementChildUnhandledKeyListeners();
   29215         }
   29216     }
   29217 
   29218     /**
   29219      * Removes a listener which will receive unhandled {@link KeyEvent}s. This must be called on the
   29220      * UI thread.
   29221      *
   29222      * @param listener a receiver of unhandled {@link KeyEvent}s.
   29223      * @see #addOnUnhandledKeyEventListener
   29224      */
   29225     public void removeOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener) {
   29226         if (mListenerInfo != null) {
   29227             if (mListenerInfo.mUnhandledKeyListeners != null
   29228                     && !mListenerInfo.mUnhandledKeyListeners.isEmpty()) {
   29229                 mListenerInfo.mUnhandledKeyListeners.remove(listener);
   29230                 if (mListenerInfo.mUnhandledKeyListeners.isEmpty()) {
   29231                     mListenerInfo.mUnhandledKeyListeners = null;
   29232                     if (mParent instanceof ViewGroup) {
   29233                         ((ViewGroup) mParent).decrementChildUnhandledKeyListeners();
   29234                     }
   29235                 }
   29236             }
   29237         }
   29238     }
   29239 }
   29240