Home | History | Annotate | Download | only in view
      1 /*
      2  * Copyright (C) 2006 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.view;
     18 
     19 import android.animation.AnimatorInflater;
     20 import android.animation.StateListAnimator;
     21 import android.annotation.CallSuper;
     22 import android.annotation.ColorInt;
     23 import android.annotation.DrawableRes;
     24 import android.annotation.FloatRange;
     25 import android.annotation.IdRes;
     26 import android.annotation.IntDef;
     27 import android.annotation.LayoutRes;
     28 import android.annotation.NonNull;
     29 import android.annotation.Nullable;
     30 import android.annotation.Size;
     31 import android.annotation.UiThread;
     32 import android.content.ClipData;
     33 import android.content.Context;
     34 import android.content.ContextWrapper;
     35 import android.content.Intent;
     36 import android.content.res.ColorStateList;
     37 import android.content.res.Configuration;
     38 import android.content.res.Resources;
     39 import android.content.res.TypedArray;
     40 import android.graphics.Bitmap;
     41 import android.graphics.Canvas;
     42 import android.graphics.Insets;
     43 import android.graphics.Interpolator;
     44 import android.graphics.LinearGradient;
     45 import android.graphics.Matrix;
     46 import android.graphics.Outline;
     47 import android.graphics.Paint;
     48 import android.graphics.PixelFormat;
     49 import android.graphics.Point;
     50 import android.graphics.PorterDuff;
     51 import android.graphics.PorterDuffXfermode;
     52 import android.graphics.Rect;
     53 import android.graphics.RectF;
     54 import android.graphics.Region;
     55 import android.graphics.Shader;
     56 import android.graphics.drawable.ColorDrawable;
     57 import android.graphics.drawable.Drawable;
     58 import android.hardware.display.DisplayManagerGlobal;
     59 import android.os.Build.VERSION_CODES;
     60 import android.os.Bundle;
     61 import android.os.Handler;
     62 import android.os.IBinder;
     63 import android.os.Parcel;
     64 import android.os.Parcelable;
     65 import android.os.RemoteException;
     66 import android.os.SystemClock;
     67 import android.os.SystemProperties;
     68 import android.os.Trace;
     69 import android.text.TextUtils;
     70 import android.util.AttributeSet;
     71 import android.util.FloatProperty;
     72 import android.util.LayoutDirection;
     73 import android.util.Log;
     74 import android.util.LongSparseLongArray;
     75 import android.util.Pools.SynchronizedPool;
     76 import android.util.Property;
     77 import android.util.SparseArray;
     78 import android.util.StateSet;
     79 import android.util.SuperNotCalledException;
     80 import android.util.TypedValue;
     81 import android.view.ContextMenu.ContextMenuInfo;
     82 import android.view.AccessibilityIterators.TextSegmentIterator;
     83 import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
     84 import android.view.AccessibilityIterators.WordTextSegmentIterator;
     85 import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
     86 import android.view.accessibility.AccessibilityEvent;
     87 import android.view.accessibility.AccessibilityEventSource;
     88 import android.view.accessibility.AccessibilityManager;
     89 import android.view.accessibility.AccessibilityNodeInfo;
     90 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
     91 import android.view.accessibility.AccessibilityNodeProvider;
     92 import android.view.animation.Animation;
     93 import android.view.animation.AnimationUtils;
     94 import android.view.animation.Transformation;
     95 import android.view.inputmethod.EditorInfo;
     96 import android.view.inputmethod.InputConnection;
     97 import android.view.inputmethod.InputMethodManager;
     98 import android.widget.Checkable;
     99 import android.widget.FrameLayout;
    100 import android.widget.ScrollBarDrawable;
    101 
    102 import static android.os.Build.VERSION_CODES.*;
    103 import static java.lang.Math.max;
    104 
    105 import com.android.internal.R;
    106 import com.android.internal.util.Predicate;
    107 import com.android.internal.view.menu.MenuBuilder;
    108 import com.google.android.collect.Lists;
    109 import com.google.android.collect.Maps;
    110 
    111 import java.lang.annotation.Retention;
    112 import java.lang.annotation.RetentionPolicy;
    113 import java.lang.ref.WeakReference;
    114 import java.lang.reflect.Field;
    115 import java.lang.reflect.InvocationTargetException;
    116 import java.lang.reflect.Method;
    117 import java.lang.reflect.Modifier;
    118 import java.util.ArrayList;
    119 import java.util.Arrays;
    120 import java.util.Collections;
    121 import java.util.HashMap;
    122 import java.util.List;
    123 import java.util.Locale;
    124 import java.util.Map;
    125 import java.util.concurrent.CopyOnWriteArrayList;
    126 import java.util.concurrent.atomic.AtomicInteger;
    127 
    128 /**
    129  * <p>
    130  * This class represents the basic building block for user interface components. A View
    131  * occupies a rectangular area on the screen and is responsible for drawing and
    132  * event handling. View is the base class for <em>widgets</em>, which are
    133  * used to create interactive UI components (buttons, text fields, etc.). The
    134  * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
    135  * are invisible containers that hold other Views (or other ViewGroups) and define
    136  * their layout properties.
    137  * </p>
    138  *
    139  * <div class="special reference">
    140  * <h3>Developer Guides</h3>
    141  * <p>For information about using this class to develop your application's user interface,
    142  * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
    143  * </div>
    144  *
    145  * <a name="Using"></a>
    146  * <h3>Using Views</h3>
    147  * <p>
    148  * All of the views in a window are arranged in a single tree. You can add views
    149  * either from code or by specifying a tree of views in one or more XML layout
    150  * files. There are many specialized subclasses of views that act as controls or
    151  * are capable of displaying text, images, or other content.
    152  * </p>
    153  * <p>
    154  * Once you have created a tree of views, there are typically a few types of
    155  * common operations you may wish to perform:
    156  * <ul>
    157  * <li><strong>Set properties:</strong> for example setting the text of a
    158  * {@link android.widget.TextView}. The available properties and the methods
    159  * that set them will vary among the different subclasses of views. Note that
    160  * properties that are known at build time can be set in the XML layout
    161  * files.</li>
    162  * <li><strong>Set focus:</strong> The framework will handled moving focus in
    163  * response to user input. To force focus to a specific view, call
    164  * {@link #requestFocus}.</li>
    165  * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
    166  * that will be notified when something interesting happens to the view. For
    167  * example, all views will let you set a listener to be notified when the view
    168  * gains or loses focus. You can register such a listener using
    169  * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
    170  * Other view subclasses offer more specialized listeners. For example, a Button
    171  * exposes a listener to notify clients when the button is clicked.</li>
    172  * <li><strong>Set visibility:</strong> You can hide or show views using
    173  * {@link #setVisibility(int)}.</li>
    174  * </ul>
    175  * </p>
    176  * <p><em>
    177  * Note: The Android framework is responsible for measuring, laying out and
    178  * drawing views. You should not call methods that perform these actions on
    179  * views yourself unless you are actually implementing a
    180  * {@link android.view.ViewGroup}.
    181  * </em></p>
    182  *
    183  * <a name="Lifecycle"></a>
    184  * <h3>Implementing a Custom View</h3>
    185  *
    186  * <p>
    187  * To implement a custom view, you will usually begin by providing overrides for
    188  * some of the standard methods that the framework calls on all views. You do
    189  * not need to override all of these methods. In fact, you can start by just
    190  * overriding {@link #onDraw(android.graphics.Canvas)}.
    191  * <table border="2" width="85%" align="center" cellpadding="5">
    192  *     <thead>
    193  *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
    194  *     </thead>
    195  *
    196  *     <tbody>
    197  *     <tr>
    198  *         <td rowspan="2">Creation</td>
    199  *         <td>Constructors</td>
    200  *         <td>There is a form of the constructor that are called when the view
    201  *         is created from code and a form that is called when the view is
    202  *         inflated from a layout file. The second form should parse and apply
    203  *         any attributes defined in the layout file.
    204  *         </td>
    205  *     </tr>
    206  *     <tr>
    207  *         <td><code>{@link #onFinishInflate()}</code></td>
    208  *         <td>Called after a view and all of its children has been inflated
    209  *         from XML.</td>
    210  *     </tr>
    211  *
    212  *     <tr>
    213  *         <td rowspan="3">Layout</td>
    214  *         <td><code>{@link #onMeasure(int, int)}</code></td>
    215  *         <td>Called to determine the size requirements for this view and all
    216  *         of its children.
    217  *         </td>
    218  *     </tr>
    219  *     <tr>
    220  *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
    221  *         <td>Called when this view should assign a size and position to all
    222  *         of its children.
    223  *         </td>
    224  *     </tr>
    225  *     <tr>
    226  *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
    227  *         <td>Called when the size of this view has changed.
    228  *         </td>
    229  *     </tr>
    230  *
    231  *     <tr>
    232  *         <td>Drawing</td>
    233  *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
    234  *         <td>Called when the view should render its content.
    235  *         </td>
    236  *     </tr>
    237  *
    238  *     <tr>
    239  *         <td rowspan="4">Event processing</td>
    240  *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
    241  *         <td>Called when a new hardware key event occurs.
    242  *         </td>
    243  *     </tr>
    244  *     <tr>
    245  *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
    246  *         <td>Called when a hardware key up event occurs.
    247  *         </td>
    248  *     </tr>
    249  *     <tr>
    250  *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
    251  *         <td>Called when a trackball motion event occurs.
    252  *         </td>
    253  *     </tr>
    254  *     <tr>
    255  *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
    256  *         <td>Called when a touch screen motion event occurs.
    257  *         </td>
    258  *     </tr>
    259  *
    260  *     <tr>
    261  *         <td rowspan="2">Focus</td>
    262  *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
    263  *         <td>Called when the view gains or loses focus.
    264  *         </td>
    265  *     </tr>
    266  *
    267  *     <tr>
    268  *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
    269  *         <td>Called when the window containing the view gains or loses focus.
    270  *         </td>
    271  *     </tr>
    272  *
    273  *     <tr>
    274  *         <td rowspan="3">Attaching</td>
    275  *         <td><code>{@link #onAttachedToWindow()}</code></td>
    276  *         <td>Called when the view is attached to a window.
    277  *         </td>
    278  *     </tr>
    279  *
    280  *     <tr>
    281  *         <td><code>{@link #onDetachedFromWindow}</code></td>
    282  *         <td>Called when the view is detached from its window.
    283  *         </td>
    284  *     </tr>
    285  *
    286  *     <tr>
    287  *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
    288  *         <td>Called when the visibility of the window containing the view
    289  *         has changed.
    290  *         </td>
    291  *     </tr>
    292  *     </tbody>
    293  *
    294  * </table>
    295  * </p>
    296  *
    297  * <a name="IDs"></a>
    298  * <h3>IDs</h3>
    299  * Views may have an integer id associated with them. These ids are typically
    300  * assigned in the layout XML files, and are used to find specific views within
    301  * the view tree. A common pattern is to:
    302  * <ul>
    303  * <li>Define a Button in the layout file and assign it a unique ID.
    304  * <pre>
    305  * &lt;Button
    306  *     android:id="@+id/my_button"
    307  *     android:layout_width="wrap_content"
    308  *     android:layout_height="wrap_content"
    309  *     android:text="@string/my_button_text"/&gt;
    310  * </pre></li>
    311  * <li>From the onCreate method of an Activity, find the Button
    312  * <pre class="prettyprint">
    313  *      Button myButton = (Button) findViewById(R.id.my_button);
    314  * </pre></li>
    315  * </ul>
    316  * <p>
    317  * View IDs need not be unique throughout the tree, but it is good practice to
    318  * ensure that they are at least unique within the part of the tree you are
    319  * searching.
    320  * </p>
    321  *
    322  * <a name="Position"></a>
    323  * <h3>Position</h3>
    324  * <p>
    325  * The geometry of a view is that of a rectangle. A view has a location,
    326  * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
    327  * two dimensions, expressed as a width and a height. The unit for location
    328  * and dimensions is the pixel.
    329  * </p>
    330  *
    331  * <p>
    332  * It is possible to retrieve the location of a view by invoking the methods
    333  * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
    334  * coordinate of the rectangle representing the view. The latter returns the
    335  * top, or Y, coordinate of the rectangle representing the view. These methods
    336  * both return the location of the view relative to its parent. For instance,
    337  * when getLeft() returns 20, that means the view is located 20 pixels to the
    338  * right of the left edge of its direct parent.
    339  * </p>
    340  *
    341  * <p>
    342  * In addition, several convenience methods are offered to avoid unnecessary
    343  * computations, namely {@link #getRight()} and {@link #getBottom()}.
    344  * These methods return the coordinates of the right and bottom edges of the
    345  * rectangle representing the view. For instance, calling {@link #getRight()}
    346  * is similar to the following computation: <code>getLeft() + getWidth()</code>
    347  * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
    348  * </p>
    349  *
    350  * <a name="SizePaddingMargins"></a>
    351  * <h3>Size, padding and margins</h3>
    352  * <p>
    353  * The size of a view is expressed with a width and a height. A view actually
    354  * possess two pairs of width and height values.
    355  * </p>
    356  *
    357  * <p>
    358  * The first pair is known as <em>measured width</em> and
    359  * <em>measured height</em>. These dimensions define how big a view wants to be
    360  * within its parent (see <a href="#Layout">Layout</a> for more details.) The
    361  * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
    362  * and {@link #getMeasuredHeight()}.
    363  * </p>
    364  *
    365  * <p>
    366  * The second pair is simply known as <em>width</em> and <em>height</em>, or
    367  * sometimes <em>drawing width</em> and <em>drawing height</em>. These
    368  * dimensions define the actual size of the view on screen, at drawing time and
    369  * after layout. These values may, but do not have to, be different from the
    370  * measured width and height. The width and height can be obtained by calling
    371  * {@link #getWidth()} and {@link #getHeight()}.
    372  * </p>
    373  *
    374  * <p>
    375  * To measure its dimensions, a view takes into account its padding. The padding
    376  * is expressed in pixels for the left, top, right and bottom parts of the view.
    377  * Padding can be used to offset the content of the view by a specific amount of
    378  * pixels. For instance, a left padding of 2 will push the view's content by
    379  * 2 pixels to the right of the left edge. Padding can be set using the
    380  * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
    381  * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
    382  * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
    383  * {@link #getPaddingEnd()}.
    384  * </p>
    385  *
    386  * <p>
    387  * Even though a view can define a padding, it does not provide any support for
    388  * margins. However, view groups provide such a support. Refer to
    389  * {@link android.view.ViewGroup} and
    390  * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
    391  * </p>
    392  *
    393  * <a name="Layout"></a>
    394  * <h3>Layout</h3>
    395  * <p>
    396  * Layout is a two pass process: a measure pass and a layout pass. The measuring
    397  * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
    398  * of the view tree. Each view pushes dimension specifications down the tree
    399  * during the recursion. At the end of the measure pass, every view has stored
    400  * its measurements. The second pass happens in
    401  * {@link #layout(int,int,int,int)} and is also top-down. During
    402  * this pass each parent is responsible for positioning all of its children
    403  * using the sizes computed in the measure pass.
    404  * </p>
    405  *
    406  * <p>
    407  * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
    408  * {@link #getMeasuredHeight()} values must be set, along with those for all of
    409  * that view's descendants. A view's measured width and measured height values
    410  * must respect the constraints imposed by the view's parents. This guarantees
    411  * that at the end of the measure pass, all parents accept all of their
    412  * children's measurements. A parent view may call measure() more than once on
    413  * its children. For example, the parent may measure each child once with
    414  * unspecified dimensions to find out how big they want to be, then call
    415  * measure() on them again with actual numbers if the sum of all the children's
    416  * unconstrained sizes is too big or too small.
    417  * </p>
    418  *
    419  * <p>
    420  * The measure pass uses two classes to communicate dimensions. The
    421  * {@link MeasureSpec} class is used by views to tell their parents how they
    422  * want to be measured and positioned. The base LayoutParams class just
    423  * describes how big the view wants to be for both width and height. For each
    424  * dimension, it can specify one of:
    425  * <ul>
    426  * <li> an exact number
    427  * <li>MATCH_PARENT, which means the view wants to be as big as its parent
    428  * (minus padding)
    429  * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
    430  * enclose its content (plus padding).
    431  * </ul>
    432  * There are subclasses of LayoutParams for different subclasses of ViewGroup.
    433  * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
    434  * an X and Y value.
    435  * </p>
    436  *
    437  * <p>
    438  * MeasureSpecs are used to push requirements down the tree from parent to
    439  * child. A MeasureSpec can be in one of three modes:
    440  * <ul>
    441  * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
    442  * of a child view. For example, a LinearLayout may call measure() on its child
    443  * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
    444  * tall the child view wants to be given a width of 240 pixels.
    445  * <li>EXACTLY: This is used by the parent to impose an exact size on the
    446  * child. The child must use this size, and guarantee that all of its
    447  * descendants will fit within this size.
    448  * <li>AT_MOST: This is used by the parent to impose a maximum size on the
    449  * child. The child must guarantee that it and all of its descendants will fit
    450  * within this size.
    451  * </ul>
    452  * </p>
    453  *
    454  * <p>
    455  * To initiate a layout, call {@link #requestLayout}. This method is typically
    456  * called by a view on itself when it believes that is can no longer fit within
    457  * its current bounds.
    458  * </p>
    459  *
    460  * <a name="Drawing"></a>
    461  * <h3>Drawing</h3>
    462  * <p>
    463  * Drawing is handled by walking the tree and recording the drawing commands of
    464  * any View that needs to update. After this, the drawing commands of the
    465  * entire tree are issued to screen, clipped to the newly damaged area.
    466  * </p>
    467  *
    468  * <p>
    469  * The tree is largely recorded and drawn in order, with parents drawn before
    470  * (i.e., behind) their children, with siblings drawn in the order they appear
    471  * in the tree. If you set a background drawable for a View, then the View will
    472  * draw it before calling back to its <code>onDraw()</code> method. The child
    473  * drawing order can be overridden with
    474  * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
    475  * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
    476  * </p>
    477  *
    478  * <p>
    479  * To force a view to draw, call {@link #invalidate()}.
    480  * </p>
    481  *
    482  * <a name="EventHandlingThreading"></a>
    483  * <h3>Event Handling and Threading</h3>
    484  * <p>
    485  * The basic cycle of a view is as follows:
    486  * <ol>
    487  * <li>An event comes in and is dispatched to the appropriate view. The view
    488  * handles the event and notifies any listeners.</li>
    489  * <li>If in the course of processing the event, the view's bounds may need
    490  * to be changed, the view will call {@link #requestLayout()}.</li>
    491  * <li>Similarly, if in the course of processing the event the view's appearance
    492  * may need to be changed, the view will call {@link #invalidate()}.</li>
    493  * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
    494  * the framework will take care of measuring, laying out, and drawing the tree
    495  * as appropriate.</li>
    496  * </ol>
    497  * </p>
    498  *
    499  * <p><em>Note: The entire view tree is single threaded. You must always be on
    500  * the UI thread when calling any method on any view.</em>
    501  * If you are doing work on other threads and want to update the state of a view
    502  * from that thread, you should use a {@link Handler}.
    503  * </p>
    504  *
    505  * <a name="FocusHandling"></a>
    506  * <h3>Focus Handling</h3>
    507  * <p>
    508  * The framework will handle routine focus movement in response to user input.
    509  * This includes changing the focus as views are removed or hidden, or as new
    510  * views become available. Views indicate their willingness to take focus
    511  * through the {@link #isFocusable} method. To change whether a view can take
    512  * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
    513  * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
    514  * and can change this via {@link #setFocusableInTouchMode(boolean)}.
    515  * </p>
    516  * <p>
    517  * Focus movement is based on an algorithm which finds the nearest neighbor in a
    518  * given direction. In rare cases, the default algorithm may not match the
    519  * intended behavior of the developer. In these situations, you can provide
    520  * explicit overrides by using these XML attributes in the layout file:
    521  * <pre>
    522  * nextFocusDown
    523  * nextFocusLeft
    524  * nextFocusRight
    525  * nextFocusUp
    526  * </pre>
    527  * </p>
    528  *
    529  *
    530  * <p>
    531  * To get a particular view to take focus, call {@link #requestFocus()}.
    532  * </p>
    533  *
    534  * <a name="TouchMode"></a>
    535  * <h3>Touch Mode</h3>
    536  * <p>
    537  * When a user is navigating a user interface via directional keys such as a D-pad, it is
    538  * necessary to give focus to actionable items such as buttons so the user can see
    539  * what will take input.  If the device has touch capabilities, however, and the user
    540  * begins interacting with the interface by touching it, it is no longer necessary to
    541  * always highlight, or give focus to, a particular view.  This motivates a mode
    542  * for interaction named 'touch mode'.
    543  * </p>
    544  * <p>
    545  * For a touch capable device, once the user touches the screen, the device
    546  * will enter touch mode.  From this point onward, only views for which
    547  * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
    548  * Other views that are touchable, like buttons, will not take focus when touched; they will
    549  * only fire the on click listeners.
    550  * </p>
    551  * <p>
    552  * Any time a user hits a directional key, such as a D-pad direction, the view device will
    553  * exit touch mode, and find a view to take focus, so that the user may resume interacting
    554  * with the user interface without touching the screen again.
    555  * </p>
    556  * <p>
    557  * The touch mode state is maintained across {@link android.app.Activity}s.  Call
    558  * {@link #isInTouchMode} to see whether the device is currently in touch mode.
    559  * </p>
    560  *
    561  * <a name="Scrolling"></a>
    562  * <h3>Scrolling</h3>
    563  * <p>
    564  * The framework provides basic support for views that wish to internally
    565  * scroll their content. This includes keeping track of the X and Y scroll
    566  * offset as well as mechanisms for drawing scrollbars. See
    567  * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
    568  * {@link #awakenScrollBars()} for more details.
    569  * </p>
    570  *
    571  * <a name="Tags"></a>
    572  * <h3>Tags</h3>
    573  * <p>
    574  * Unlike IDs, tags are not used to identify views. Tags are essentially an
    575  * extra piece of information that can be associated with a view. They are most
    576  * often used as a convenience to store data related to views in the views
    577  * themselves rather than by putting them in a separate structure.
    578  * </p>
    579  *
    580  * <a name="Properties"></a>
    581  * <h3>Properties</h3>
    582  * <p>
    583  * The View class exposes an {@link #ALPHA} property, as well as several transform-related
    584  * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
    585  * available both in the {@link Property} form as well as in similarly-named setter/getter
    586  * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
    587  * be used to set persistent state associated with these rendering-related properties on the view.
    588  * The properties and methods can also be used in conjunction with
    589  * {@link android.animation.Animator Animator}-based animations, described more in the
    590  * <a href="#Animation">Animation</a> section.
    591  * </p>
    592  *
    593  * <a name="Animation"></a>
    594  * <h3>Animation</h3>
    595  * <p>
    596  * Starting with Android 3.0, the preferred way of animating views is to use the
    597  * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
    598  * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
    599  * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
    600  * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
    601  * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
    602  * makes animating these View properties particularly easy and efficient.
    603  * </p>
    604  * <p>
    605  * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
    606  * You can attach an {@link Animation} object to a view using
    607  * {@link #setAnimation(Animation)} or
    608  * {@link #startAnimation(Animation)}. The animation can alter the scale,
    609  * rotation, translation and alpha of a view over time. If the animation is
    610  * attached to a view that has children, the animation will affect the entire
    611  * subtree rooted by that node. When an animation is started, the framework will
    612  * take care of redrawing the appropriate views until the animation completes.
    613  * </p>
    614  *
    615  * <a name="Security"></a>
    616  * <h3>Security</h3>
    617  * <p>
    618  * Sometimes it is essential that an application be able to verify that an action
    619  * is being performed with the full knowledge and consent of the user, such as
    620  * granting a permission request, making a purchase or clicking on an advertisement.
    621  * Unfortunately, a malicious application could try to spoof the user into
    622  * performing these actions, unaware, by concealing the intended purpose of the view.
    623  * As a remedy, the framework offers a touch filtering mechanism that can be used to
    624  * improve the security of views that provide access to sensitive functionality.
    625  * </p><p>
    626  * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
    627  * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
    628  * will discard touches that are received whenever the view's window is obscured by
    629  * another visible window.  As a result, the view will not receive touches whenever a
    630  * toast, dialog or other window appears above the view's window.
    631  * </p><p>
    632  * For more fine-grained control over security, consider overriding the
    633  * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
    634  * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
    635  * </p>
    636  *
    637  * @attr ref android.R.styleable#View_alpha
    638  * @attr ref android.R.styleable#View_background
    639  * @attr ref android.R.styleable#View_clickable
    640  * @attr ref android.R.styleable#View_contentDescription
    641  * @attr ref android.R.styleable#View_drawingCacheQuality
    642  * @attr ref android.R.styleable#View_duplicateParentState
    643  * @attr ref android.R.styleable#View_id
    644  * @attr ref android.R.styleable#View_requiresFadingEdge
    645  * @attr ref android.R.styleable#View_fadeScrollbars
    646  * @attr ref android.R.styleable#View_fadingEdgeLength
    647  * @attr ref android.R.styleable#View_filterTouchesWhenObscured
    648  * @attr ref android.R.styleable#View_fitsSystemWindows
    649  * @attr ref android.R.styleable#View_isScrollContainer
    650  * @attr ref android.R.styleable#View_focusable
    651  * @attr ref android.R.styleable#View_focusableInTouchMode
    652  * @attr ref android.R.styleable#View_hapticFeedbackEnabled
    653  * @attr ref android.R.styleable#View_keepScreenOn
    654  * @attr ref android.R.styleable#View_layerType
    655  * @attr ref android.R.styleable#View_layoutDirection
    656  * @attr ref android.R.styleable#View_longClickable
    657  * @attr ref android.R.styleable#View_minHeight
    658  * @attr ref android.R.styleable#View_minWidth
    659  * @attr ref android.R.styleable#View_nextFocusDown
    660  * @attr ref android.R.styleable#View_nextFocusLeft
    661  * @attr ref android.R.styleable#View_nextFocusRight
    662  * @attr ref android.R.styleable#View_nextFocusUp
    663  * @attr ref android.R.styleable#View_onClick
    664  * @attr ref android.R.styleable#View_padding
    665  * @attr ref android.R.styleable#View_paddingBottom
    666  * @attr ref android.R.styleable#View_paddingLeft
    667  * @attr ref android.R.styleable#View_paddingRight
    668  * @attr ref android.R.styleable#View_paddingTop
    669  * @attr ref android.R.styleable#View_paddingStart
    670  * @attr ref android.R.styleable#View_paddingEnd
    671  * @attr ref android.R.styleable#View_saveEnabled
    672  * @attr ref android.R.styleable#View_rotation
    673  * @attr ref android.R.styleable#View_rotationX
    674  * @attr ref android.R.styleable#View_rotationY
    675  * @attr ref android.R.styleable#View_scaleX
    676  * @attr ref android.R.styleable#View_scaleY
    677  * @attr ref android.R.styleable#View_scrollX
    678  * @attr ref android.R.styleable#View_scrollY
    679  * @attr ref android.R.styleable#View_scrollbarSize
    680  * @attr ref android.R.styleable#View_scrollbarStyle
    681  * @attr ref android.R.styleable#View_scrollbars
    682  * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
    683  * @attr ref android.R.styleable#View_scrollbarFadeDuration
    684  * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
    685  * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
    686  * @attr ref android.R.styleable#View_scrollbarThumbVertical
    687  * @attr ref android.R.styleable#View_scrollbarTrackVertical
    688  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
    689  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
    690  * @attr ref android.R.styleable#View_stateListAnimator
    691  * @attr ref android.R.styleable#View_transitionName
    692  * @attr ref android.R.styleable#View_soundEffectsEnabled
    693  * @attr ref android.R.styleable#View_tag
    694  * @attr ref android.R.styleable#View_textAlignment
    695  * @attr ref android.R.styleable#View_textDirection
    696  * @attr ref android.R.styleable#View_transformPivotX
    697  * @attr ref android.R.styleable#View_transformPivotY
    698  * @attr ref android.R.styleable#View_translationX
    699  * @attr ref android.R.styleable#View_translationY
    700  * @attr ref android.R.styleable#View_translationZ
    701  * @attr ref android.R.styleable#View_visibility
    702  *
    703  * @see android.view.ViewGroup
    704  */
    705 @UiThread
    706 public class View implements Drawable.Callback, KeyEvent.Callback,
    707         AccessibilityEventSource {
    708     private static final boolean DBG = false;
    709 
    710     /**
    711      * The logging tag used by this class with android.util.Log.
    712      */
    713     protected static final String VIEW_LOG_TAG = "View";
    714 
    715     /**
    716      * When set to true, apps will draw debugging information about their layouts.
    717      *
    718      * @hide
    719      */
    720     public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
    721 
    722     /**
    723      * When set to true, this view will save its attribute data.
    724      *
    725      * @hide
    726      */
    727     public static boolean mDebugViewAttributes = false;
    728 
    729     /**
    730      * Used to mark a View that has no ID.
    731      */
    732     public static final int NO_ID = -1;
    733 
    734     /**
    735      * Signals that compatibility booleans have been initialized according to
    736      * target SDK versions.
    737      */
    738     private static boolean sCompatibilityDone = false;
    739 
    740     /**
    741      * Use the old (broken) way of building MeasureSpecs.
    742      */
    743     private static boolean sUseBrokenMakeMeasureSpec = false;
    744 
    745     /**
    746      * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
    747      */
    748     static boolean sUseZeroUnspecifiedMeasureSpec = false;
    749 
    750     /**
    751      * Ignore any optimizations using the measure cache.
    752      */
    753     private static boolean sIgnoreMeasureCache = false;
    754 
    755     /**
    756      * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
    757      * calling setFlags.
    758      */
    759     private static final int NOT_FOCUSABLE = 0x00000000;
    760 
    761     /**
    762      * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
    763      * setFlags.
    764      */
    765     private static final int FOCUSABLE = 0x00000001;
    766 
    767     /**
    768      * Mask for use with setFlags indicating bits used for focus.
    769      */
    770     private static final int FOCUSABLE_MASK = 0x00000001;
    771 
    772     /**
    773      * This view will adjust its padding to fit sytem windows (e.g. status bar)
    774      */
    775     private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
    776 
    777     /** @hide */
    778     @IntDef({VISIBLE, INVISIBLE, GONE})
    779     @Retention(RetentionPolicy.SOURCE)
    780     public @interface Visibility {}
    781 
    782     /**
    783      * This view is visible.
    784      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
    785      * android:visibility}.
    786      */
    787     public static final int VISIBLE = 0x00000000;
    788 
    789     /**
    790      * This view is invisible, but it still takes up space for layout purposes.
    791      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
    792      * android:visibility}.
    793      */
    794     public static final int INVISIBLE = 0x00000004;
    795 
    796     /**
    797      * This view is invisible, and it doesn't take any space for layout
    798      * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
    799      * android:visibility}.
    800      */
    801     public static final int GONE = 0x00000008;
    802 
    803     /**
    804      * Mask for use with setFlags indicating bits used for visibility.
    805      * {@hide}
    806      */
    807     static final int VISIBILITY_MASK = 0x0000000C;
    808 
    809     private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
    810 
    811     /**
    812      * This view is enabled. Interpretation varies by subclass.
    813      * Use with ENABLED_MASK when calling setFlags.
    814      * {@hide}
    815      */
    816     static final int ENABLED = 0x00000000;
    817 
    818     /**
    819      * This view is disabled. Interpretation varies by subclass.
    820      * Use with ENABLED_MASK when calling setFlags.
    821      * {@hide}
    822      */
    823     static final int DISABLED = 0x00000020;
    824 
    825    /**
    826     * Mask for use with setFlags indicating bits used for indicating whether
    827     * this view is enabled
    828     * {@hide}
    829     */
    830     static final int ENABLED_MASK = 0x00000020;
    831 
    832     /**
    833      * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
    834      * called and further optimizations will be performed. It is okay to have
    835      * this flag set and a background. Use with DRAW_MASK when calling setFlags.
    836      * {@hide}
    837      */
    838     static final int WILL_NOT_DRAW = 0x00000080;
    839 
    840     /**
    841      * Mask for use with setFlags indicating bits used for indicating whether
    842      * this view is will draw
    843      * {@hide}
    844      */
    845     static final int DRAW_MASK = 0x00000080;
    846 
    847     /**
    848      * <p>This view doesn't show scrollbars.</p>
    849      * {@hide}
    850      */
    851     static final int SCROLLBARS_NONE = 0x00000000;
    852 
    853     /**
    854      * <p>This view shows horizontal scrollbars.</p>
    855      * {@hide}
    856      */
    857     static final int SCROLLBARS_HORIZONTAL = 0x00000100;
    858 
    859     /**
    860      * <p>This view shows vertical scrollbars.</p>
    861      * {@hide}
    862      */
    863     static final int SCROLLBARS_VERTICAL = 0x00000200;
    864 
    865     /**
    866      * <p>Mask for use with setFlags indicating bits used for indicating which
    867      * scrollbars are enabled.</p>
    868      * {@hide}
    869      */
    870     static final int SCROLLBARS_MASK = 0x00000300;
    871 
    872     /**
    873      * Indicates that the view should filter touches when its window is obscured.
    874      * Refer to the class comments for more information about this security feature.
    875      * {@hide}
    876      */
    877     static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
    878 
    879     /**
    880      * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
    881      * that they are optional and should be skipped if the window has
    882      * requested system UI flags that ignore those insets for layout.
    883      */
    884     static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
    885 
    886     /**
    887      * <p>This view doesn't show fading edges.</p>
    888      * {@hide}
    889      */
    890     static final int FADING_EDGE_NONE = 0x00000000;
    891 
    892     /**
    893      * <p>This view shows horizontal fading edges.</p>
    894      * {@hide}
    895      */
    896     static final int FADING_EDGE_HORIZONTAL = 0x00001000;
    897 
    898     /**
    899      * <p>This view shows vertical fading edges.</p>
    900      * {@hide}
    901      */
    902     static final int FADING_EDGE_VERTICAL = 0x00002000;
    903 
    904     /**
    905      * <p>Mask for use with setFlags indicating bits used for indicating which
    906      * fading edges are enabled.</p>
    907      * {@hide}
    908      */
    909     static final int FADING_EDGE_MASK = 0x00003000;
    910 
    911     /**
    912      * <p>Indicates this view can be clicked. When clickable, a View reacts
    913      * to clicks by notifying the OnClickListener.<p>
    914      * {@hide}
    915      */
    916     static final int CLICKABLE = 0x00004000;
    917 
    918     /**
    919      * <p>Indicates this view is caching its drawing into a bitmap.</p>
    920      * {@hide}
    921      */
    922     static final int DRAWING_CACHE_ENABLED = 0x00008000;
    923 
    924     /**
    925      * <p>Indicates that no icicle should be saved for this view.<p>
    926      * {@hide}
    927      */
    928     static final int SAVE_DISABLED = 0x000010000;
    929 
    930     /**
    931      * <p>Mask for use with setFlags indicating bits used for the saveEnabled
    932      * property.</p>
    933      * {@hide}
    934      */
    935     static final int SAVE_DISABLED_MASK = 0x000010000;
    936 
    937     /**
    938      * <p>Indicates that no drawing cache should ever be created for this view.<p>
    939      * {@hide}
    940      */
    941     static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
    942 
    943     /**
    944      * <p>Indicates this view can take / keep focus when int touch mode.</p>
    945      * {@hide}
    946      */
    947     static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
    948 
    949     /** @hide */
    950     @Retention(RetentionPolicy.SOURCE)
    951     @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
    952     public @interface DrawingCacheQuality {}
    953 
    954     /**
    955      * <p>Enables low quality mode for the drawing cache.</p>
    956      */
    957     public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
    958 
    959     /**
    960      * <p>Enables high quality mode for the drawing cache.</p>
    961      */
    962     public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
    963 
    964     /**
    965      * <p>Enables automatic quality mode for the drawing cache.</p>
    966      */
    967     public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
    968 
    969     private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
    970             DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
    971     };
    972 
    973     /**
    974      * <p>Mask for use with setFlags indicating bits used for the cache
    975      * quality property.</p>
    976      * {@hide}
    977      */
    978     static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
    979 
    980     /**
    981      * <p>
    982      * Indicates this view can be long clicked. When long clickable, a View
    983      * reacts to long clicks by notifying the OnLongClickListener or showing a
    984      * context menu.
    985      * </p>
    986      * {@hide}
    987      */
    988     static final int LONG_CLICKABLE = 0x00200000;
    989 
    990     /**
    991      * <p>Indicates that this view gets its drawable states from its direct parent
    992      * and ignores its original internal states.</p>
    993      *
    994      * @hide
    995      */
    996     static final int DUPLICATE_PARENT_STATE = 0x00400000;
    997 
    998     /**
    999      * <p>
   1000      * Indicates this view can be context clicked. When context clickable, a View reacts to a
   1001      * context click (e.g. a primary stylus button press or right mouse click) by notifying the
   1002      * OnContextClickListener.
   1003      * </p>
   1004      * {@hide}
   1005      */
   1006     static final int CONTEXT_CLICKABLE = 0x00800000;
   1007 
   1008 
   1009     /** @hide */
   1010     @IntDef({
   1011         SCROLLBARS_INSIDE_OVERLAY,
   1012         SCROLLBARS_INSIDE_INSET,
   1013         SCROLLBARS_OUTSIDE_OVERLAY,
   1014         SCROLLBARS_OUTSIDE_INSET
   1015     })
   1016     @Retention(RetentionPolicy.SOURCE)
   1017     public @interface ScrollBarStyle {}
   1018 
   1019     /**
   1020      * The scrollbar style to display the scrollbars inside the content area,
   1021      * without increasing the padding. The scrollbars will be overlaid with
   1022      * translucency on the view's content.
   1023      */
   1024     public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
   1025 
   1026     /**
   1027      * The scrollbar style to display the scrollbars inside the padded area,
   1028      * increasing the padding of the view. The scrollbars will not overlap the
   1029      * content area of the view.
   1030      */
   1031     public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
   1032 
   1033     /**
   1034      * The scrollbar style to display the scrollbars at the edge of the view,
   1035      * without increasing the padding. The scrollbars will be overlaid with
   1036      * translucency.
   1037      */
   1038     public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
   1039 
   1040     /**
   1041      * The scrollbar style to display the scrollbars at the edge of the view,
   1042      * increasing the padding of the view. The scrollbars will only overlap the
   1043      * background, if any.
   1044      */
   1045     public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
   1046 
   1047     /**
   1048      * Mask to check if the scrollbar style is overlay or inset.
   1049      * {@hide}
   1050      */
   1051     static final int SCROLLBARS_INSET_MASK = 0x01000000;
   1052 
   1053     /**
   1054      * Mask to check if the scrollbar style is inside or outside.
   1055      * {@hide}
   1056      */
   1057     static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
   1058 
   1059     /**
   1060      * Mask for scrollbar style.
   1061      * {@hide}
   1062      */
   1063     static final int SCROLLBARS_STYLE_MASK = 0x03000000;
   1064 
   1065     /**
   1066      * View flag indicating that the screen should remain on while the
   1067      * window containing this view is visible to the user.  This effectively
   1068      * takes care of automatically setting the WindowManager's
   1069      * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
   1070      */
   1071     public static final int KEEP_SCREEN_ON = 0x04000000;
   1072 
   1073     /**
   1074      * View flag indicating whether this view should have sound effects enabled
   1075      * for events such as clicking and touching.
   1076      */
   1077     public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
   1078 
   1079     /**
   1080      * View flag indicating whether this view should have haptic feedback
   1081      * enabled for events such as long presses.
   1082      */
   1083     public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
   1084 
   1085     /**
   1086      * <p>Indicates that the view hierarchy should stop saving state when
   1087      * it reaches this view.  If state saving is initiated immediately at
   1088      * the view, it will be allowed.
   1089      * {@hide}
   1090      */
   1091     static final int PARENT_SAVE_DISABLED = 0x20000000;
   1092 
   1093     /**
   1094      * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
   1095      * {@hide}
   1096      */
   1097     static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
   1098 
   1099     /** @hide */
   1100     @IntDef(flag = true,
   1101             value = {
   1102                 FOCUSABLES_ALL,
   1103                 FOCUSABLES_TOUCH_MODE
   1104             })
   1105     @Retention(RetentionPolicy.SOURCE)
   1106     public @interface FocusableMode {}
   1107 
   1108     /**
   1109      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
   1110      * should add all focusable Views regardless if they are focusable in touch mode.
   1111      */
   1112     public static final int FOCUSABLES_ALL = 0x00000000;
   1113 
   1114     /**
   1115      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
   1116      * should add only Views focusable in touch mode.
   1117      */
   1118     public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
   1119 
   1120     /** @hide */
   1121     @IntDef({
   1122             FOCUS_BACKWARD,
   1123             FOCUS_FORWARD,
   1124             FOCUS_LEFT,
   1125             FOCUS_UP,
   1126             FOCUS_RIGHT,
   1127             FOCUS_DOWN
   1128     })
   1129     @Retention(RetentionPolicy.SOURCE)
   1130     public @interface FocusDirection {}
   1131 
   1132     /** @hide */
   1133     @IntDef({
   1134             FOCUS_LEFT,
   1135             FOCUS_UP,
   1136             FOCUS_RIGHT,
   1137             FOCUS_DOWN
   1138     })
   1139     @Retention(RetentionPolicy.SOURCE)
   1140     public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
   1141 
   1142     /**
   1143      * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
   1144      * item.
   1145      */
   1146     public static final int FOCUS_BACKWARD = 0x00000001;
   1147 
   1148     /**
   1149      * Use with {@link #focusSearch(int)}. Move focus to the next selectable
   1150      * item.
   1151      */
   1152     public static final int FOCUS_FORWARD = 0x00000002;
   1153 
   1154     /**
   1155      * Use with {@link #focusSearch(int)}. Move focus to the left.
   1156      */
   1157     public static final int FOCUS_LEFT = 0x00000011;
   1158 
   1159     /**
   1160      * Use with {@link #focusSearch(int)}. Move focus up.
   1161      */
   1162     public static final int FOCUS_UP = 0x00000021;
   1163 
   1164     /**
   1165      * Use with {@link #focusSearch(int)}. Move focus to the right.
   1166      */
   1167     public static final int FOCUS_RIGHT = 0x00000042;
   1168 
   1169     /**
   1170      * Use with {@link #focusSearch(int)}. Move focus down.
   1171      */
   1172     public static final int FOCUS_DOWN = 0x00000082;
   1173 
   1174     /**
   1175      * Bits of {@link #getMeasuredWidthAndState()} and
   1176      * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
   1177      */
   1178     public static final int MEASURED_SIZE_MASK = 0x00ffffff;
   1179 
   1180     /**
   1181      * Bits of {@link #getMeasuredWidthAndState()} and
   1182      * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
   1183      */
   1184     public static final int MEASURED_STATE_MASK = 0xff000000;
   1185 
   1186     /**
   1187      * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
   1188      * for functions that combine both width and height into a single int,
   1189      * such as {@link #getMeasuredState()} and the childState argument of
   1190      * {@link #resolveSizeAndState(int, int, int)}.
   1191      */
   1192     public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
   1193 
   1194     /**
   1195      * Bit of {@link #getMeasuredWidthAndState()} and
   1196      * {@link #getMeasuredWidthAndState()} that indicates the measured size
   1197      * is smaller that the space the view would like to have.
   1198      */
   1199     public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
   1200 
   1201     /**
   1202      * Base View state sets
   1203      */
   1204     // Singles
   1205     /**
   1206      * Indicates the view has no states set. States are used with
   1207      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1208      * view depending on its state.
   1209      *
   1210      * @see android.graphics.drawable.Drawable
   1211      * @see #getDrawableState()
   1212      */
   1213     protected static final int[] EMPTY_STATE_SET;
   1214     /**
   1215      * Indicates the view is enabled. States are used with
   1216      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1217      * view depending on its state.
   1218      *
   1219      * @see android.graphics.drawable.Drawable
   1220      * @see #getDrawableState()
   1221      */
   1222     protected static final int[] ENABLED_STATE_SET;
   1223     /**
   1224      * Indicates the view is focused. States are used with
   1225      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1226      * view depending on its state.
   1227      *
   1228      * @see android.graphics.drawable.Drawable
   1229      * @see #getDrawableState()
   1230      */
   1231     protected static final int[] FOCUSED_STATE_SET;
   1232     /**
   1233      * Indicates the view is selected. States are used with
   1234      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1235      * view depending on its state.
   1236      *
   1237      * @see android.graphics.drawable.Drawable
   1238      * @see #getDrawableState()
   1239      */
   1240     protected static final int[] SELECTED_STATE_SET;
   1241     /**
   1242      * Indicates the view is pressed. States are used with
   1243      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1244      * view depending on its state.
   1245      *
   1246      * @see android.graphics.drawable.Drawable
   1247      * @see #getDrawableState()
   1248      */
   1249     protected static final int[] PRESSED_STATE_SET;
   1250     /**
   1251      * Indicates the view's window has focus. States are used with
   1252      * {@link android.graphics.drawable.Drawable} to change the drawing of the
   1253      * view depending on its state.
   1254      *
   1255      * @see android.graphics.drawable.Drawable
   1256      * @see #getDrawableState()
   1257      */
   1258     protected static final int[] WINDOW_FOCUSED_STATE_SET;
   1259     // Doubles
   1260     /**
   1261      * Indicates the view is enabled and has the focus.
   1262      *
   1263      * @see #ENABLED_STATE_SET
   1264      * @see #FOCUSED_STATE_SET
   1265      */
   1266     protected static final int[] ENABLED_FOCUSED_STATE_SET;
   1267     /**
   1268      * Indicates the view is enabled and selected.
   1269      *
   1270      * @see #ENABLED_STATE_SET
   1271      * @see #SELECTED_STATE_SET
   1272      */
   1273     protected static final int[] ENABLED_SELECTED_STATE_SET;
   1274     /**
   1275      * Indicates the view is enabled and that its window has focus.
   1276      *
   1277      * @see #ENABLED_STATE_SET
   1278      * @see #WINDOW_FOCUSED_STATE_SET
   1279      */
   1280     protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
   1281     /**
   1282      * Indicates the view is focused and selected.
   1283      *
   1284      * @see #FOCUSED_STATE_SET
   1285      * @see #SELECTED_STATE_SET
   1286      */
   1287     protected static final int[] FOCUSED_SELECTED_STATE_SET;
   1288     /**
   1289      * Indicates the view has the focus and that its window has the focus.
   1290      *
   1291      * @see #FOCUSED_STATE_SET
   1292      * @see #WINDOW_FOCUSED_STATE_SET
   1293      */
   1294     protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
   1295     /**
   1296      * Indicates the view is selected and that its window has the focus.
   1297      *
   1298      * @see #SELECTED_STATE_SET
   1299      * @see #WINDOW_FOCUSED_STATE_SET
   1300      */
   1301     protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
   1302     // Triples
   1303     /**
   1304      * Indicates the view is enabled, focused and selected.
   1305      *
   1306      * @see #ENABLED_STATE_SET
   1307      * @see #FOCUSED_STATE_SET
   1308      * @see #SELECTED_STATE_SET
   1309      */
   1310     protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
   1311     /**
   1312      * Indicates the view is enabled, focused and its window has the focus.
   1313      *
   1314      * @see #ENABLED_STATE_SET
   1315      * @see #FOCUSED_STATE_SET
   1316      * @see #WINDOW_FOCUSED_STATE_SET
   1317      */
   1318     protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
   1319     /**
   1320      * Indicates the view is enabled, selected and its window has the focus.
   1321      *
   1322      * @see #ENABLED_STATE_SET
   1323      * @see #SELECTED_STATE_SET
   1324      * @see #WINDOW_FOCUSED_STATE_SET
   1325      */
   1326     protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1327     /**
   1328      * Indicates the view is focused, selected and its window has the focus.
   1329      *
   1330      * @see #FOCUSED_STATE_SET
   1331      * @see #SELECTED_STATE_SET
   1332      * @see #WINDOW_FOCUSED_STATE_SET
   1333      */
   1334     protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1335     /**
   1336      * Indicates the view is enabled, focused, selected and its window
   1337      * has the focus.
   1338      *
   1339      * @see #ENABLED_STATE_SET
   1340      * @see #FOCUSED_STATE_SET
   1341      * @see #SELECTED_STATE_SET
   1342      * @see #WINDOW_FOCUSED_STATE_SET
   1343      */
   1344     protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1345     /**
   1346      * Indicates the view is pressed and its window has the focus.
   1347      *
   1348      * @see #PRESSED_STATE_SET
   1349      * @see #WINDOW_FOCUSED_STATE_SET
   1350      */
   1351     protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
   1352     /**
   1353      * Indicates the view is pressed and selected.
   1354      *
   1355      * @see #PRESSED_STATE_SET
   1356      * @see #SELECTED_STATE_SET
   1357      */
   1358     protected static final int[] PRESSED_SELECTED_STATE_SET;
   1359     /**
   1360      * Indicates the view is pressed, selected and its window has the focus.
   1361      *
   1362      * @see #PRESSED_STATE_SET
   1363      * @see #SELECTED_STATE_SET
   1364      * @see #WINDOW_FOCUSED_STATE_SET
   1365      */
   1366     protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1367     /**
   1368      * Indicates the view is pressed and focused.
   1369      *
   1370      * @see #PRESSED_STATE_SET
   1371      * @see #FOCUSED_STATE_SET
   1372      */
   1373     protected static final int[] PRESSED_FOCUSED_STATE_SET;
   1374     /**
   1375      * Indicates the view is pressed, focused and its window has the focus.
   1376      *
   1377      * @see #PRESSED_STATE_SET
   1378      * @see #FOCUSED_STATE_SET
   1379      * @see #WINDOW_FOCUSED_STATE_SET
   1380      */
   1381     protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
   1382     /**
   1383      * Indicates the view is pressed, focused and selected.
   1384      *
   1385      * @see #PRESSED_STATE_SET
   1386      * @see #SELECTED_STATE_SET
   1387      * @see #FOCUSED_STATE_SET
   1388      */
   1389     protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
   1390     /**
   1391      * Indicates the view is pressed, focused, selected and its window has the focus.
   1392      *
   1393      * @see #PRESSED_STATE_SET
   1394      * @see #FOCUSED_STATE_SET
   1395      * @see #SELECTED_STATE_SET
   1396      * @see #WINDOW_FOCUSED_STATE_SET
   1397      */
   1398     protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1399     /**
   1400      * Indicates the view is pressed and enabled.
   1401      *
   1402      * @see #PRESSED_STATE_SET
   1403      * @see #ENABLED_STATE_SET
   1404      */
   1405     protected static final int[] PRESSED_ENABLED_STATE_SET;
   1406     /**
   1407      * Indicates the view is pressed, enabled and its window has the focus.
   1408      *
   1409      * @see #PRESSED_STATE_SET
   1410      * @see #ENABLED_STATE_SET
   1411      * @see #WINDOW_FOCUSED_STATE_SET
   1412      */
   1413     protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
   1414     /**
   1415      * Indicates the view is pressed, enabled and selected.
   1416      *
   1417      * @see #PRESSED_STATE_SET
   1418      * @see #ENABLED_STATE_SET
   1419      * @see #SELECTED_STATE_SET
   1420      */
   1421     protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
   1422     /**
   1423      * Indicates the view is pressed, enabled, selected and its window has the
   1424      * focus.
   1425      *
   1426      * @see #PRESSED_STATE_SET
   1427      * @see #ENABLED_STATE_SET
   1428      * @see #SELECTED_STATE_SET
   1429      * @see #WINDOW_FOCUSED_STATE_SET
   1430      */
   1431     protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1432     /**
   1433      * Indicates the view is pressed, enabled and focused.
   1434      *
   1435      * @see #PRESSED_STATE_SET
   1436      * @see #ENABLED_STATE_SET
   1437      * @see #FOCUSED_STATE_SET
   1438      */
   1439     protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
   1440     /**
   1441      * Indicates the view is pressed, enabled, focused and its window has the
   1442      * focus.
   1443      *
   1444      * @see #PRESSED_STATE_SET
   1445      * @see #ENABLED_STATE_SET
   1446      * @see #FOCUSED_STATE_SET
   1447      * @see #WINDOW_FOCUSED_STATE_SET
   1448      */
   1449     protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
   1450     /**
   1451      * Indicates the view is pressed, enabled, focused and selected.
   1452      *
   1453      * @see #PRESSED_STATE_SET
   1454      * @see #ENABLED_STATE_SET
   1455      * @see #SELECTED_STATE_SET
   1456      * @see #FOCUSED_STATE_SET
   1457      */
   1458     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
   1459     /**
   1460      * Indicates the view is pressed, enabled, focused, selected and its window
   1461      * has the focus.
   1462      *
   1463      * @see #PRESSED_STATE_SET
   1464      * @see #ENABLED_STATE_SET
   1465      * @see #SELECTED_STATE_SET
   1466      * @see #FOCUSED_STATE_SET
   1467      * @see #WINDOW_FOCUSED_STATE_SET
   1468      */
   1469     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
   1470 
   1471     static {
   1472         EMPTY_STATE_SET = StateSet.get(0);
   1473 
   1474         WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
   1475 
   1476         SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
   1477         SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1478                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
   1479 
   1480         FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
   1481         FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1482                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
   1483         FOCUSED_SELECTED_STATE_SET = StateSet.get(
   1484                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
   1485         FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1486                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   1487                         | StateSet.VIEW_STATE_FOCUSED);
   1488 
   1489         ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
   1490         ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1491                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
   1492         ENABLED_SELECTED_STATE_SET = StateSet.get(
   1493                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
   1494         ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1495                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   1496                         | StateSet.VIEW_STATE_ENABLED);
   1497         ENABLED_FOCUSED_STATE_SET = StateSet.get(
   1498                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
   1499         ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1500                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
   1501                         | StateSet.VIEW_STATE_ENABLED);
   1502         ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
   1503                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
   1504                         | StateSet.VIEW_STATE_ENABLED);
   1505         ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1506                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   1507                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
   1508 
   1509         PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
   1510         PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1511                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
   1512         PRESSED_SELECTED_STATE_SET = StateSet.get(
   1513                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
   1514         PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1515                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   1516                         | StateSet.VIEW_STATE_PRESSED);
   1517         PRESSED_FOCUSED_STATE_SET = StateSet.get(
   1518                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
   1519         PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1520                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
   1521                         | StateSet.VIEW_STATE_PRESSED);
   1522         PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
   1523                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
   1524                         | StateSet.VIEW_STATE_PRESSED);
   1525         PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1526                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   1527                         | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
   1528         PRESSED_ENABLED_STATE_SET = StateSet.get(
   1529                 StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
   1530         PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1531                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
   1532                         | StateSet.VIEW_STATE_PRESSED);
   1533         PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
   1534                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
   1535                         | StateSet.VIEW_STATE_PRESSED);
   1536         PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1537                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   1538                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
   1539         PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
   1540                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
   1541                         | StateSet.VIEW_STATE_PRESSED);
   1542         PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1543                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
   1544                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
   1545         PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
   1546                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
   1547                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
   1548         PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
   1549                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
   1550                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
   1551                         | StateSet.VIEW_STATE_PRESSED);
   1552     }
   1553 
   1554     /**
   1555      * Accessibility event types that are dispatched for text population.
   1556      */
   1557     private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
   1558             AccessibilityEvent.TYPE_VIEW_CLICKED
   1559             | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
   1560             | AccessibilityEvent.TYPE_VIEW_SELECTED
   1561             | AccessibilityEvent.TYPE_VIEW_FOCUSED
   1562             | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
   1563             | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
   1564             | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
   1565             | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
   1566             | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
   1567             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
   1568             | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
   1569 
   1570     /**
   1571      * Temporary Rect currently for use in setBackground().  This will probably
   1572      * be extended in the future to hold our own class with more than just
   1573      * a Rect. :)
   1574      */
   1575     static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
   1576 
   1577     /**
   1578      * Map used to store views' tags.
   1579      */
   1580     private SparseArray<Object> mKeyedTags;
   1581 
   1582     /**
   1583      * The next available accessibility id.
   1584      */
   1585     private static int sNextAccessibilityViewId;
   1586 
   1587     /**
   1588      * The animation currently associated with this view.
   1589      * @hide
   1590      */
   1591     protected Animation mCurrentAnimation = null;
   1592 
   1593     /**
   1594      * Width as measured during measure pass.
   1595      * {@hide}
   1596      */
   1597     @ViewDebug.ExportedProperty(category = "measurement")
   1598     int mMeasuredWidth;
   1599 
   1600     /**
   1601      * Height as measured during measure pass.
   1602      * {@hide}
   1603      */
   1604     @ViewDebug.ExportedProperty(category = "measurement")
   1605     int mMeasuredHeight;
   1606 
   1607     /**
   1608      * Flag to indicate that this view was marked INVALIDATED, or had its display list
   1609      * invalidated, prior to the current drawing iteration. If true, the view must re-draw
   1610      * its display list. This flag, used only when hw accelerated, allows us to clear the
   1611      * flag while retaining this information until it's needed (at getDisplayList() time and
   1612      * in drawChild(), when we decide to draw a view's children's display lists into our own).
   1613      *
   1614      * {@hide}
   1615      */
   1616     boolean mRecreateDisplayList = false;
   1617 
   1618     /**
   1619      * The view's identifier.
   1620      * {@hide}
   1621      *
   1622      * @see #setId(int)
   1623      * @see #getId()
   1624      */
   1625     @IdRes
   1626     @ViewDebug.ExportedProperty(resolveId = true)
   1627     int mID = NO_ID;
   1628 
   1629     /**
   1630      * The stable ID of this view for accessibility purposes.
   1631      */
   1632     int mAccessibilityViewId = NO_ID;
   1633 
   1634     private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
   1635 
   1636     SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
   1637 
   1638     /**
   1639      * The view's tag.
   1640      * {@hide}
   1641      *
   1642      * @see #setTag(Object)
   1643      * @see #getTag()
   1644      */
   1645     protected Object mTag = null;
   1646 
   1647     // for mPrivateFlags:
   1648     /** {@hide} */
   1649     static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
   1650     /** {@hide} */
   1651     static final int PFLAG_FOCUSED                     = 0x00000002;
   1652     /** {@hide} */
   1653     static final int PFLAG_SELECTED                    = 0x00000004;
   1654     /** {@hide} */
   1655     static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
   1656     /** {@hide} */
   1657     static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
   1658     /** {@hide} */
   1659     static final int PFLAG_DRAWN                       = 0x00000020;
   1660     /**
   1661      * When this flag is set, this view is running an animation on behalf of its
   1662      * children and should therefore not cancel invalidate requests, even if they
   1663      * lie outside of this view's bounds.
   1664      *
   1665      * {@hide}
   1666      */
   1667     static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
   1668     /** {@hide} */
   1669     static final int PFLAG_SKIP_DRAW                   = 0x00000080;
   1670     /** {@hide} */
   1671     static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
   1672     /** {@hide} */
   1673     static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
   1674     /** {@hide} */
   1675     static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
   1676     /** {@hide} */
   1677     static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
   1678     /** {@hide} */
   1679     static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
   1680 
   1681     private static final int PFLAG_PRESSED             = 0x00004000;
   1682 
   1683     /** {@hide} */
   1684     static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
   1685     /**
   1686      * Flag used to indicate that this view should be drawn once more (and only once
   1687      * more) after its animation has completed.
   1688      * {@hide}
   1689      */
   1690     static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
   1691 
   1692     private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
   1693 
   1694     /**
   1695      * Indicates that the View returned true when onSetAlpha() was called and that
   1696      * the alpha must be restored.
   1697      * {@hide}
   1698      */
   1699     static final int PFLAG_ALPHA_SET                   = 0x00040000;
   1700 
   1701     /**
   1702      * Set by {@link #setScrollContainer(boolean)}.
   1703      */
   1704     static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
   1705 
   1706     /**
   1707      * Set by {@link #setScrollContainer(boolean)}.
   1708      */
   1709     static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
   1710 
   1711     /**
   1712      * View flag indicating whether this view was invalidated (fully or partially.)
   1713      *
   1714      * @hide
   1715      */
   1716     static final int PFLAG_DIRTY                       = 0x00200000;
   1717 
   1718     /**
   1719      * View flag indicating whether this view was invalidated by an opaque
   1720      * invalidate request.
   1721      *
   1722      * @hide
   1723      */
   1724     static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
   1725 
   1726     /**
   1727      * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
   1728      *
   1729      * @hide
   1730      */
   1731     static final int PFLAG_DIRTY_MASK                  = 0x00600000;
   1732 
   1733     /**
   1734      * Indicates whether the background is opaque.
   1735      *
   1736      * @hide
   1737      */
   1738     static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
   1739 
   1740     /**
   1741      * Indicates whether the scrollbars are opaque.
   1742      *
   1743      * @hide
   1744      */
   1745     static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
   1746 
   1747     /**
   1748      * Indicates whether the view is opaque.
   1749      *
   1750      * @hide
   1751      */
   1752     static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
   1753 
   1754     /**
   1755      * Indicates a prepressed state;
   1756      * the short time between ACTION_DOWN and recognizing
   1757      * a 'real' press. Prepressed is used to recognize quick taps
   1758      * even when they are shorter than ViewConfiguration.getTapTimeout().
   1759      *
   1760      * @hide
   1761      */
   1762     private static final int PFLAG_PREPRESSED          = 0x02000000;
   1763 
   1764     /**
   1765      * Indicates whether the view is temporarily detached.
   1766      *
   1767      * @hide
   1768      */
   1769     static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
   1770 
   1771     /**
   1772      * Indicates that we should awaken scroll bars once attached
   1773      *
   1774      * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
   1775      * during window attachment and it is no longer needed. Feel free to repurpose it.
   1776      *
   1777      * @hide
   1778      */
   1779     private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
   1780 
   1781     /**
   1782      * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
   1783      * @hide
   1784      */
   1785     private static final int PFLAG_HOVERED             = 0x10000000;
   1786 
   1787     /**
   1788      * no longer needed, should be reused
   1789      */
   1790     private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
   1791 
   1792     /** {@hide} */
   1793     static final int PFLAG_ACTIVATED                   = 0x40000000;
   1794 
   1795     /**
   1796      * Indicates that this view was specifically invalidated, not just dirtied because some
   1797      * child view was invalidated. The flag is used to determine when we need to recreate
   1798      * a view's display list (as opposed to just returning a reference to its existing
   1799      * display list).
   1800      *
   1801      * @hide
   1802      */
   1803     static final int PFLAG_INVALIDATED                 = 0x80000000;
   1804 
   1805     /**
   1806      * Masks for mPrivateFlags2, as generated by dumpFlags():
   1807      *
   1808      * |-------|-------|-------|-------|
   1809      *                                 1 PFLAG2_DRAG_CAN_ACCEPT
   1810      *                                1  PFLAG2_DRAG_HOVERED
   1811      *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
   1812      *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
   1813      *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
   1814      *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
   1815      *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
   1816      *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
   1817      *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
   1818      *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
   1819      *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
   1820      *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
   1821      *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
   1822      *                         111       PFLAG2_TEXT_DIRECTION_MASK
   1823      *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
   1824      *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
   1825      *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
   1826      *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
   1827      *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
   1828      *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
   1829      *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
   1830      *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
   1831      *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
   1832      *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
   1833      *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
   1834      *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
   1835      *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
   1836      *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
   1837      *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
   1838      *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
   1839      *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
   1840      *     1                             PFLAG2_VIEW_QUICK_REJECTED
   1841      *    1                              PFLAG2_PADDING_RESOLVED
   1842      *   1                               PFLAG2_DRAWABLE_RESOLVED
   1843      *  1                                PFLAG2_HAS_TRANSIENT_STATE
   1844      * |-------|-------|-------|-------|
   1845      */
   1846 
   1847     /**
   1848      * Indicates that this view has reported that it can accept the current drag's content.
   1849      * Cleared when the drag operation concludes.
   1850      * @hide
   1851      */
   1852     static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
   1853 
   1854     /**
   1855      * Indicates that this view is currently directly under the drag location in a
   1856      * drag-and-drop operation involving content that it can accept.  Cleared when
   1857      * the drag exits the view, or when the drag operation concludes.
   1858      * @hide
   1859      */
   1860     static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
   1861 
   1862     /** @hide */
   1863     @IntDef({
   1864         LAYOUT_DIRECTION_LTR,
   1865         LAYOUT_DIRECTION_RTL,
   1866         LAYOUT_DIRECTION_INHERIT,
   1867         LAYOUT_DIRECTION_LOCALE
   1868     })
   1869     @Retention(RetentionPolicy.SOURCE)
   1870     // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
   1871     public @interface LayoutDir {}
   1872 
   1873     /** @hide */
   1874     @IntDef({
   1875         LAYOUT_DIRECTION_LTR,
   1876         LAYOUT_DIRECTION_RTL
   1877     })
   1878     @Retention(RetentionPolicy.SOURCE)
   1879     public @interface ResolvedLayoutDir {}
   1880 
   1881     /**
   1882      * A flag to indicate that the layout direction of this view has not been defined yet.
   1883      * @hide
   1884      */
   1885     public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
   1886 
   1887     /**
   1888      * Horizontal layout direction of this view is from Left to Right.
   1889      * Use with {@link #setLayoutDirection}.
   1890      */
   1891     public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
   1892 
   1893     /**
   1894      * Horizontal layout direction of this view is from Right to Left.
   1895      * Use with {@link #setLayoutDirection}.
   1896      */
   1897     public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
   1898 
   1899     /**
   1900      * Horizontal layout direction of this view is inherited from its parent.
   1901      * Use with {@link #setLayoutDirection}.
   1902      */
   1903     public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
   1904 
   1905     /**
   1906      * Horizontal layout direction of this view is from deduced from the default language
   1907      * script for the locale. Use with {@link #setLayoutDirection}.
   1908      */
   1909     public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
   1910 
   1911     /**
   1912      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
   1913      * @hide
   1914      */
   1915     static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
   1916 
   1917     /**
   1918      * Mask for use with private flags indicating bits used for horizontal layout direction.
   1919      * @hide
   1920      */
   1921     static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
   1922 
   1923     /**
   1924      * Indicates whether the view horizontal layout direction has been resolved and drawn to the
   1925      * right-to-left direction.
   1926      * @hide
   1927      */
   1928     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
   1929 
   1930     /**
   1931      * Indicates whether the view horizontal layout direction has been resolved.
   1932      * @hide
   1933      */
   1934     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
   1935 
   1936     /**
   1937      * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
   1938      * @hide
   1939      */
   1940     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
   1941             << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
   1942 
   1943     /*
   1944      * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
   1945      * flag value.
   1946      * @hide
   1947      */
   1948     private static final int[] LAYOUT_DIRECTION_FLAGS = {
   1949             LAYOUT_DIRECTION_LTR,
   1950             LAYOUT_DIRECTION_RTL,
   1951             LAYOUT_DIRECTION_INHERIT,
   1952             LAYOUT_DIRECTION_LOCALE
   1953     };
   1954 
   1955     /**
   1956      * Default horizontal layout direction.
   1957      */
   1958     private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
   1959 
   1960     /**
   1961      * Default horizontal layout direction.
   1962      * @hide
   1963      */
   1964     static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
   1965 
   1966     /**
   1967      * Text direction is inherited through {@link ViewGroup}
   1968      */
   1969     public static final int TEXT_DIRECTION_INHERIT = 0;
   1970 
   1971     /**
   1972      * Text direction is using "first strong algorithm". The first strong directional character
   1973      * determines the paragraph direction. If there is no strong directional character, the
   1974      * paragraph direction is the view's resolved layout direction.
   1975      */
   1976     public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
   1977 
   1978     /**
   1979      * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
   1980      * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
   1981      * If there are neither, the paragraph direction is the view's resolved layout direction.
   1982      */
   1983     public static final int TEXT_DIRECTION_ANY_RTL = 2;
   1984 
   1985     /**
   1986      * Text direction is forced to LTR.
   1987      */
   1988     public static final int TEXT_DIRECTION_LTR = 3;
   1989 
   1990     /**
   1991      * Text direction is forced to RTL.
   1992      */
   1993     public static final int TEXT_DIRECTION_RTL = 4;
   1994 
   1995     /**
   1996      * Text direction is coming from the system Locale.
   1997      */
   1998     public static final int TEXT_DIRECTION_LOCALE = 5;
   1999 
   2000     /**
   2001      * Text direction is using "first strong algorithm". The first strong directional character
   2002      * determines the paragraph direction. If there is no strong directional character, the
   2003      * paragraph direction is LTR.
   2004      */
   2005     public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
   2006 
   2007     /**
   2008      * Text direction is using "first strong algorithm". The first strong directional character
   2009      * determines the paragraph direction. If there is no strong directional character, the
   2010      * paragraph direction is RTL.
   2011      */
   2012     public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
   2013 
   2014     /**
   2015      * Default text direction is inherited
   2016      */
   2017     private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
   2018 
   2019     /**
   2020      * Default resolved text direction
   2021      * @hide
   2022      */
   2023     static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
   2024 
   2025     /**
   2026      * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
   2027      * @hide
   2028      */
   2029     static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
   2030 
   2031     /**
   2032      * Mask for use with private flags indicating bits used for text direction.
   2033      * @hide
   2034      */
   2035     static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
   2036             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
   2037 
   2038     /**
   2039      * Array of text direction flags for mapping attribute "textDirection" to correct
   2040      * flag value.
   2041      * @hide
   2042      */
   2043     private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
   2044             TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2045             TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2046             TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2047             TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2048             TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2049             TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2050             TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
   2051             TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
   2052     };
   2053 
   2054     /**
   2055      * Indicates whether the view text direction has been resolved.
   2056      * @hide
   2057      */
   2058     static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
   2059             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
   2060 
   2061     /**
   2062      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
   2063      * @hide
   2064      */
   2065     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
   2066 
   2067     /**
   2068      * Mask for use with private flags indicating bits used for resolved text direction.
   2069      * @hide
   2070      */
   2071     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
   2072             << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
   2073 
   2074     /**
   2075      * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
   2076      * @hide
   2077      */
   2078     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
   2079             TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
   2080 
   2081     /** @hide */
   2082     @IntDef({
   2083         TEXT_ALIGNMENT_INHERIT,
   2084         TEXT_ALIGNMENT_GRAVITY,
   2085         TEXT_ALIGNMENT_CENTER,
   2086         TEXT_ALIGNMENT_TEXT_START,
   2087         TEXT_ALIGNMENT_TEXT_END,
   2088         TEXT_ALIGNMENT_VIEW_START,
   2089         TEXT_ALIGNMENT_VIEW_END
   2090     })
   2091     @Retention(RetentionPolicy.SOURCE)
   2092     public @interface TextAlignment {}
   2093 
   2094     /**
   2095      * Default text alignment. The text alignment of this View is inherited from its parent.
   2096      * Use with {@link #setTextAlignment(int)}
   2097      */
   2098     public static final int TEXT_ALIGNMENT_INHERIT = 0;
   2099 
   2100     /**
   2101      * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
   2102      * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraphs text direction.
   2103      *
   2104      * Use with {@link #setTextAlignment(int)}
   2105      */
   2106     public static final int TEXT_ALIGNMENT_GRAVITY = 1;
   2107 
   2108     /**
   2109      * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
   2110      *
   2111      * Use with {@link #setTextAlignment(int)}
   2112      */
   2113     public static final int TEXT_ALIGNMENT_TEXT_START = 2;
   2114 
   2115     /**
   2116      * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
   2117      *
   2118      * Use with {@link #setTextAlignment(int)}
   2119      */
   2120     public static final int TEXT_ALIGNMENT_TEXT_END = 3;
   2121 
   2122     /**
   2123      * Center the paragraph, e.g. ALIGN_CENTER.
   2124      *
   2125      * Use with {@link #setTextAlignment(int)}
   2126      */
   2127     public static final int TEXT_ALIGNMENT_CENTER = 4;
   2128 
   2129     /**
   2130      * Align to the start of the view, which is ALIGN_LEFT if the views resolved
   2131      * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
   2132      *
   2133      * Use with {@link #setTextAlignment(int)}
   2134      */
   2135     public static final int TEXT_ALIGNMENT_VIEW_START = 5;
   2136 
   2137     /**
   2138      * Align to the end of the view, which is ALIGN_RIGHT if the views resolved
   2139      * layoutDirection is LTR, and ALIGN_LEFT otherwise.
   2140      *
   2141      * Use with {@link #setTextAlignment(int)}
   2142      */
   2143     public static final int TEXT_ALIGNMENT_VIEW_END = 6;
   2144 
   2145     /**
   2146      * Default text alignment is inherited
   2147      */
   2148     private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
   2149 
   2150     /**
   2151      * Default resolved text alignment
   2152      * @hide
   2153      */
   2154     static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
   2155 
   2156     /**
   2157       * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
   2158       * @hide
   2159       */
   2160     static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
   2161 
   2162     /**
   2163       * Mask for use with private flags indicating bits used for text alignment.
   2164       * @hide
   2165       */
   2166     static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
   2167 
   2168     /**
   2169      * Array of text direction flags for mapping attribute "textAlignment" to correct
   2170      * flag value.
   2171      * @hide
   2172      */
   2173     private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
   2174             TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
   2175             TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
   2176             TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
   2177             TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
   2178             TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
   2179             TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
   2180             TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
   2181     };
   2182 
   2183     /**
   2184      * Indicates whether the view text alignment has been resolved.
   2185      * @hide
   2186      */
   2187     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
   2188 
   2189     /**
   2190      * Bit shift to get the resolved text alignment.
   2191      * @hide
   2192      */
   2193     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
   2194 
   2195     /**
   2196      * Mask for use with private flags indicating bits used for text alignment.
   2197      * @hide
   2198      */
   2199     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
   2200             << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
   2201 
   2202     /**
   2203      * Indicates whether if the view text alignment has been resolved to gravity
   2204      */
   2205     private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
   2206             TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
   2207 
   2208     // Accessiblity constants for mPrivateFlags2
   2209 
   2210     /**
   2211      * Shift for the bits in {@link #mPrivateFlags2} related to the
   2212      * "importantForAccessibility" attribute.
   2213      */
   2214     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
   2215 
   2216     /**
   2217      * Automatically determine whether a view is important for accessibility.
   2218      */
   2219     public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
   2220 
   2221     /**
   2222      * The view is important for accessibility.
   2223      */
   2224     public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
   2225 
   2226     /**
   2227      * The view is not important for accessibility.
   2228      */
   2229     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
   2230 
   2231     /**
   2232      * The view is not important for accessibility, nor are any of its
   2233      * descendant views.
   2234      */
   2235     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
   2236 
   2237     /**
   2238      * The default whether the view is important for accessibility.
   2239      */
   2240     static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
   2241 
   2242     /**
   2243      * Mask for obtainig the bits which specify how to determine
   2244      * whether a view is important for accessibility.
   2245      */
   2246     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
   2247         | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
   2248         | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
   2249         << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
   2250 
   2251     /**
   2252      * Shift for the bits in {@link #mPrivateFlags2} related to the
   2253      * "accessibilityLiveRegion" attribute.
   2254      */
   2255     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
   2256 
   2257     /**
   2258      * Live region mode specifying that accessibility services should not
   2259      * automatically announce changes to this view. This is the default live
   2260      * region mode for most views.
   2261      * <p>
   2262      * Use with {@link #setAccessibilityLiveRegion(int)}.
   2263      */
   2264     public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
   2265 
   2266     /**
   2267      * Live region mode specifying that accessibility services should announce
   2268      * changes to this view.
   2269      * <p>
   2270      * Use with {@link #setAccessibilityLiveRegion(int)}.
   2271      */
   2272     public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
   2273 
   2274     /**
   2275      * Live region mode specifying that accessibility services should interrupt
   2276      * ongoing speech to immediately announce changes to this view.
   2277      * <p>
   2278      * Use with {@link #setAccessibilityLiveRegion(int)}.
   2279      */
   2280     public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
   2281 
   2282     /**
   2283      * The default whether the view is important for accessibility.
   2284      */
   2285     static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
   2286 
   2287     /**
   2288      * Mask for obtaining the bits which specify a view's accessibility live
   2289      * region mode.
   2290      */
   2291     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
   2292             | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
   2293             << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
   2294 
   2295     /**
   2296      * Flag indicating whether a view has accessibility focus.
   2297      */
   2298     static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
   2299 
   2300     /**
   2301      * Flag whether the accessibility state of the subtree rooted at this view changed.
   2302      */
   2303     static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
   2304 
   2305     /**
   2306      * Flag indicating whether a view failed the quickReject() check in draw(). This condition
   2307      * is used to check whether later changes to the view's transform should invalidate the
   2308      * view to force the quickReject test to run again.
   2309      */
   2310     static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
   2311 
   2312     /**
   2313      * Flag indicating that start/end padding has been resolved into left/right padding
   2314      * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
   2315      * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
   2316      * during measurement. In some special cases this is required such as when an adapter-based
   2317      * view measures prospective children without attaching them to a window.
   2318      */
   2319     static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
   2320 
   2321     /**
   2322      * Flag indicating that the start/end drawables has been resolved into left/right ones.
   2323      */
   2324     static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
   2325 
   2326     /**
   2327      * Indicates that the view is tracking some sort of transient state
   2328      * that the app should not need to be aware of, but that the framework
   2329      * should take special care to preserve.
   2330      */
   2331     static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
   2332 
   2333     /**
   2334      * Group of bits indicating that RTL properties resolution is done.
   2335      */
   2336     static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
   2337             PFLAG2_TEXT_DIRECTION_RESOLVED |
   2338             PFLAG2_TEXT_ALIGNMENT_RESOLVED |
   2339             PFLAG2_PADDING_RESOLVED |
   2340             PFLAG2_DRAWABLE_RESOLVED;
   2341 
   2342     // There are a couple of flags left in mPrivateFlags2
   2343 
   2344     /* End of masks for mPrivateFlags2 */
   2345 
   2346     /**
   2347      * Masks for mPrivateFlags3, as generated by dumpFlags():
   2348      *
   2349      * |-------|-------|-------|-------|
   2350      *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
   2351      *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
   2352      *                               1   PFLAG3_IS_LAID_OUT
   2353      *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
   2354      *                             1     PFLAG3_CALLED_SUPER
   2355      *                            1      PFLAG3_APPLYING_INSETS
   2356      *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
   2357      *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
   2358      *                         1         PFLAG3_ASSIST_BLOCKED
   2359      * |-------|-------|-------|-------|
   2360      */
   2361 
   2362     /**
   2363      * Flag indicating that view has a transform animation set on it. This is used to track whether
   2364      * an animation is cleared between successive frames, in order to tell the associated
   2365      * DisplayList to clear its animation matrix.
   2366      */
   2367     static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
   2368 
   2369     /**
   2370      * Flag indicating that view has an alpha animation set on it. This is used to track whether an
   2371      * animation is cleared between successive frames, in order to tell the associated
   2372      * DisplayList to restore its alpha value.
   2373      */
   2374     static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
   2375 
   2376     /**
   2377      * Flag indicating that the view has been through at least one layout since it
   2378      * was last attached to a window.
   2379      */
   2380     static final int PFLAG3_IS_LAID_OUT = 0x4;
   2381 
   2382     /**
   2383      * Flag indicating that a call to measure() was skipped and should be done
   2384      * instead when layout() is invoked.
   2385      */
   2386     static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
   2387 
   2388     /**
   2389      * Flag indicating that an overridden method correctly called down to
   2390      * the superclass implementation as required by the API spec.
   2391      */
   2392     static final int PFLAG3_CALLED_SUPER = 0x10;
   2393 
   2394     /**
   2395      * Flag indicating that we're in the process of applying window insets.
   2396      */
   2397     static final int PFLAG3_APPLYING_INSETS = 0x20;
   2398 
   2399     /**
   2400      * Flag indicating that we're in the process of fitting system windows using the old method.
   2401      */
   2402     static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
   2403 
   2404     /**
   2405      * Flag indicating that nested scrolling is enabled for this view.
   2406      * The view will optionally cooperate with views up its parent chain to allow for
   2407      * integrated nested scrolling along the same axis.
   2408      */
   2409     static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
   2410 
   2411     /**
   2412      * Flag indicating that the bottom scroll indicator should be displayed
   2413      * when this view can scroll up.
   2414      */
   2415     static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
   2416 
   2417     /**
   2418      * Flag indicating that the bottom scroll indicator should be displayed
   2419      * when this view can scroll down.
   2420      */
   2421     static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
   2422 
   2423     /**
   2424      * Flag indicating that the left scroll indicator should be displayed
   2425      * when this view can scroll left.
   2426      */
   2427     static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
   2428 
   2429     /**
   2430      * Flag indicating that the right scroll indicator should be displayed
   2431      * when this view can scroll right.
   2432      */
   2433     static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
   2434 
   2435     /**
   2436      * Flag indicating that the start scroll indicator should be displayed
   2437      * when this view can scroll in the start direction.
   2438      */
   2439     static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
   2440 
   2441     /**
   2442      * Flag indicating that the end scroll indicator should be displayed
   2443      * when this view can scroll in the end direction.
   2444      */
   2445     static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
   2446 
   2447     /* End of masks for mPrivateFlags3 */
   2448 
   2449     static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
   2450 
   2451     static final int SCROLL_INDICATORS_NONE = 0x0000;
   2452 
   2453     /**
   2454      * Mask for use with setFlags indicating bits used for indicating which
   2455      * scroll indicators are enabled.
   2456      */
   2457     static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
   2458             | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
   2459             | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
   2460             | PFLAG3_SCROLL_INDICATOR_END;
   2461 
   2462     /**
   2463      * Left-shift required to translate between public scroll indicator flags
   2464      * and internal PFLAGS3 flags. When used as a right-shift, translates
   2465      * PFLAGS3 flags to public flags.
   2466      */
   2467     static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
   2468 
   2469     /** @hide */
   2470     @Retention(RetentionPolicy.SOURCE)
   2471     @IntDef(flag = true,
   2472             value = {
   2473                     SCROLL_INDICATOR_TOP,
   2474                     SCROLL_INDICATOR_BOTTOM,
   2475                     SCROLL_INDICATOR_LEFT,
   2476                     SCROLL_INDICATOR_RIGHT,
   2477                     SCROLL_INDICATOR_START,
   2478                     SCROLL_INDICATOR_END,
   2479             })
   2480     public @interface ScrollIndicators {}
   2481 
   2482     /**
   2483      * Scroll indicator direction for the top edge of the view.
   2484      *
   2485      * @see #setScrollIndicators(int)
   2486      * @see #setScrollIndicators(int, int)
   2487      * @see #getScrollIndicators()
   2488      */
   2489     public static final int SCROLL_INDICATOR_TOP =
   2490             PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   2491 
   2492     /**
   2493      * Scroll indicator direction for the bottom edge of the view.
   2494      *
   2495      * @see #setScrollIndicators(int)
   2496      * @see #setScrollIndicators(int, int)
   2497      * @see #getScrollIndicators()
   2498      */
   2499     public static final int SCROLL_INDICATOR_BOTTOM =
   2500             PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   2501 
   2502     /**
   2503      * Scroll indicator direction for the left edge of the view.
   2504      *
   2505      * @see #setScrollIndicators(int)
   2506      * @see #setScrollIndicators(int, int)
   2507      * @see #getScrollIndicators()
   2508      */
   2509     public static final int SCROLL_INDICATOR_LEFT =
   2510             PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   2511 
   2512     /**
   2513      * Scroll indicator direction for the right edge of the view.
   2514      *
   2515      * @see #setScrollIndicators(int)
   2516      * @see #setScrollIndicators(int, int)
   2517      * @see #getScrollIndicators()
   2518      */
   2519     public static final int SCROLL_INDICATOR_RIGHT =
   2520             PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   2521 
   2522     /**
   2523      * Scroll indicator direction for the starting edge of the view.
   2524      * <p>
   2525      * Resolved according to the view's layout direction, see
   2526      * {@link #getLayoutDirection()} for more information.
   2527      *
   2528      * @see #setScrollIndicators(int)
   2529      * @see #setScrollIndicators(int, int)
   2530      * @see #getScrollIndicators()
   2531      */
   2532     public static final int SCROLL_INDICATOR_START =
   2533             PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   2534 
   2535     /**
   2536      * Scroll indicator direction for the ending edge of the view.
   2537      * <p>
   2538      * Resolved according to the view's layout direction, see
   2539      * {@link #getLayoutDirection()} for more information.
   2540      *
   2541      * @see #setScrollIndicators(int)
   2542      * @see #setScrollIndicators(int, int)
   2543      * @see #getScrollIndicators()
   2544      */
   2545     public static final int SCROLL_INDICATOR_END =
   2546             PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   2547 
   2548     /**
   2549      * <p>Indicates that we are allowing {@link ViewStructure} to traverse
   2550      * into this view.<p>
   2551      */
   2552     static final int PFLAG3_ASSIST_BLOCKED = 0x100;
   2553 
   2554     /**
   2555      * Always allow a user to over-scroll this view, provided it is a
   2556      * view that can scroll.
   2557      *
   2558      * @see #getOverScrollMode()
   2559      * @see #setOverScrollMode(int)
   2560      */
   2561     public static final int OVER_SCROLL_ALWAYS = 0;
   2562 
   2563     /**
   2564      * Allow a user to over-scroll this view only if the content is large
   2565      * enough to meaningfully scroll, provided it is a view that can scroll.
   2566      *
   2567      * @see #getOverScrollMode()
   2568      * @see #setOverScrollMode(int)
   2569      */
   2570     public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
   2571 
   2572     /**
   2573      * Never allow a user to over-scroll this view.
   2574      *
   2575      * @see #getOverScrollMode()
   2576      * @see #setOverScrollMode(int)
   2577      */
   2578     public static final int OVER_SCROLL_NEVER = 2;
   2579 
   2580     /**
   2581      * Special constant for {@link #setSystemUiVisibility(int)}: View has
   2582      * requested the system UI (status bar) to be visible (the default).
   2583      *
   2584      * @see #setSystemUiVisibility(int)
   2585      */
   2586     public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
   2587 
   2588     /**
   2589      * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
   2590      * system UI to enter an unobtrusive "low profile" mode.
   2591      *
   2592      * <p>This is for use in games, book readers, video players, or any other
   2593      * "immersive" application where the usual system chrome is deemed too distracting.
   2594      *
   2595      * <p>In low profile mode, the status bar and/or navigation icons may dim.
   2596      *
   2597      * @see #setSystemUiVisibility(int)
   2598      */
   2599     public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
   2600 
   2601     /**
   2602      * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
   2603      * system navigation be temporarily hidden.
   2604      *
   2605      * <p>This is an even less obtrusive state than that called for by
   2606      * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
   2607      * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
   2608      * those to disappear. This is useful (in conjunction with the
   2609      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
   2610      * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
   2611      * window flags) for displaying content using every last pixel on the display.
   2612      *
   2613      * <p>There is a limitation: because navigation controls are so important, the least user
   2614      * interaction will cause them to reappear immediately.  When this happens, both
   2615      * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
   2616      * so that both elements reappear at the same time.
   2617      *
   2618      * @see #setSystemUiVisibility(int)
   2619      */
   2620     public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
   2621 
   2622     /**
   2623      * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
   2624      * into the normal fullscreen mode so that its content can take over the screen
   2625      * while still allowing the user to interact with the application.
   2626      *
   2627      * <p>This has the same visual effect as
   2628      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
   2629      * WindowManager.LayoutParams.FLAG_FULLSCREEN},
   2630      * meaning that non-critical screen decorations (such as the status bar) will be
   2631      * hidden while the user is in the View's window, focusing the experience on
   2632      * that content.  Unlike the window flag, if you are using ActionBar in
   2633      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
   2634      * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
   2635      * hide the action bar.
   2636      *
   2637      * <p>This approach to going fullscreen is best used over the window flag when
   2638      * it is a transient state -- that is, the application does this at certain
   2639      * points in its user interaction where it wants to allow the user to focus
   2640      * on content, but not as a continuous state.  For situations where the application
   2641      * would like to simply stay full screen the entire time (such as a game that
   2642      * wants to take over the screen), the
   2643      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
   2644      * is usually a better approach.  The state set here will be removed by the system
   2645      * in various situations (such as the user moving to another application) like
   2646      * the other system UI states.
   2647      *
   2648      * <p>When using this flag, the application should provide some easy facility
   2649      * for the user to go out of it.  A common example would be in an e-book
   2650      * reader, where tapping on the screen brings back whatever screen and UI
   2651      * decorations that had been hidden while the user was immersed in reading
   2652      * the book.
   2653      *
   2654      * @see #setSystemUiVisibility(int)
   2655      */
   2656     public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
   2657 
   2658     /**
   2659      * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
   2660      * flags, we would like a stable view of the content insets given to
   2661      * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
   2662      * will always represent the worst case that the application can expect
   2663      * as a continuous state.  In the stock Android UI this is the space for
   2664      * the system bar, nav bar, and status bar, but not more transient elements
   2665      * such as an input method.
   2666      *
   2667      * The stable layout your UI sees is based on the system UI modes you can
   2668      * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
   2669      * then you will get a stable layout for changes of the
   2670      * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
   2671      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
   2672      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
   2673      * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
   2674      * with a stable layout.  (Note that you should avoid using
   2675      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
   2676      *
   2677      * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
   2678      * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
   2679      * then a hidden status bar will be considered a "stable" state for purposes
   2680      * here.  This allows your UI to continually hide the status bar, while still
   2681      * using the system UI flags to hide the action bar while still retaining
   2682      * a stable layout.  Note that changing the window fullscreen flag will never
   2683      * provide a stable layout for a clean transition.
   2684      *
   2685      * <p>If you are using ActionBar in
   2686      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
   2687      * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
   2688      * insets it adds to those given to the application.
   2689      */
   2690     public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
   2691 
   2692     /**
   2693      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
   2694      * to be laid out as if it has requested
   2695      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
   2696      * allows it to avoid artifacts when switching in and out of that mode, at
   2697      * the expense that some of its user interface may be covered by screen
   2698      * decorations when they are shown.  You can perform layout of your inner
   2699      * UI elements to account for the navigation system UI through the
   2700      * {@link #fitSystemWindows(Rect)} method.
   2701      */
   2702     public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
   2703 
   2704     /**
   2705      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
   2706      * to be laid out as if it has requested
   2707      * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
   2708      * allows it to avoid artifacts when switching in and out of that mode, at
   2709      * the expense that some of its user interface may be covered by screen
   2710      * decorations when they are shown.  You can perform layout of your inner
   2711      * UI elements to account for non-fullscreen system UI through the
   2712      * {@link #fitSystemWindows(Rect)} method.
   2713      */
   2714     public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
   2715 
   2716     /**
   2717      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
   2718      * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
   2719      * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
   2720      * user interaction.
   2721      * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
   2722      * has an effect when used in combination with that flag.</p>
   2723      */
   2724     public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
   2725 
   2726     /**
   2727      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
   2728      * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
   2729      * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
   2730      * experience while also hiding the system bars.  If this flag is not set,
   2731      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
   2732      * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
   2733      * if the user swipes from the top of the screen.
   2734      * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
   2735      * system gestures, such as swiping from the top of the screen.  These transient system bars
   2736      * will overlay apps content, may have some degree of transparency, and will automatically
   2737      * hide after a short timeout.
   2738      * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
   2739      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
   2740      * with one or both of those flags.</p>
   2741      */
   2742     public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
   2743 
   2744     /**
   2745      * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
   2746      * is compatible with light status bar backgrounds.
   2747      *
   2748      * <p>For this to take effect, the window must request
   2749      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
   2750      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
   2751      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
   2752      *         FLAG_TRANSLUCENT_STATUS}.
   2753      *
   2754      * @see android.R.attr#windowLightStatusBar
   2755      */
   2756     public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
   2757 
   2758     /**
   2759      * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
   2760      */
   2761     public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
   2762 
   2763     /**
   2764      * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
   2765      */
   2766     public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
   2767 
   2768     /**
   2769      * @hide
   2770      *
   2771      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   2772      * out of the public fields to keep the undefined bits out of the developer's way.
   2773      *
   2774      * Flag to make the status bar not expandable.  Unless you also
   2775      * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
   2776      */
   2777     public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
   2778 
   2779     /**
   2780      * @hide
   2781      *
   2782      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   2783      * out of the public fields to keep the undefined bits out of the developer's way.
   2784      *
   2785      * Flag to hide notification icons and scrolling ticker text.
   2786      */
   2787     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
   2788 
   2789     /**
   2790      * @hide
   2791      *
   2792      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   2793      * out of the public fields to keep the undefined bits out of the developer's way.
   2794      *
   2795      * Flag to disable incoming notification alerts.  This will not block
   2796      * icons, but it will block sound, vibrating and other visual or aural notifications.
   2797      */
   2798     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
   2799 
   2800     /**
   2801      * @hide
   2802      *
   2803      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   2804      * out of the public fields to keep the undefined bits out of the developer's way.
   2805      *
   2806      * Flag to hide only the scrolling ticker.  Note that
   2807      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
   2808      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
   2809      */
   2810     public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
   2811 
   2812     /**
   2813      * @hide
   2814      *
   2815      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   2816      * out of the public fields to keep the undefined bits out of the developer's way.
   2817      *
   2818      * Flag to hide the center system info area.
   2819      */
   2820     public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
   2821 
   2822     /**
   2823      * @hide
   2824      *
   2825      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   2826      * out of the public fields to keep the undefined bits out of the developer's way.
   2827      *
   2828      * Flag to hide only the home button.  Don't use this
   2829      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
   2830      */
   2831     public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
   2832 
   2833     /**
   2834      * @hide
   2835      *
   2836      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   2837      * out of the public fields to keep the undefined bits out of the developer's way.
   2838      *
   2839      * Flag to hide only the back button. Don't use this
   2840      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
   2841      */
   2842     public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
   2843 
   2844     /**
   2845      * @hide
   2846      *
   2847      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   2848      * out of the public fields to keep the undefined bits out of the developer's way.
   2849      *
   2850      * Flag to hide only the clock.  You might use this if your activity has
   2851      * its own clock making the status bar's clock redundant.
   2852      */
   2853     public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
   2854 
   2855     /**
   2856      * @hide
   2857      *
   2858      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   2859      * out of the public fields to keep the undefined bits out of the developer's way.
   2860      *
   2861      * Flag to hide only the recent apps button. Don't use this
   2862      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
   2863      */
   2864     public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
   2865 
   2866     /**
   2867      * @hide
   2868      *
   2869      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   2870      * out of the public fields to keep the undefined bits out of the developer's way.
   2871      *
   2872      * Flag to disable the global search gesture. Don't use this
   2873      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
   2874      */
   2875     public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
   2876 
   2877     /**
   2878      * @hide
   2879      *
   2880      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   2881      * out of the public fields to keep the undefined bits out of the developer's way.
   2882      *
   2883      * Flag to specify that the status bar is displayed in transient mode.
   2884      */
   2885     public static final int STATUS_BAR_TRANSIENT = 0x04000000;
   2886 
   2887     /**
   2888      * @hide
   2889      *
   2890      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   2891      * out of the public fields to keep the undefined bits out of the developer's way.
   2892      *
   2893      * Flag to specify that the navigation bar is displayed in transient mode.
   2894      */
   2895     public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
   2896 
   2897     /**
   2898      * @hide
   2899      *
   2900      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   2901      * out of the public fields to keep the undefined bits out of the developer's way.
   2902      *
   2903      * Flag to specify that the hidden status bar would like to be shown.
   2904      */
   2905     public static final int STATUS_BAR_UNHIDE = 0x10000000;
   2906 
   2907     /**
   2908      * @hide
   2909      *
   2910      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   2911      * out of the public fields to keep the undefined bits out of the developer's way.
   2912      *
   2913      * Flag to specify that the hidden navigation bar would like to be shown.
   2914      */
   2915     public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
   2916 
   2917     /**
   2918      * @hide
   2919      *
   2920      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   2921      * out of the public fields to keep the undefined bits out of the developer's way.
   2922      *
   2923      * Flag to specify that the status bar is displayed in translucent mode.
   2924      */
   2925     public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
   2926 
   2927     /**
   2928      * @hide
   2929      *
   2930      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
   2931      * out of the public fields to keep the undefined bits out of the developer's way.
   2932      *
   2933      * Flag to specify that the navigation bar is displayed in translucent mode.
   2934      */
   2935     public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
   2936 
   2937     /**
   2938      * @hide
   2939      *
   2940      * Whether Recents is visible or not.
   2941      */
   2942     public static final int RECENT_APPS_VISIBLE = 0x00004000;
   2943 
   2944     /**
   2945      * @hide
   2946      *
   2947      * Makes system ui transparent.
   2948      */
   2949     public static final int SYSTEM_UI_TRANSPARENT = 0x00008000;
   2950 
   2951     /**
   2952      * @hide
   2953      */
   2954     public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FFF;
   2955 
   2956     /**
   2957      * These are the system UI flags that can be cleared by events outside
   2958      * of an application.  Currently this is just the ability to tap on the
   2959      * screen while hiding the navigation bar to have it return.
   2960      * @hide
   2961      */
   2962     public static final int SYSTEM_UI_CLEARABLE_FLAGS =
   2963             SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
   2964             | SYSTEM_UI_FLAG_FULLSCREEN;
   2965 
   2966     /**
   2967      * Flags that can impact the layout in relation to system UI.
   2968      */
   2969     public static final int SYSTEM_UI_LAYOUT_FLAGS =
   2970             SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
   2971             | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
   2972 
   2973     /** @hide */
   2974     @IntDef(flag = true,
   2975             value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
   2976     @Retention(RetentionPolicy.SOURCE)
   2977     public @interface FindViewFlags {}
   2978 
   2979     /**
   2980      * Find views that render the specified text.
   2981      *
   2982      * @see #findViewsWithText(ArrayList, CharSequence, int)
   2983      */
   2984     public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
   2985 
   2986     /**
   2987      * Find find views that contain the specified content description.
   2988      *
   2989      * @see #findViewsWithText(ArrayList, CharSequence, int)
   2990      */
   2991     public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
   2992 
   2993     /**
   2994      * Find views that contain {@link AccessibilityNodeProvider}. Such
   2995      * a View is a root of virtual view hierarchy and may contain the searched
   2996      * text. If this flag is set Views with providers are automatically
   2997      * added and it is a responsibility of the client to call the APIs of
   2998      * the provider to determine whether the virtual tree rooted at this View
   2999      * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
   3000      * representing the virtual views with this text.
   3001      *
   3002      * @see #findViewsWithText(ArrayList, CharSequence, int)
   3003      *
   3004      * @hide
   3005      */
   3006     public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
   3007 
   3008     /**
   3009      * The undefined cursor position.
   3010      *
   3011      * @hide
   3012      */
   3013     public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
   3014 
   3015     /**
   3016      * Indicates that the screen has changed state and is now off.
   3017      *
   3018      * @see #onScreenStateChanged(int)
   3019      */
   3020     public static final int SCREEN_STATE_OFF = 0x0;
   3021 
   3022     /**
   3023      * Indicates that the screen has changed state and is now on.
   3024      *
   3025      * @see #onScreenStateChanged(int)
   3026      */
   3027     public static final int SCREEN_STATE_ON = 0x1;
   3028 
   3029     /**
   3030      * Indicates no axis of view scrolling.
   3031      */
   3032     public static final int SCROLL_AXIS_NONE = 0;
   3033 
   3034     /**
   3035      * Indicates scrolling along the horizontal axis.
   3036      */
   3037     public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
   3038 
   3039     /**
   3040      * Indicates scrolling along the vertical axis.
   3041      */
   3042     public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
   3043 
   3044     /**
   3045      * Controls the over-scroll mode for this view.
   3046      * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
   3047      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
   3048      * and {@link #OVER_SCROLL_NEVER}.
   3049      */
   3050     private int mOverScrollMode;
   3051 
   3052     /**
   3053      * The parent this view is attached to.
   3054      * {@hide}
   3055      *
   3056      * @see #getParent()
   3057      */
   3058     protected ViewParent mParent;
   3059 
   3060     /**
   3061      * {@hide}
   3062      */
   3063     AttachInfo mAttachInfo;
   3064 
   3065     /**
   3066      * {@hide}
   3067      */
   3068     @ViewDebug.ExportedProperty(flagMapping = {
   3069         @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
   3070                 name = "FORCE_LAYOUT"),
   3071         @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
   3072                 name = "LAYOUT_REQUIRED"),
   3073         @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
   3074             name = "DRAWING_CACHE_INVALID", outputIf = false),
   3075         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
   3076         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
   3077         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
   3078         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
   3079     }, formatToHexString = true)
   3080     int mPrivateFlags;
   3081     int mPrivateFlags2;
   3082     int mPrivateFlags3;
   3083 
   3084     /**
   3085      * This view's request for the visibility of the status bar.
   3086      * @hide
   3087      */
   3088     @ViewDebug.ExportedProperty(flagMapping = {
   3089         @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
   3090                                 equals = SYSTEM_UI_FLAG_LOW_PROFILE,
   3091                                 name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
   3092         @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
   3093                                 equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
   3094                                 name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
   3095         @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
   3096                                 equals = SYSTEM_UI_FLAG_VISIBLE,
   3097                                 name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
   3098     }, formatToHexString = true)
   3099     int mSystemUiVisibility;
   3100 
   3101     /**
   3102      * Reference count for transient state.
   3103      * @see #setHasTransientState(boolean)
   3104      */
   3105     int mTransientStateCount = 0;
   3106 
   3107     /**
   3108      * Count of how many windows this view has been attached to.
   3109      */
   3110     int mWindowAttachCount;
   3111 
   3112     /**
   3113      * The layout parameters associated with this view and used by the parent
   3114      * {@link android.view.ViewGroup} to determine how this view should be
   3115      * laid out.
   3116      * {@hide}
   3117      */
   3118     protected ViewGroup.LayoutParams mLayoutParams;
   3119 
   3120     /**
   3121      * The view flags hold various views states.
   3122      * {@hide}
   3123      */
   3124     @ViewDebug.ExportedProperty(formatToHexString = true)
   3125     int mViewFlags;
   3126 
   3127     static class TransformationInfo {
   3128         /**
   3129          * The transform matrix for the View. This transform is calculated internally
   3130          * based on the translation, rotation, and scale properties.
   3131          *
   3132          * Do *not* use this variable directly; instead call getMatrix(), which will
   3133          * load the value from the View's RenderNode.
   3134          */
   3135         private final Matrix mMatrix = new Matrix();
   3136 
   3137         /**
   3138          * The inverse transform matrix for the View. This transform is calculated
   3139          * internally based on the translation, rotation, and scale properties.
   3140          *
   3141          * Do *not* use this variable directly; instead call getInverseMatrix(),
   3142          * which will load the value from the View's RenderNode.
   3143          */
   3144         private Matrix mInverseMatrix;
   3145 
   3146         /**
   3147          * The opacity of the View. This is a value from 0 to 1, where 0 means
   3148          * completely transparent and 1 means completely opaque.
   3149          */
   3150         @ViewDebug.ExportedProperty
   3151         float mAlpha = 1f;
   3152 
   3153         /**
   3154          * The opacity of the view as manipulated by the Fade transition. This is a hidden
   3155          * property only used by transitions, which is composited with the other alpha
   3156          * values to calculate the final visual alpha value.
   3157          */
   3158         float mTransitionAlpha = 1f;
   3159     }
   3160 
   3161     TransformationInfo mTransformationInfo;
   3162 
   3163     /**
   3164      * Current clip bounds. to which all drawing of this view are constrained.
   3165      */
   3166     Rect mClipBounds = null;
   3167 
   3168     private boolean mLastIsOpaque;
   3169 
   3170     /**
   3171      * The distance in pixels from the left edge of this view's parent
   3172      * to the left edge of this view.
   3173      * {@hide}
   3174      */
   3175     @ViewDebug.ExportedProperty(category = "layout")
   3176     protected int mLeft;
   3177     /**
   3178      * The distance in pixels from the left edge of this view's parent
   3179      * to the right edge of this view.
   3180      * {@hide}
   3181      */
   3182     @ViewDebug.ExportedProperty(category = "layout")
   3183     protected int mRight;
   3184     /**
   3185      * The distance in pixels from the top edge of this view's parent
   3186      * to the top edge of this view.
   3187      * {@hide}
   3188      */
   3189     @ViewDebug.ExportedProperty(category = "layout")
   3190     protected int mTop;
   3191     /**
   3192      * The distance in pixels from the top edge of this view's parent
   3193      * to the bottom edge of this view.
   3194      * {@hide}
   3195      */
   3196     @ViewDebug.ExportedProperty(category = "layout")
   3197     protected int mBottom;
   3198 
   3199     /**
   3200      * The offset, in pixels, by which the content of this view is scrolled
   3201      * horizontally.
   3202      * {@hide}
   3203      */
   3204     @ViewDebug.ExportedProperty(category = "scrolling")
   3205     protected int mScrollX;
   3206     /**
   3207      * The offset, in pixels, by which the content of this view is scrolled
   3208      * vertically.
   3209      * {@hide}
   3210      */
   3211     @ViewDebug.ExportedProperty(category = "scrolling")
   3212     protected int mScrollY;
   3213 
   3214     /**
   3215      * The left padding in pixels, that is the distance in pixels between the
   3216      * left edge of this view and the left edge of its content.
   3217      * {@hide}
   3218      */
   3219     @ViewDebug.ExportedProperty(category = "padding")
   3220     protected int mPaddingLeft = 0;
   3221     /**
   3222      * The right padding in pixels, that is the distance in pixels between the
   3223      * right edge of this view and the right edge of its content.
   3224      * {@hide}
   3225      */
   3226     @ViewDebug.ExportedProperty(category = "padding")
   3227     protected int mPaddingRight = 0;
   3228     /**
   3229      * The top padding in pixels, that is the distance in pixels between the
   3230      * top edge of this view and the top edge of its content.
   3231      * {@hide}
   3232      */
   3233     @ViewDebug.ExportedProperty(category = "padding")
   3234     protected int mPaddingTop;
   3235     /**
   3236      * The bottom padding in pixels, that is the distance in pixels between the
   3237      * bottom edge of this view and the bottom edge of its content.
   3238      * {@hide}
   3239      */
   3240     @ViewDebug.ExportedProperty(category = "padding")
   3241     protected int mPaddingBottom;
   3242 
   3243     /**
   3244      * The layout insets in pixels, that is the distance in pixels between the
   3245      * visible edges of this view its bounds.
   3246      */
   3247     private Insets mLayoutInsets;
   3248 
   3249     /**
   3250      * Briefly describes the view and is primarily used for accessibility support.
   3251      */
   3252     private CharSequence mContentDescription;
   3253 
   3254     /**
   3255      * Specifies the id of a view for which this view serves as a label for
   3256      * accessibility purposes.
   3257      */
   3258     private int mLabelForId = View.NO_ID;
   3259 
   3260     /**
   3261      * Predicate for matching labeled view id with its label for
   3262      * accessibility purposes.
   3263      */
   3264     private MatchLabelForPredicate mMatchLabelForPredicate;
   3265 
   3266     /**
   3267      * Specifies a view before which this one is visited in accessibility traversal.
   3268      */
   3269     private int mAccessibilityTraversalBeforeId = NO_ID;
   3270 
   3271     /**
   3272      * Specifies a view after which this one is visited in accessibility traversal.
   3273      */
   3274     private int mAccessibilityTraversalAfterId = NO_ID;
   3275 
   3276     /**
   3277      * Predicate for matching a view by its id.
   3278      */
   3279     private MatchIdPredicate mMatchIdPredicate;
   3280 
   3281     /**
   3282      * Cache the paddingRight set by the user to append to the scrollbar's size.
   3283      *
   3284      * @hide
   3285      */
   3286     @ViewDebug.ExportedProperty(category = "padding")
   3287     protected int mUserPaddingRight;
   3288 
   3289     /**
   3290      * Cache the paddingBottom set by the user to append to the scrollbar's size.
   3291      *
   3292      * @hide
   3293      */
   3294     @ViewDebug.ExportedProperty(category = "padding")
   3295     protected int mUserPaddingBottom;
   3296 
   3297     /**
   3298      * Cache the paddingLeft set by the user to append to the scrollbar's size.
   3299      *
   3300      * @hide
   3301      */
   3302     @ViewDebug.ExportedProperty(category = "padding")
   3303     protected int mUserPaddingLeft;
   3304 
   3305     /**
   3306      * Cache the paddingStart set by the user to append to the scrollbar's size.
   3307      *
   3308      */
   3309     @ViewDebug.ExportedProperty(category = "padding")
   3310     int mUserPaddingStart;
   3311 
   3312     /**
   3313      * Cache the paddingEnd set by the user to append to the scrollbar's size.
   3314      *
   3315      */
   3316     @ViewDebug.ExportedProperty(category = "padding")
   3317     int mUserPaddingEnd;
   3318 
   3319     /**
   3320      * Cache initial left padding.
   3321      *
   3322      * @hide
   3323      */
   3324     int mUserPaddingLeftInitial;
   3325 
   3326     /**
   3327      * Cache initial right padding.
   3328      *
   3329      * @hide
   3330      */
   3331     int mUserPaddingRightInitial;
   3332 
   3333     /**
   3334      * Default undefined padding
   3335      */
   3336     private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
   3337 
   3338     /**
   3339      * Cache if a left padding has been defined
   3340      */
   3341     private boolean mLeftPaddingDefined = false;
   3342 
   3343     /**
   3344      * Cache if a right padding has been defined
   3345      */
   3346     private boolean mRightPaddingDefined = false;
   3347 
   3348     /**
   3349      * @hide
   3350      */
   3351     int mOldWidthMeasureSpec = Integer.MIN_VALUE;
   3352     /**
   3353      * @hide
   3354      */
   3355     int mOldHeightMeasureSpec = Integer.MIN_VALUE;
   3356 
   3357     private LongSparseLongArray mMeasureCache;
   3358 
   3359     @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
   3360     private Drawable mBackground;
   3361     private TintInfo mBackgroundTint;
   3362 
   3363     @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
   3364     private ForegroundInfo mForegroundInfo;
   3365 
   3366     private Drawable mScrollIndicatorDrawable;
   3367 
   3368     /**
   3369      * RenderNode used for backgrounds.
   3370      * <p>
   3371      * When non-null and valid, this is expected to contain an up-to-date copy
   3372      * of the background drawable. It is cleared on temporary detach, and reset
   3373      * on cleanup.
   3374      */
   3375     private RenderNode mBackgroundRenderNode;
   3376 
   3377     private int mBackgroundResource;
   3378     private boolean mBackgroundSizeChanged;
   3379 
   3380     private String mTransitionName;
   3381 
   3382     static class TintInfo {
   3383         ColorStateList mTintList;
   3384         PorterDuff.Mode mTintMode;
   3385         boolean mHasTintMode;
   3386         boolean mHasTintList;
   3387     }
   3388 
   3389     private static class ForegroundInfo {
   3390         private Drawable mDrawable;
   3391         private TintInfo mTintInfo;
   3392         private int mGravity = Gravity.FILL;
   3393         private boolean mInsidePadding = true;
   3394         private boolean mBoundsChanged = true;
   3395         private final Rect mSelfBounds = new Rect();
   3396         private final Rect mOverlayBounds = new Rect();
   3397     }
   3398 
   3399     static class ListenerInfo {
   3400         /**
   3401          * Listener used to dispatch focus change events.
   3402          * This field should be made private, so it is hidden from the SDK.
   3403          * {@hide}
   3404          */
   3405         protected OnFocusChangeListener mOnFocusChangeListener;
   3406 
   3407         /**
   3408          * Listeners for layout change events.
   3409          */
   3410         private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
   3411 
   3412         protected OnScrollChangeListener mOnScrollChangeListener;
   3413 
   3414         /**
   3415          * Listeners for attach events.
   3416          */
   3417         private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
   3418 
   3419         /**
   3420          * Listener used to dispatch click events.
   3421          * This field should be made private, so it is hidden from the SDK.
   3422          * {@hide}
   3423          */
   3424         public OnClickListener mOnClickListener;
   3425 
   3426         /**
   3427          * Listener used to dispatch long click events.
   3428          * This field should be made private, so it is hidden from the SDK.
   3429          * {@hide}
   3430          */
   3431         protected OnLongClickListener mOnLongClickListener;
   3432 
   3433         /**
   3434          * Listener used to dispatch context click events. This field should be made private, so it
   3435          * is hidden from the SDK.
   3436          * {@hide}
   3437          */
   3438         protected OnContextClickListener mOnContextClickListener;
   3439 
   3440         /**
   3441          * Listener used to build the context menu.
   3442          * This field should be made private, so it is hidden from the SDK.
   3443          * {@hide}
   3444          */
   3445         protected OnCreateContextMenuListener mOnCreateContextMenuListener;
   3446 
   3447         private OnKeyListener mOnKeyListener;
   3448 
   3449         private OnTouchListener mOnTouchListener;
   3450 
   3451         private OnHoverListener mOnHoverListener;
   3452 
   3453         private OnGenericMotionListener mOnGenericMotionListener;
   3454 
   3455         private OnDragListener mOnDragListener;
   3456 
   3457         private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
   3458 
   3459         OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
   3460     }
   3461 
   3462     ListenerInfo mListenerInfo;
   3463 
   3464     /**
   3465      * The application environment this view lives in.
   3466      * This field should be made private, so it is hidden from the SDK.
   3467      * {@hide}
   3468      */
   3469     @ViewDebug.ExportedProperty(deepExport = true)
   3470     protected Context mContext;
   3471 
   3472     private final Resources mResources;
   3473 
   3474     private ScrollabilityCache mScrollCache;
   3475 
   3476     private int[] mDrawableState = null;
   3477 
   3478     ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
   3479 
   3480     /**
   3481      * Animator that automatically runs based on state changes.
   3482      */
   3483     private StateListAnimator mStateListAnimator;
   3484 
   3485     /**
   3486      * When this view has focus and the next focus is {@link #FOCUS_LEFT},
   3487      * the user may specify which view to go to next.
   3488      */
   3489     private int mNextFocusLeftId = View.NO_ID;
   3490 
   3491     /**
   3492      * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
   3493      * the user may specify which view to go to next.
   3494      */
   3495     private int mNextFocusRightId = View.NO_ID;
   3496 
   3497     /**
   3498      * When this view has focus and the next focus is {@link #FOCUS_UP},
   3499      * the user may specify which view to go to next.
   3500      */
   3501     private int mNextFocusUpId = View.NO_ID;
   3502 
   3503     /**
   3504      * When this view has focus and the next focus is {@link #FOCUS_DOWN},
   3505      * the user may specify which view to go to next.
   3506      */
   3507     private int mNextFocusDownId = View.NO_ID;
   3508 
   3509     /**
   3510      * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
   3511      * the user may specify which view to go to next.
   3512      */
   3513     int mNextFocusForwardId = View.NO_ID;
   3514 
   3515     private CheckForLongPress mPendingCheckForLongPress;
   3516     private CheckForTap mPendingCheckForTap = null;
   3517     private PerformClick mPerformClick;
   3518     private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
   3519 
   3520     private UnsetPressedState mUnsetPressedState;
   3521 
   3522     /**
   3523      * Whether the long press's action has been invoked.  The tap's action is invoked on the
   3524      * up event while a long press is invoked as soon as the long press duration is reached, so
   3525      * a long press could be performed before the tap is checked, in which case the tap's action
   3526      * should not be invoked.
   3527      */
   3528     private boolean mHasPerformedLongPress;
   3529 
   3530     /**
   3531      * Whether a context click button is currently pressed down. This is true when the stylus is
   3532      * touching the screen and the primary button has been pressed, or if a mouse's right button is
   3533      * pressed. This is false once the button is released or if the stylus has been lifted.
   3534      */
   3535     private boolean mInContextButtonPress;
   3536 
   3537     /**
   3538      * Whether the next up event should be ignored for the purposes of gesture recognition. This is
   3539      * true after a stylus button press has occured, when the next up event should not be recognized
   3540      * as a tap.
   3541      */
   3542     private boolean mIgnoreNextUpEvent;
   3543 
   3544     /**
   3545      * The minimum height of the view. We'll try our best to have the height
   3546      * of this view to at least this amount.
   3547      */
   3548     @ViewDebug.ExportedProperty(category = "measurement")
   3549     private int mMinHeight;
   3550 
   3551     /**
   3552      * The minimum width of the view. We'll try our best to have the width
   3553      * of this view to at least this amount.
   3554      */
   3555     @ViewDebug.ExportedProperty(category = "measurement")
   3556     private int mMinWidth;
   3557 
   3558     /**
   3559      * The delegate to handle touch events that are physically in this view
   3560      * but should be handled by another view.
   3561      */
   3562     private TouchDelegate mTouchDelegate = null;
   3563 
   3564     /**
   3565      * Solid color to use as a background when creating the drawing cache. Enables
   3566      * the cache to use 16 bit bitmaps instead of 32 bit.
   3567      */
   3568     private int mDrawingCacheBackgroundColor = 0;
   3569 
   3570     /**
   3571      * Special tree observer used when mAttachInfo is null.
   3572      */
   3573     private ViewTreeObserver mFloatingTreeObserver;
   3574 
   3575     /**
   3576      * Cache the touch slop from the context that created the view.
   3577      */
   3578     private int mTouchSlop;
   3579 
   3580     /**
   3581      * Object that handles automatic animation of view properties.
   3582      */
   3583     private ViewPropertyAnimator mAnimator = null;
   3584 
   3585     /**
   3586      * Flag indicating that a drag can cross window boundaries.  When
   3587      * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
   3588      * with this flag set, all visible applications will be able to participate
   3589      * in the drag operation and receive the dragged content.
   3590      *
   3591      * @hide
   3592      */
   3593     public static final int DRAG_FLAG_GLOBAL = 1;
   3594 
   3595     /**
   3596      * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
   3597      */
   3598     private float mVerticalScrollFactor;
   3599 
   3600     /**
   3601      * Position of the vertical scroll bar.
   3602      */
   3603     private int mVerticalScrollbarPosition;
   3604 
   3605     /**
   3606      * Position the scroll bar at the default position as determined by the system.
   3607      */
   3608     public static final int SCROLLBAR_POSITION_DEFAULT = 0;
   3609 
   3610     /**
   3611      * Position the scroll bar along the left edge.
   3612      */
   3613     public static final int SCROLLBAR_POSITION_LEFT = 1;
   3614 
   3615     /**
   3616      * Position the scroll bar along the right edge.
   3617      */
   3618     public static final int SCROLLBAR_POSITION_RIGHT = 2;
   3619 
   3620     /**
   3621      * Indicates that the view does not have a layer.
   3622      *
   3623      * @see #getLayerType()
   3624      * @see #setLayerType(int, android.graphics.Paint)
   3625      * @see #LAYER_TYPE_SOFTWARE
   3626      * @see #LAYER_TYPE_HARDWARE
   3627      */
   3628     public static final int LAYER_TYPE_NONE = 0;
   3629 
   3630     /**
   3631      * <p>Indicates that the view has a software layer. A software layer is backed
   3632      * by a bitmap and causes the view to be rendered using Android's software
   3633      * rendering pipeline, even if hardware acceleration is enabled.</p>
   3634      *
   3635      * <p>Software layers have various usages:</p>
   3636      * <p>When the application is not using hardware acceleration, a software layer
   3637      * is useful to apply a specific color filter and/or blending mode and/or
   3638      * translucency to a view and all its children.</p>
   3639      * <p>When the application is using hardware acceleration, a software layer
   3640      * is useful to render drawing primitives not supported by the hardware
   3641      * accelerated pipeline. It can also be used to cache a complex view tree
   3642      * into a texture and reduce the complexity of drawing operations. For instance,
   3643      * when animating a complex view tree with a translation, a software layer can
   3644      * be used to render the view tree only once.</p>
   3645      * <p>Software layers should be avoided when the affected view tree updates
   3646      * often. Every update will require to re-render the software layer, which can
   3647      * potentially be slow (particularly when hardware acceleration is turned on
   3648      * since the layer will have to be uploaded into a hardware texture after every
   3649      * update.)</p>
   3650      *
   3651      * @see #getLayerType()
   3652      * @see #setLayerType(int, android.graphics.Paint)
   3653      * @see #LAYER_TYPE_NONE
   3654      * @see #LAYER_TYPE_HARDWARE
   3655      */
   3656     public static final int LAYER_TYPE_SOFTWARE = 1;
   3657 
   3658     /**
   3659      * <p>Indicates that the view has a hardware layer. A hardware layer is backed
   3660      * by a hardware specific texture (generally Frame Buffer Objects or FBO on
   3661      * OpenGL hardware) and causes the view to be rendered using Android's hardware
   3662      * rendering pipeline, but only if hardware acceleration is turned on for the
   3663      * view hierarchy. When hardware acceleration is turned off, hardware layers
   3664      * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
   3665      *
   3666      * <p>A hardware layer is useful to apply a specific color filter and/or
   3667      * blending mode and/or translucency to a view and all its children.</p>
   3668      * <p>A hardware layer can be used to cache a complex view tree into a
   3669      * texture and reduce the complexity of drawing operations. For instance,
   3670      * when animating a complex view tree with a translation, a hardware layer can
   3671      * be used to render the view tree only once.</p>
   3672      * <p>A hardware layer can also be used to increase the rendering quality when
   3673      * rotation transformations are applied on a view. It can also be used to
   3674      * prevent potential clipping issues when applying 3D transforms on a view.</p>
   3675      *
   3676      * @see #getLayerType()
   3677      * @see #setLayerType(int, android.graphics.Paint)
   3678      * @see #LAYER_TYPE_NONE
   3679      * @see #LAYER_TYPE_SOFTWARE
   3680      */
   3681     public static final int LAYER_TYPE_HARDWARE = 2;
   3682 
   3683     @ViewDebug.ExportedProperty(category = "drawing", mapping = {
   3684             @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
   3685             @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
   3686             @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
   3687     })
   3688     int mLayerType = LAYER_TYPE_NONE;
   3689     Paint mLayerPaint;
   3690 
   3691     /**
   3692      * Set to true when drawing cache is enabled and cannot be created.
   3693      *
   3694      * @hide
   3695      */
   3696     public boolean mCachingFailed;
   3697     private Bitmap mDrawingCache;
   3698     private Bitmap mUnscaledDrawingCache;
   3699 
   3700     /**
   3701      * RenderNode holding View properties, potentially holding a DisplayList of View content.
   3702      * <p>
   3703      * When non-null and valid, this is expected to contain an up-to-date copy
   3704      * of the View content. Its DisplayList content is cleared on temporary detach and reset on
   3705      * cleanup.
   3706      */
   3707     final RenderNode mRenderNode;
   3708 
   3709     /**
   3710      * Set to true when the view is sending hover accessibility events because it
   3711      * is the innermost hovered view.
   3712      */
   3713     private boolean mSendingHoverAccessibilityEvents;
   3714 
   3715     /**
   3716      * Delegate for injecting accessibility functionality.
   3717      */
   3718     AccessibilityDelegate mAccessibilityDelegate;
   3719 
   3720     /**
   3721      * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
   3722      * and add/remove objects to/from the overlay directly through the Overlay methods.
   3723      */
   3724     ViewOverlay mOverlay;
   3725 
   3726     /**
   3727      * The currently active parent view for receiving delegated nested scrolling events.
   3728      * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
   3729      * by {@link #stopNestedScroll()} at the same point where we clear
   3730      * requestDisallowInterceptTouchEvent.
   3731      */
   3732     private ViewParent mNestedScrollingParent;
   3733 
   3734     /**
   3735      * Consistency verifier for debugging purposes.
   3736      * @hide
   3737      */
   3738     protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
   3739             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
   3740                     new InputEventConsistencyVerifier(this, 0) : null;
   3741 
   3742     private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
   3743 
   3744     private int[] mTempNestedScrollConsumed;
   3745 
   3746     /**
   3747      * An overlay is going to draw this View instead of being drawn as part of this
   3748      * View's parent. mGhostView is the View in the Overlay that must be invalidated
   3749      * when this view is invalidated.
   3750      */
   3751     GhostView mGhostView;
   3752 
   3753     /**
   3754      * Holds pairs of adjacent attribute data: attribute name followed by its value.
   3755      * @hide
   3756      */
   3757     @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
   3758     public String[] mAttributes;
   3759 
   3760     /**
   3761      * Maps a Resource id to its name.
   3762      */
   3763     private static SparseArray<String> mAttributeMap;
   3764 
   3765     /**
   3766      * @hide
   3767      */
   3768     String mStartActivityRequestWho;
   3769 
   3770     /**
   3771      * Simple constructor to use when creating a view from code.
   3772      *
   3773      * @param context The Context the view is running in, through which it can
   3774      *        access the current theme, resources, etc.
   3775      */
   3776     public View(Context context) {
   3777         mContext = context;
   3778         mResources = context != null ? context.getResources() : null;
   3779         mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
   3780         // Set some flags defaults
   3781         mPrivateFlags2 =
   3782                 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
   3783                 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
   3784                 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
   3785                 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
   3786                 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
   3787                 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
   3788         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
   3789         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
   3790         mUserPaddingStart = UNDEFINED_PADDING;
   3791         mUserPaddingEnd = UNDEFINED_PADDING;
   3792         mRenderNode = RenderNode.create(getClass().getName(), this);
   3793 
   3794         if (!sCompatibilityDone && context != null) {
   3795             final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
   3796 
   3797             // Older apps may need this compatibility hack for measurement.
   3798             sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
   3799 
   3800             // Older apps expect onMeasure() to always be called on a layout pass, regardless
   3801             // of whether a layout was requested on that View.
   3802             sIgnoreMeasureCache = targetSdkVersion < KITKAT;
   3803 
   3804             Canvas.sCompatibilityRestore = targetSdkVersion < M;
   3805 
   3806             // In M and newer, our widgets can pass a "hint" value in the size
   3807             // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
   3808             // know what the expected parent size is going to be, so e.g. list items can size
   3809             // themselves at 1/3 the size of their container. It breaks older apps though,
   3810             // specifically apps that use some popular open source libraries.
   3811             sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < M;
   3812 
   3813             sCompatibilityDone = true;
   3814         }
   3815     }
   3816 
   3817     /**
   3818      * Constructor that is called when inflating a view from XML. This is called
   3819      * when a view is being constructed from an XML file, supplying attributes
   3820      * that were specified in the XML file. This version uses a default style of
   3821      * 0, so the only attribute values applied are those in the Context's Theme
   3822      * and the given AttributeSet.
   3823      *
   3824      * <p>
   3825      * The method onFinishInflate() will be called after all children have been
   3826      * added.
   3827      *
   3828      * @param context The Context the view is running in, through which it can
   3829      *        access the current theme, resources, etc.
   3830      * @param attrs The attributes of the XML tag that is inflating the view.
   3831      * @see #View(Context, AttributeSet, int)
   3832      */
   3833     public View(Context context, @Nullable AttributeSet attrs) {
   3834         this(context, attrs, 0);
   3835     }
   3836 
   3837     /**
   3838      * Perform inflation from XML and apply a class-specific base style from a
   3839      * theme attribute. This constructor of View allows subclasses to use their
   3840      * own base style when they are inflating. For example, a Button class's
   3841      * constructor would call this version of the super class constructor and
   3842      * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
   3843      * allows the theme's button style to modify all of the base view attributes
   3844      * (in particular its background) as well as the Button class's attributes.
   3845      *
   3846      * @param context The Context the view is running in, through which it can
   3847      *        access the current theme, resources, etc.
   3848      * @param attrs The attributes of the XML tag that is inflating the view.
   3849      * @param defStyleAttr An attribute in the current theme that contains a
   3850      *        reference to a style resource that supplies default values for
   3851      *        the view. Can be 0 to not look for defaults.
   3852      * @see #View(Context, AttributeSet)
   3853      */
   3854     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
   3855         this(context, attrs, defStyleAttr, 0);
   3856     }
   3857 
   3858     /**
   3859      * Perform inflation from XML and apply a class-specific base style from a
   3860      * theme attribute or style resource. This constructor of View allows
   3861      * subclasses to use their own base style when they are inflating.
   3862      * <p>
   3863      * When determining the final value of a particular attribute, there are
   3864      * four inputs that come into play:
   3865      * <ol>
   3866      * <li>Any attribute values in the given AttributeSet.
   3867      * <li>The style resource specified in the AttributeSet (named "style").
   3868      * <li>The default style specified by <var>defStyleAttr</var>.
   3869      * <li>The default style specified by <var>defStyleRes</var>.
   3870      * <li>The base values in this theme.
   3871      * </ol>
   3872      * <p>
   3873      * Each of these inputs is considered in-order, with the first listed taking
   3874      * precedence over the following ones. In other words, if in the
   3875      * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
   3876      * , then the button's text will <em>always</em> be black, regardless of
   3877      * what is specified in any of the styles.
   3878      *
   3879      * @param context The Context the view is running in, through which it can
   3880      *        access the current theme, resources, etc.
   3881      * @param attrs The attributes of the XML tag that is inflating the view.
   3882      * @param defStyleAttr An attribute in the current theme that contains a
   3883      *        reference to a style resource that supplies default values for
   3884      *        the view. Can be 0 to not look for defaults.
   3885      * @param defStyleRes A resource identifier of a style resource that
   3886      *        supplies default values for the view, used only if
   3887      *        defStyleAttr is 0 or can not be found in the theme. Can be 0
   3888      *        to not look for defaults.
   3889      * @see #View(Context, AttributeSet, int)
   3890      */
   3891     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
   3892         this(context);
   3893 
   3894         final TypedArray a = context.obtainStyledAttributes(
   3895                 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
   3896 
   3897         if (mDebugViewAttributes) {
   3898             saveAttributeData(attrs, a);
   3899         }
   3900 
   3901         Drawable background = null;
   3902 
   3903         int leftPadding = -1;
   3904         int topPadding = -1;
   3905         int rightPadding = -1;
   3906         int bottomPadding = -1;
   3907         int startPadding = UNDEFINED_PADDING;
   3908         int endPadding = UNDEFINED_PADDING;
   3909 
   3910         int padding = -1;
   3911 
   3912         int viewFlagValues = 0;
   3913         int viewFlagMasks = 0;
   3914 
   3915         boolean setScrollContainer = false;
   3916 
   3917         int x = 0;
   3918         int y = 0;
   3919 
   3920         float tx = 0;
   3921         float ty = 0;
   3922         float tz = 0;
   3923         float elevation = 0;
   3924         float rotation = 0;
   3925         float rotationX = 0;
   3926         float rotationY = 0;
   3927         float sx = 1f;
   3928         float sy = 1f;
   3929         boolean transformSet = false;
   3930 
   3931         int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
   3932         int overScrollMode = mOverScrollMode;
   3933         boolean initializeScrollbars = false;
   3934         boolean initializeScrollIndicators = false;
   3935 
   3936         boolean startPaddingDefined = false;
   3937         boolean endPaddingDefined = false;
   3938         boolean leftPaddingDefined = false;
   3939         boolean rightPaddingDefined = false;
   3940 
   3941         final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
   3942 
   3943         final int N = a.getIndexCount();
   3944         for (int i = 0; i < N; i++) {
   3945             int attr = a.getIndex(i);
   3946             switch (attr) {
   3947                 case com.android.internal.R.styleable.View_background:
   3948                     background = a.getDrawable(attr);
   3949                     break;
   3950                 case com.android.internal.R.styleable.View_padding:
   3951                     padding = a.getDimensionPixelSize(attr, -1);
   3952                     mUserPaddingLeftInitial = padding;
   3953                     mUserPaddingRightInitial = padding;
   3954                     leftPaddingDefined = true;
   3955                     rightPaddingDefined = true;
   3956                     break;
   3957                  case com.android.internal.R.styleable.View_paddingLeft:
   3958                     leftPadding = a.getDimensionPixelSize(attr, -1);
   3959                     mUserPaddingLeftInitial = leftPadding;
   3960                     leftPaddingDefined = true;
   3961                     break;
   3962                 case com.android.internal.R.styleable.View_paddingTop:
   3963                     topPadding = a.getDimensionPixelSize(attr, -1);
   3964                     break;
   3965                 case com.android.internal.R.styleable.View_paddingRight:
   3966                     rightPadding = a.getDimensionPixelSize(attr, -1);
   3967                     mUserPaddingRightInitial = rightPadding;
   3968                     rightPaddingDefined = true;
   3969                     break;
   3970                 case com.android.internal.R.styleable.View_paddingBottom:
   3971                     bottomPadding = a.getDimensionPixelSize(attr, -1);
   3972                     break;
   3973                 case com.android.internal.R.styleable.View_paddingStart:
   3974                     startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
   3975                     startPaddingDefined = (startPadding != UNDEFINED_PADDING);
   3976                     break;
   3977                 case com.android.internal.R.styleable.View_paddingEnd:
   3978                     endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
   3979                     endPaddingDefined = (endPadding != UNDEFINED_PADDING);
   3980                     break;
   3981                 case com.android.internal.R.styleable.View_scrollX:
   3982                     x = a.getDimensionPixelOffset(attr, 0);
   3983                     break;
   3984                 case com.android.internal.R.styleable.View_scrollY:
   3985                     y = a.getDimensionPixelOffset(attr, 0);
   3986                     break;
   3987                 case com.android.internal.R.styleable.View_alpha:
   3988                     setAlpha(a.getFloat(attr, 1f));
   3989                     break;
   3990                 case com.android.internal.R.styleable.View_transformPivotX:
   3991                     setPivotX(a.getDimensionPixelOffset(attr, 0));
   3992                     break;
   3993                 case com.android.internal.R.styleable.View_transformPivotY:
   3994                     setPivotY(a.getDimensionPixelOffset(attr, 0));
   3995                     break;
   3996                 case com.android.internal.R.styleable.View_translationX:
   3997                     tx = a.getDimensionPixelOffset(attr, 0);
   3998                     transformSet = true;
   3999                     break;
   4000                 case com.android.internal.R.styleable.View_translationY:
   4001                     ty = a.getDimensionPixelOffset(attr, 0);
   4002                     transformSet = true;
   4003                     break;
   4004                 case com.android.internal.R.styleable.View_translationZ:
   4005                     tz = a.getDimensionPixelOffset(attr, 0);
   4006                     transformSet = true;
   4007                     break;
   4008                 case com.android.internal.R.styleable.View_elevation:
   4009                     elevation = a.getDimensionPixelOffset(attr, 0);
   4010                     transformSet = true;
   4011                     break;
   4012                 case com.android.internal.R.styleable.View_rotation:
   4013                     rotation = a.getFloat(attr, 0);
   4014                     transformSet = true;
   4015                     break;
   4016                 case com.android.internal.R.styleable.View_rotationX:
   4017                     rotationX = a.getFloat(attr, 0);
   4018                     transformSet = true;
   4019                     break;
   4020                 case com.android.internal.R.styleable.View_rotationY:
   4021                     rotationY = a.getFloat(attr, 0);
   4022                     transformSet = true;
   4023                     break;
   4024                 case com.android.internal.R.styleable.View_scaleX:
   4025                     sx = a.getFloat(attr, 1f);
   4026                     transformSet = true;
   4027                     break;
   4028                 case com.android.internal.R.styleable.View_scaleY:
   4029                     sy = a.getFloat(attr, 1f);
   4030                     transformSet = true;
   4031                     break;
   4032                 case com.android.internal.R.styleable.View_id:
   4033                     mID = a.getResourceId(attr, NO_ID);
   4034                     break;
   4035                 case com.android.internal.R.styleable.View_tag:
   4036                     mTag = a.getText(attr);
   4037                     break;
   4038                 case com.android.internal.R.styleable.View_fitsSystemWindows:
   4039                     if (a.getBoolean(attr, false)) {
   4040                         viewFlagValues |= FITS_SYSTEM_WINDOWS;
   4041                         viewFlagMasks |= FITS_SYSTEM_WINDOWS;
   4042                     }
   4043                     break;
   4044                 case com.android.internal.R.styleable.View_focusable:
   4045                     if (a.getBoolean(attr, false)) {
   4046                         viewFlagValues |= FOCUSABLE;
   4047                         viewFlagMasks |= FOCUSABLE_MASK;
   4048                     }
   4049                     break;
   4050                 case com.android.internal.R.styleable.View_focusableInTouchMode:
   4051                     if (a.getBoolean(attr, false)) {
   4052                         viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
   4053                         viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
   4054                     }
   4055                     break;
   4056                 case com.android.internal.R.styleable.View_clickable:
   4057                     if (a.getBoolean(attr, false)) {
   4058                         viewFlagValues |= CLICKABLE;
   4059                         viewFlagMasks |= CLICKABLE;
   4060                     }
   4061                     break;
   4062                 case com.android.internal.R.styleable.View_longClickable:
   4063                     if (a.getBoolean(attr, false)) {
   4064                         viewFlagValues |= LONG_CLICKABLE;
   4065                         viewFlagMasks |= LONG_CLICKABLE;
   4066                     }
   4067                     break;
   4068                 case com.android.internal.R.styleable.View_contextClickable:
   4069                     if (a.getBoolean(attr, false)) {
   4070                         viewFlagValues |= CONTEXT_CLICKABLE;
   4071                         viewFlagMasks |= CONTEXT_CLICKABLE;
   4072                     }
   4073                     break;
   4074                 case com.android.internal.R.styleable.View_saveEnabled:
   4075                     if (!a.getBoolean(attr, true)) {
   4076                         viewFlagValues |= SAVE_DISABLED;
   4077                         viewFlagMasks |= SAVE_DISABLED_MASK;
   4078                     }
   4079                     break;
   4080                 case com.android.internal.R.styleable.View_duplicateParentState:
   4081                     if (a.getBoolean(attr, false)) {
   4082                         viewFlagValues |= DUPLICATE_PARENT_STATE;
   4083                         viewFlagMasks |= DUPLICATE_PARENT_STATE;
   4084                     }
   4085                     break;
   4086                 case com.android.internal.R.styleable.View_visibility:
   4087                     final int visibility = a.getInt(attr, 0);
   4088                     if (visibility != 0) {
   4089                         viewFlagValues |= VISIBILITY_FLAGS[visibility];
   4090                         viewFlagMasks |= VISIBILITY_MASK;
   4091                     }
   4092                     break;
   4093                 case com.android.internal.R.styleable.View_layoutDirection:
   4094                     // Clear any layout direction flags (included resolved bits) already set
   4095                     mPrivateFlags2 &=
   4096                             ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
   4097                     // Set the layout direction flags depending on the value of the attribute
   4098                     final int layoutDirection = a.getInt(attr, -1);
   4099                     final int value = (layoutDirection != -1) ?
   4100                             LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
   4101                     mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
   4102                     break;
   4103                 case com.android.internal.R.styleable.View_drawingCacheQuality:
   4104                     final int cacheQuality = a.getInt(attr, 0);
   4105                     if (cacheQuality != 0) {
   4106                         viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
   4107                         viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
   4108                     }
   4109                     break;
   4110                 case com.android.internal.R.styleable.View_contentDescription:
   4111                     setContentDescription(a.getString(attr));
   4112                     break;
   4113                 case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
   4114                     setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
   4115                     break;
   4116                 case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
   4117                     setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
   4118                     break;
   4119                 case com.android.internal.R.styleable.View_labelFor:
   4120                     setLabelFor(a.getResourceId(attr, NO_ID));
   4121                     break;
   4122                 case com.android.internal.R.styleable.View_soundEffectsEnabled:
   4123                     if (!a.getBoolean(attr, true)) {
   4124                         viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
   4125                         viewFlagMasks |= SOUND_EFFECTS_ENABLED;
   4126                     }
   4127                     break;
   4128                 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
   4129                     if (!a.getBoolean(attr, true)) {
   4130                         viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
   4131                         viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
   4132                     }
   4133                     break;
   4134                 case R.styleable.View_scrollbars:
   4135                     final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
   4136                     if (scrollbars != SCROLLBARS_NONE) {
   4137                         viewFlagValues |= scrollbars;
   4138                         viewFlagMasks |= SCROLLBARS_MASK;
   4139                         initializeScrollbars = true;
   4140                     }
   4141                     break;
   4142                 //noinspection deprecation
   4143                 case R.styleable.View_fadingEdge:
   4144                     if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
   4145                         // Ignore the attribute starting with ICS
   4146                         break;
   4147                     }
   4148                     // With builds < ICS, fall through and apply fading edges
   4149                 case R.styleable.View_requiresFadingEdge:
   4150                     final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
   4151                     if (fadingEdge != FADING_EDGE_NONE) {
   4152                         viewFlagValues |= fadingEdge;
   4153                         viewFlagMasks |= FADING_EDGE_MASK;
   4154                         initializeFadingEdgeInternal(a);
   4155                     }
   4156                     break;
   4157                 case R.styleable.View_scrollbarStyle:
   4158                     scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
   4159                     if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
   4160                         viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
   4161                         viewFlagMasks |= SCROLLBARS_STYLE_MASK;
   4162                     }
   4163                     break;
   4164                 case R.styleable.View_isScrollContainer:
   4165                     setScrollContainer = true;
   4166                     if (a.getBoolean(attr, false)) {
   4167                         setScrollContainer(true);
   4168                     }
   4169                     break;
   4170                 case com.android.internal.R.styleable.View_keepScreenOn:
   4171                     if (a.getBoolean(attr, false)) {
   4172                         viewFlagValues |= KEEP_SCREEN_ON;
   4173                         viewFlagMasks |= KEEP_SCREEN_ON;
   4174                     }
   4175                     break;
   4176                 case R.styleable.View_filterTouchesWhenObscured:
   4177                     if (a.getBoolean(attr, false)) {
   4178                         viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
   4179                         viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
   4180                     }
   4181                     break;
   4182                 case R.styleable.View_nextFocusLeft:
   4183                     mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
   4184                     break;
   4185                 case R.styleable.View_nextFocusRight:
   4186                     mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
   4187                     break;
   4188                 case R.styleable.View_nextFocusUp:
   4189                     mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
   4190                     break;
   4191                 case R.styleable.View_nextFocusDown:
   4192                     mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
   4193                     break;
   4194                 case R.styleable.View_nextFocusForward:
   4195                     mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
   4196                     break;
   4197                 case R.styleable.View_minWidth:
   4198                     mMinWidth = a.getDimensionPixelSize(attr, 0);
   4199                     break;
   4200                 case R.styleable.View_minHeight:
   4201                     mMinHeight = a.getDimensionPixelSize(attr, 0);
   4202                     break;
   4203                 case R.styleable.View_onClick:
   4204                     if (context.isRestricted()) {
   4205                         throw new IllegalStateException("The android:onClick attribute cannot "
   4206                                 + "be used within a restricted context");
   4207                     }
   4208 
   4209                     final String handlerName = a.getString(attr);
   4210                     if (handlerName != null) {
   4211                         setOnClickListener(new DeclaredOnClickListener(this, handlerName));
   4212                     }
   4213                     break;
   4214                 case R.styleable.View_overScrollMode:
   4215                     overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
   4216                     break;
   4217                 case R.styleable.View_verticalScrollbarPosition:
   4218                     mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
   4219                     break;
   4220                 case R.styleable.View_layerType:
   4221                     setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
   4222                     break;
   4223                 case R.styleable.View_textDirection:
   4224                     // Clear any text direction flag already set
   4225                     mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
   4226                     // Set the text direction flags depending on the value of the attribute
   4227                     final int textDirection = a.getInt(attr, -1);
   4228                     if (textDirection != -1) {
   4229                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
   4230                     }
   4231                     break;
   4232                 case R.styleable.View_textAlignment:
   4233                     // Clear any text alignment flag already set
   4234                     mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
   4235                     // Set the text alignment flag depending on the value of the attribute
   4236                     final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
   4237                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
   4238                     break;
   4239                 case R.styleable.View_importantForAccessibility:
   4240                     setImportantForAccessibility(a.getInt(attr,
   4241                             IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
   4242                     break;
   4243                 case R.styleable.View_accessibilityLiveRegion:
   4244                     setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
   4245                     break;
   4246                 case R.styleable.View_transitionName:
   4247                     setTransitionName(a.getString(attr));
   4248                     break;
   4249                 case R.styleable.View_nestedScrollingEnabled:
   4250                     setNestedScrollingEnabled(a.getBoolean(attr, false));
   4251                     break;
   4252                 case R.styleable.View_stateListAnimator:
   4253                     setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
   4254                             a.getResourceId(attr, 0)));
   4255                     break;
   4256                 case R.styleable.View_backgroundTint:
   4257                     // This will get applied later during setBackground().
   4258                     if (mBackgroundTint == null) {
   4259                         mBackgroundTint = new TintInfo();
   4260                     }
   4261                     mBackgroundTint.mTintList = a.getColorStateList(
   4262                             R.styleable.View_backgroundTint);
   4263                     mBackgroundTint.mHasTintList = true;
   4264                     break;
   4265                 case R.styleable.View_backgroundTintMode:
   4266                     // This will get applied later during setBackground().
   4267                     if (mBackgroundTint == null) {
   4268                         mBackgroundTint = new TintInfo();
   4269                     }
   4270                     mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
   4271                             R.styleable.View_backgroundTintMode, -1), null);
   4272                     mBackgroundTint.mHasTintMode = true;
   4273                     break;
   4274                 case R.styleable.View_outlineProvider:
   4275                     setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
   4276                             PROVIDER_BACKGROUND));
   4277                     break;
   4278                 case R.styleable.View_foreground:
   4279                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
   4280                         setForeground(a.getDrawable(attr));
   4281                     }
   4282                     break;
   4283                 case R.styleable.View_foregroundGravity:
   4284                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
   4285                         setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
   4286                     }
   4287                     break;
   4288                 case R.styleable.View_foregroundTintMode:
   4289                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
   4290                         setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
   4291                     }
   4292                     break;
   4293                 case R.styleable.View_foregroundTint:
   4294                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
   4295                         setForegroundTintList(a.getColorStateList(attr));
   4296                     }
   4297                     break;
   4298                 case R.styleable.View_foregroundInsidePadding:
   4299                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
   4300                         if (mForegroundInfo == null) {
   4301                             mForegroundInfo = new ForegroundInfo();
   4302                         }
   4303                         mForegroundInfo.mInsidePadding = a.getBoolean(attr,
   4304                                 mForegroundInfo.mInsidePadding);
   4305                     }
   4306                     break;
   4307                 case R.styleable.View_scrollIndicators:
   4308                     final int scrollIndicators =
   4309                             (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
   4310                                     & SCROLL_INDICATORS_PFLAG3_MASK;
   4311                     if (scrollIndicators != 0) {
   4312                         mPrivateFlags3 |= scrollIndicators;
   4313                         initializeScrollIndicators = true;
   4314                     }
   4315                     break;
   4316             }
   4317         }
   4318 
   4319         setOverScrollMode(overScrollMode);
   4320 
   4321         // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
   4322         // the resolved layout direction). Those cached values will be used later during padding
   4323         // resolution.
   4324         mUserPaddingStart = startPadding;
   4325         mUserPaddingEnd = endPadding;
   4326 
   4327         if (background != null) {
   4328             setBackground(background);
   4329         }
   4330 
   4331         // setBackground above will record that padding is currently provided by the background.
   4332         // If we have padding specified via xml, record that here instead and use it.
   4333         mLeftPaddingDefined = leftPaddingDefined;
   4334         mRightPaddingDefined = rightPaddingDefined;
   4335 
   4336         if (padding >= 0) {
   4337             leftPadding = padding;
   4338             topPadding = padding;
   4339             rightPadding = padding;
   4340             bottomPadding = padding;
   4341             mUserPaddingLeftInitial = padding;
   4342             mUserPaddingRightInitial = padding;
   4343         }
   4344 
   4345         if (isRtlCompatibilityMode()) {
   4346             // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
   4347             // left / right padding are used if defined (meaning here nothing to do). If they are not
   4348             // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
   4349             // start / end and resolve them as left / right (layout direction is not taken into account).
   4350             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
   4351             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
   4352             // defined.
   4353             if (!mLeftPaddingDefined && startPaddingDefined) {
   4354                 leftPadding = startPadding;
   4355             }
   4356             mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
   4357             if (!mRightPaddingDefined && endPaddingDefined) {
   4358                 rightPadding = endPadding;
   4359             }
   4360             mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
   4361         } else {
   4362             // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
   4363             // values defined. Otherwise, left /right values are used.
   4364             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
   4365             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
   4366             // defined.
   4367             final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
   4368 
   4369             if (mLeftPaddingDefined && !hasRelativePadding) {
   4370                 mUserPaddingLeftInitial = leftPadding;
   4371             }
   4372             if (mRightPaddingDefined && !hasRelativePadding) {
   4373                 mUserPaddingRightInitial = rightPadding;
   4374             }
   4375         }
   4376 
   4377         internalSetPadding(
   4378                 mUserPaddingLeftInitial,
   4379                 topPadding >= 0 ? topPadding : mPaddingTop,
   4380                 mUserPaddingRightInitial,
   4381                 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
   4382 
   4383         if (viewFlagMasks != 0) {
   4384             setFlags(viewFlagValues, viewFlagMasks);
   4385         }
   4386 
   4387         if (initializeScrollbars) {
   4388             initializeScrollbarsInternal(a);
   4389         }
   4390 
   4391         if (initializeScrollIndicators) {
   4392             initializeScrollIndicatorsInternal();
   4393         }
   4394 
   4395         a.recycle();
   4396 
   4397         // Needs to be called after mViewFlags is set
   4398         if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
   4399             recomputePadding();
   4400         }
   4401 
   4402         if (x != 0 || y != 0) {
   4403             scrollTo(x, y);
   4404         }
   4405 
   4406         if (transformSet) {
   4407             setTranslationX(tx);
   4408             setTranslationY(ty);
   4409             setTranslationZ(tz);
   4410             setElevation(elevation);
   4411             setRotation(rotation);
   4412             setRotationX(rotationX);
   4413             setRotationY(rotationY);
   4414             setScaleX(sx);
   4415             setScaleY(sy);
   4416         }
   4417 
   4418         if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
   4419             setScrollContainer(true);
   4420         }
   4421 
   4422         computeOpaqueFlags();
   4423     }
   4424 
   4425     /**
   4426      * An implementation of OnClickListener that attempts to lazily load a
   4427      * named click handling method from a parent or ancestor context.
   4428      */
   4429     private static class DeclaredOnClickListener implements OnClickListener {
   4430         private final View mHostView;
   4431         private final String mMethodName;
   4432 
   4433         private Method mMethod;
   4434 
   4435         public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
   4436             mHostView = hostView;
   4437             mMethodName = methodName;
   4438         }
   4439 
   4440         @Override
   4441         public void onClick(@NonNull View v) {
   4442             if (mMethod == null) {
   4443                 mMethod = resolveMethod(mHostView.getContext(), mMethodName);
   4444             }
   4445 
   4446             try {
   4447                 mMethod.invoke(mHostView.getContext(), v);
   4448             } catch (IllegalAccessException e) {
   4449                 throw new IllegalStateException(
   4450                         "Could not execute non-public method for android:onClick", e);
   4451             } catch (InvocationTargetException e) {
   4452                 throw new IllegalStateException(
   4453                         "Could not execute method for android:onClick", e);
   4454             }
   4455         }
   4456 
   4457         @NonNull
   4458         private Method resolveMethod(@Nullable Context context, @NonNull String name) {
   4459             while (context != null) {
   4460                 try {
   4461                     if (!context.isRestricted()) {
   4462                         return context.getClass().getMethod(mMethodName, View.class);
   4463                     }
   4464                 } catch (NoSuchMethodException e) {
   4465                     // Failed to find method, keep searching up the hierarchy.
   4466                 }
   4467 
   4468                 if (context instanceof ContextWrapper) {
   4469                     context = ((ContextWrapper) context).getBaseContext();
   4470                 } else {
   4471                     // Can't search up the hierarchy, null out and fail.
   4472                     context = null;
   4473                 }
   4474             }
   4475 
   4476             final int id = mHostView.getId();
   4477             final String idText = id == NO_ID ? "" : " with id '"
   4478                     + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
   4479             throw new IllegalStateException("Could not find method " + mMethodName
   4480                     + "(View) in a parent or ancestor Context for android:onClick "
   4481                     + "attribute defined on view " + mHostView.getClass() + idText);
   4482         }
   4483     }
   4484 
   4485     /**
   4486      * Non-public constructor for use in testing
   4487      */
   4488     View() {
   4489         mResources = null;
   4490         mRenderNode = RenderNode.create(getClass().getName(), this);
   4491     }
   4492 
   4493     private static SparseArray<String> getAttributeMap() {
   4494         if (mAttributeMap == null) {
   4495             mAttributeMap = new SparseArray<>();
   4496         }
   4497         return mAttributeMap;
   4498     }
   4499 
   4500     private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
   4501         final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
   4502         final int indexCount = t.getIndexCount();
   4503         final String[] attributes = new String[(attrsCount + indexCount) * 2];
   4504 
   4505         int i = 0;
   4506 
   4507         // Store raw XML attributes.
   4508         for (int j = 0; j < attrsCount; ++j) {
   4509             attributes[i] = attrs.getAttributeName(j);
   4510             attributes[i + 1] = attrs.getAttributeValue(j);
   4511             i += 2;
   4512         }
   4513 
   4514         // Store resolved styleable attributes.
   4515         final Resources res = t.getResources();
   4516         final SparseArray<String> attributeMap = getAttributeMap();
   4517         for (int j = 0; j < indexCount; ++j) {
   4518             final int index = t.getIndex(j);
   4519             if (!t.hasValueOrEmpty(index)) {
   4520                 // Value is undefined. Skip it.
   4521                 continue;
   4522             }
   4523 
   4524             final int resourceId = t.getResourceId(index, 0);
   4525             if (resourceId == 0) {
   4526                 // Value is not a reference. Skip it.
   4527                 continue;
   4528             }
   4529 
   4530             String resourceName = attributeMap.get(resourceId);
   4531             if (resourceName == null) {
   4532                 try {
   4533                     resourceName = res.getResourceName(resourceId);
   4534                 } catch (Resources.NotFoundException e) {
   4535                     resourceName = "0x" + Integer.toHexString(resourceId);
   4536                 }
   4537                 attributeMap.put(resourceId, resourceName);
   4538             }
   4539 
   4540             attributes[i] = resourceName;
   4541             attributes[i + 1] = t.getString(index);
   4542             i += 2;
   4543         }
   4544 
   4545         // Trim to fit contents.
   4546         final String[] trimmed = new String[i];
   4547         System.arraycopy(attributes, 0, trimmed, 0, i);
   4548         mAttributes = trimmed;
   4549     }
   4550 
   4551     public String toString() {
   4552         StringBuilder out = new StringBuilder(128);
   4553         out.append(getClass().getName());
   4554         out.append('{');
   4555         out.append(Integer.toHexString(System.identityHashCode(this)));
   4556         out.append(' ');
   4557         switch (mViewFlags&VISIBILITY_MASK) {
   4558             case VISIBLE: out.append('V'); break;
   4559             case INVISIBLE: out.append('I'); break;
   4560             case GONE: out.append('G'); break;
   4561             default: out.append('.'); break;
   4562         }
   4563         out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
   4564         out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
   4565         out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
   4566         out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
   4567         out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
   4568         out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
   4569         out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
   4570         out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
   4571         out.append(' ');
   4572         out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
   4573         out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
   4574         out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
   4575         if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
   4576             out.append('p');
   4577         } else {
   4578             out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
   4579         }
   4580         out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
   4581         out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
   4582         out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
   4583         out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
   4584         out.append(' ');
   4585         out.append(mLeft);
   4586         out.append(',');
   4587         out.append(mTop);
   4588         out.append('-');
   4589         out.append(mRight);
   4590         out.append(',');
   4591         out.append(mBottom);
   4592         final int id = getId();
   4593         if (id != NO_ID) {
   4594             out.append(" #");
   4595             out.append(Integer.toHexString(id));
   4596             final Resources r = mResources;
   4597             if (Resources.resourceHasPackage(id) && r != null) {
   4598                 try {
   4599                     String pkgname;
   4600                     switch (id&0xff000000) {
   4601                         case 0x7f000000:
   4602                             pkgname="app";
   4603                             break;
   4604                         case 0x01000000:
   4605                             pkgname="android";
   4606                             break;
   4607                         default:
   4608                             pkgname = r.getResourcePackageName(id);
   4609                             break;
   4610                     }
   4611                     String typename = r.getResourceTypeName(id);
   4612                     String entryname = r.getResourceEntryName(id);
   4613                     out.append(" ");
   4614                     out.append(pkgname);
   4615                     out.append(":");
   4616                     out.append(typename);
   4617                     out.append("/");
   4618                     out.append(entryname);
   4619                 } catch (Resources.NotFoundException e) {
   4620                 }
   4621             }
   4622         }
   4623         out.append("}");
   4624         return out.toString();
   4625     }
   4626 
   4627     /**
   4628      * <p>
   4629      * Initializes the fading edges from a given set of styled attributes. This
   4630      * method should be called by subclasses that need fading edges and when an
   4631      * instance of these subclasses is created programmatically rather than
   4632      * being inflated from XML. This method is automatically called when the XML
   4633      * is inflated.
   4634      * </p>
   4635      *
   4636      * @param a the styled attributes set to initialize the fading edges from
   4637      *
   4638      * @removed
   4639      */
   4640     protected void initializeFadingEdge(TypedArray a) {
   4641         // This method probably shouldn't have been included in the SDK to begin with.
   4642         // It relies on 'a' having been initialized using an attribute filter array that is
   4643         // not publicly available to the SDK. The old method has been renamed
   4644         // to initializeFadingEdgeInternal and hidden for framework use only;
   4645         // this one initializes using defaults to make it safe to call for apps.
   4646 
   4647         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
   4648 
   4649         initializeFadingEdgeInternal(arr);
   4650 
   4651         arr.recycle();
   4652     }
   4653 
   4654     /**
   4655      * <p>
   4656      * Initializes the fading edges from a given set of styled attributes. This
   4657      * method should be called by subclasses that need fading edges and when an
   4658      * instance of these subclasses is created programmatically rather than
   4659      * being inflated from XML. This method is automatically called when the XML
   4660      * is inflated.
   4661      * </p>
   4662      *
   4663      * @param a the styled attributes set to initialize the fading edges from
   4664      * @hide This is the real method; the public one is shimmed to be safe to call from apps.
   4665      */
   4666     protected void initializeFadingEdgeInternal(TypedArray a) {
   4667         initScrollCache();
   4668 
   4669         mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
   4670                 R.styleable.View_fadingEdgeLength,
   4671                 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
   4672     }
   4673 
   4674     /**
   4675      * Returns the size of the vertical faded edges used to indicate that more
   4676      * content in this view is visible.
   4677      *
   4678      * @return The size in pixels of the vertical faded edge or 0 if vertical
   4679      *         faded edges are not enabled for this view.
   4680      * @attr ref android.R.styleable#View_fadingEdgeLength
   4681      */
   4682     public int getVerticalFadingEdgeLength() {
   4683         if (isVerticalFadingEdgeEnabled()) {
   4684             ScrollabilityCache cache = mScrollCache;
   4685             if (cache != null) {
   4686                 return cache.fadingEdgeLength;
   4687             }
   4688         }
   4689         return 0;
   4690     }
   4691 
   4692     /**
   4693      * Set the size of the faded edge used to indicate that more content in this
   4694      * view is available.  Will not change whether the fading edge is enabled; use
   4695      * {@link #setVerticalFadingEdgeEnabled(boolean)} or
   4696      * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
   4697      * for the vertical or horizontal fading edges.
   4698      *
   4699      * @param length The size in pixels of the faded edge used to indicate that more
   4700      *        content in this view is visible.
   4701      */
   4702     public void setFadingEdgeLength(int length) {
   4703         initScrollCache();
   4704         mScrollCache.fadingEdgeLength = length;
   4705     }
   4706 
   4707     /**
   4708      * Returns the size of the horizontal faded edges used to indicate that more
   4709      * content in this view is visible.
   4710      *
   4711      * @return The size in pixels of the horizontal faded edge or 0 if horizontal
   4712      *         faded edges are not enabled for this view.
   4713      * @attr ref android.R.styleable#View_fadingEdgeLength
   4714      */
   4715     public int getHorizontalFadingEdgeLength() {
   4716         if (isHorizontalFadingEdgeEnabled()) {
   4717             ScrollabilityCache cache = mScrollCache;
   4718             if (cache != null) {
   4719                 return cache.fadingEdgeLength;
   4720             }
   4721         }
   4722         return 0;
   4723     }
   4724 
   4725     /**
   4726      * Returns the width of the vertical scrollbar.
   4727      *
   4728      * @return The width in pixels of the vertical scrollbar or 0 if there
   4729      *         is no vertical scrollbar.
   4730      */
   4731     public int getVerticalScrollbarWidth() {
   4732         ScrollabilityCache cache = mScrollCache;
   4733         if (cache != null) {
   4734             ScrollBarDrawable scrollBar = cache.scrollBar;
   4735             if (scrollBar != null) {
   4736                 int size = scrollBar.getSize(true);
   4737                 if (size <= 0) {
   4738                     size = cache.scrollBarSize;
   4739                 }
   4740                 return size;
   4741             }
   4742             return 0;
   4743         }
   4744         return 0;
   4745     }
   4746 
   4747     /**
   4748      * Returns the height of the horizontal scrollbar.
   4749      *
   4750      * @return The height in pixels of the horizontal scrollbar or 0 if
   4751      *         there is no horizontal scrollbar.
   4752      */
   4753     protected int getHorizontalScrollbarHeight() {
   4754         ScrollabilityCache cache = mScrollCache;
   4755         if (cache != null) {
   4756             ScrollBarDrawable scrollBar = cache.scrollBar;
   4757             if (scrollBar != null) {
   4758                 int size = scrollBar.getSize(false);
   4759                 if (size <= 0) {
   4760                     size = cache.scrollBarSize;
   4761                 }
   4762                 return size;
   4763             }
   4764             return 0;
   4765         }
   4766         return 0;
   4767     }
   4768 
   4769     /**
   4770      * <p>
   4771      * Initializes the scrollbars from a given set of styled attributes. This
   4772      * method should be called by subclasses that need scrollbars and when an
   4773      * instance of these subclasses is created programmatically rather than
   4774      * being inflated from XML. This method is automatically called when the XML
   4775      * is inflated.
   4776      * </p>
   4777      *
   4778      * @param a the styled attributes set to initialize the scrollbars from
   4779      *
   4780      * @removed
   4781      */
   4782     protected void initializeScrollbars(TypedArray a) {
   4783         // It's not safe to use this method from apps. The parameter 'a' must have been obtained
   4784         // using the View filter array which is not available to the SDK. As such, internal
   4785         // framework usage now uses initializeScrollbarsInternal and we grab a default
   4786         // TypedArray with the right filter instead here.
   4787         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
   4788 
   4789         initializeScrollbarsInternal(arr);
   4790 
   4791         // We ignored the method parameter. Recycle the one we actually did use.
   4792         arr.recycle();
   4793     }
   4794 
   4795     /**
   4796      * <p>
   4797      * Initializes the scrollbars from a given set of styled attributes. This
   4798      * method should be called by subclasses that need scrollbars and when an
   4799      * instance of these subclasses is created programmatically rather than
   4800      * being inflated from XML. This method is automatically called when the XML
   4801      * is inflated.
   4802      * </p>
   4803      *
   4804      * @param a the styled attributes set to initialize the scrollbars from
   4805      * @hide
   4806      */
   4807     protected void initializeScrollbarsInternal(TypedArray a) {
   4808         initScrollCache();
   4809 
   4810         final ScrollabilityCache scrollabilityCache = mScrollCache;
   4811 
   4812         if (scrollabilityCache.scrollBar == null) {
   4813             scrollabilityCache.scrollBar = new ScrollBarDrawable();
   4814             scrollabilityCache.scrollBar.setCallback(this);
   4815             scrollabilityCache.scrollBar.setState(getDrawableState());
   4816         }
   4817 
   4818         final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
   4819 
   4820         if (!fadeScrollbars) {
   4821             scrollabilityCache.state = ScrollabilityCache.ON;
   4822         }
   4823         scrollabilityCache.fadeScrollBars = fadeScrollbars;
   4824 
   4825 
   4826         scrollabilityCache.scrollBarFadeDuration = a.getInt(
   4827                 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
   4828                         .getScrollBarFadeDuration());
   4829         scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
   4830                 R.styleable.View_scrollbarDefaultDelayBeforeFade,
   4831                 ViewConfiguration.getScrollDefaultDelay());
   4832 
   4833 
   4834         scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
   4835                 com.android.internal.R.styleable.View_scrollbarSize,
   4836                 ViewConfiguration.get(mContext).getScaledScrollBarSize());
   4837 
   4838         Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
   4839         scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
   4840 
   4841         Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
   4842         if (thumb != null) {
   4843             scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
   4844         }
   4845 
   4846         boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
   4847                 false);
   4848         if (alwaysDraw) {
   4849             scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
   4850         }
   4851 
   4852         track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
   4853         scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
   4854 
   4855         thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
   4856         if (thumb != null) {
   4857             scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
   4858         }
   4859 
   4860         alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
   4861                 false);
   4862         if (alwaysDraw) {
   4863             scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
   4864         }
   4865 
   4866         // Apply layout direction to the new Drawables if needed
   4867         final int layoutDirection = getLayoutDirection();
   4868         if (track != null) {
   4869             track.setLayoutDirection(layoutDirection);
   4870         }
   4871         if (thumb != null) {
   4872             thumb.setLayoutDirection(layoutDirection);
   4873         }
   4874 
   4875         // Re-apply user/background padding so that scrollbar(s) get added
   4876         resolvePadding();
   4877     }
   4878 
   4879     private void initializeScrollIndicatorsInternal() {
   4880         // Some day maybe we'll break this into top/left/start/etc. and let the
   4881         // client control it. Until then, you can have any scroll indicator you
   4882         // want as long as it's a 1dp foreground-colored rectangle.
   4883         if (mScrollIndicatorDrawable == null) {
   4884             mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
   4885         }
   4886     }
   4887 
   4888     /**
   4889      * <p>
   4890      * Initalizes the scrollability cache if necessary.
   4891      * </p>
   4892      */
   4893     private void initScrollCache() {
   4894         if (mScrollCache == null) {
   4895             mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
   4896         }
   4897     }
   4898 
   4899     private ScrollabilityCache getScrollCache() {
   4900         initScrollCache();
   4901         return mScrollCache;
   4902     }
   4903 
   4904     /**
   4905      * Set the position of the vertical scroll bar. Should be one of
   4906      * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
   4907      * {@link #SCROLLBAR_POSITION_RIGHT}.
   4908      *
   4909      * @param position Where the vertical scroll bar should be positioned.
   4910      */
   4911     public void setVerticalScrollbarPosition(int position) {
   4912         if (mVerticalScrollbarPosition != position) {
   4913             mVerticalScrollbarPosition = position;
   4914             computeOpaqueFlags();
   4915             resolvePadding();
   4916         }
   4917     }
   4918 
   4919     /**
   4920      * @return The position where the vertical scroll bar will show, if applicable.
   4921      * @see #setVerticalScrollbarPosition(int)
   4922      */
   4923     public int getVerticalScrollbarPosition() {
   4924         return mVerticalScrollbarPosition;
   4925     }
   4926 
   4927     /**
   4928      * Sets the state of all scroll indicators.
   4929      * <p>
   4930      * See {@link #setScrollIndicators(int, int)} for usage information.
   4931      *
   4932      * @param indicators a bitmask of indicators that should be enabled, or
   4933      *                   {@code 0} to disable all indicators
   4934      * @see #setScrollIndicators(int, int)
   4935      * @see #getScrollIndicators()
   4936      * @attr ref android.R.styleable#View_scrollIndicators
   4937      */
   4938     public void setScrollIndicators(@ScrollIndicators int indicators) {
   4939         setScrollIndicators(indicators,
   4940                 SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
   4941     }
   4942 
   4943     /**
   4944      * Sets the state of the scroll indicators specified by the mask. To change
   4945      * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
   4946      * <p>
   4947      * When a scroll indicator is enabled, it will be displayed if the view
   4948      * can scroll in the direction of the indicator.
   4949      * <p>
   4950      * Multiple indicator types may be enabled or disabled by passing the
   4951      * logical OR of the desired types. If multiple types are specified, they
   4952      * will all be set to the same enabled state.
   4953      * <p>
   4954      * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
   4955      *
   4956      * @param indicators the indicator direction, or the logical OR of multiple
   4957      *             indicator directions. One or more of:
   4958      *             <ul>
   4959      *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
   4960      *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
   4961      *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
   4962      *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
   4963      *               <li>{@link #SCROLL_INDICATOR_START}</li>
   4964      *               <li>{@link #SCROLL_INDICATOR_END}</li>
   4965      *             </ul>
   4966      * @see #setScrollIndicators(int)
   4967      * @see #getScrollIndicators()
   4968      * @attr ref android.R.styleable#View_scrollIndicators
   4969      */
   4970     public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
   4971         // Shift and sanitize mask.
   4972         mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   4973         mask &= SCROLL_INDICATORS_PFLAG3_MASK;
   4974 
   4975         // Shift and mask indicators.
   4976         indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   4977         indicators &= mask;
   4978 
   4979         // Merge with non-masked flags.
   4980         final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
   4981 
   4982         if (mPrivateFlags3 != updatedFlags) {
   4983             mPrivateFlags3 = updatedFlags;
   4984 
   4985             if (indicators != 0) {
   4986                 initializeScrollIndicatorsInternal();
   4987             }
   4988             invalidate();
   4989         }
   4990     }
   4991 
   4992     /**
   4993      * Returns a bitmask representing the enabled scroll indicators.
   4994      * <p>
   4995      * For example, if the top and left scroll indicators are enabled and all
   4996      * other indicators are disabled, the return value will be
   4997      * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
   4998      * <p>
   4999      * To check whether the bottom scroll indicator is enabled, use the value
   5000      * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
   5001      *
   5002      * @return a bitmask representing the enabled scroll indicators
   5003      */
   5004     @ScrollIndicators
   5005     public int getScrollIndicators() {
   5006         return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
   5007                 >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
   5008     }
   5009 
   5010     ListenerInfo getListenerInfo() {
   5011         if (mListenerInfo != null) {
   5012             return mListenerInfo;
   5013         }
   5014         mListenerInfo = new ListenerInfo();
   5015         return mListenerInfo;
   5016     }
   5017 
   5018     /**
   5019      * Register a callback to be invoked when the scroll X or Y positions of
   5020      * this view change.
   5021      * <p>
   5022      * <b>Note:</b> Some views handle scrolling independently from View and may
   5023      * have their own separate listeners for scroll-type events. For example,
   5024      * {@link android.widget.ListView ListView} allows clients to register an
   5025      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
   5026      * to listen for changes in list scroll position.
   5027      *
   5028      * @param l The listener to notify when the scroll X or Y position changes.
   5029      * @see android.view.View#getScrollX()
   5030      * @see android.view.View#getScrollY()
   5031      */
   5032     public void setOnScrollChangeListener(OnScrollChangeListener l) {
   5033         getListenerInfo().mOnScrollChangeListener = l;
   5034     }
   5035 
   5036     /**
   5037      * Register a callback to be invoked when focus of this view changed.
   5038      *
   5039      * @param l The callback that will run.
   5040      */
   5041     public void setOnFocusChangeListener(OnFocusChangeListener l) {
   5042         getListenerInfo().mOnFocusChangeListener = l;
   5043     }
   5044 
   5045     /**
   5046      * Add a listener that will be called when the bounds of the view change due to
   5047      * layout processing.
   5048      *
   5049      * @param listener The listener that will be called when layout bounds change.
   5050      */
   5051     public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
   5052         ListenerInfo li = getListenerInfo();
   5053         if (li.mOnLayoutChangeListeners == null) {
   5054             li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
   5055         }
   5056         if (!li.mOnLayoutChangeListeners.contains(listener)) {
   5057             li.mOnLayoutChangeListeners.add(listener);
   5058         }
   5059     }
   5060 
   5061     /**
   5062      * Remove a listener for layout changes.
   5063      *
   5064      * @param listener The listener for layout bounds change.
   5065      */
   5066     public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
   5067         ListenerInfo li = mListenerInfo;
   5068         if (li == null || li.mOnLayoutChangeListeners == null) {
   5069             return;
   5070         }
   5071         li.mOnLayoutChangeListeners.remove(listener);
   5072     }
   5073 
   5074     /**
   5075      * Add a listener for attach state changes.
   5076      *
   5077      * This listener will be called whenever this view is attached or detached
   5078      * from a window. Remove the listener using
   5079      * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
   5080      *
   5081      * @param listener Listener to attach
   5082      * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
   5083      */
   5084     public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
   5085         ListenerInfo li = getListenerInfo();
   5086         if (li.mOnAttachStateChangeListeners == null) {
   5087             li.mOnAttachStateChangeListeners
   5088                     = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
   5089         }
   5090         li.mOnAttachStateChangeListeners.add(listener);
   5091     }
   5092 
   5093     /**
   5094      * Remove a listener for attach state changes. The listener will receive no further
   5095      * notification of window attach/detach events.
   5096      *
   5097      * @param listener Listener to remove
   5098      * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
   5099      */
   5100     public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
   5101         ListenerInfo li = mListenerInfo;
   5102         if (li == null || li.mOnAttachStateChangeListeners == null) {
   5103             return;
   5104         }
   5105         li.mOnAttachStateChangeListeners.remove(listener);
   5106     }
   5107 
   5108     /**
   5109      * Returns the focus-change callback registered for this view.
   5110      *
   5111      * @return The callback, or null if one is not registered.
   5112      */
   5113     public OnFocusChangeListener getOnFocusChangeListener() {
   5114         ListenerInfo li = mListenerInfo;
   5115         return li != null ? li.mOnFocusChangeListener : null;
   5116     }
   5117 
   5118     /**
   5119      * Register a callback to be invoked when this view is clicked. If this view is not
   5120      * clickable, it becomes clickable.
   5121      *
   5122      * @param l The callback that will run
   5123      *
   5124      * @see #setClickable(boolean)
   5125      */
   5126     public void setOnClickListener(@Nullable OnClickListener l) {
   5127         if (!isClickable()) {
   5128             setClickable(true);
   5129         }
   5130         getListenerInfo().mOnClickListener = l;
   5131     }
   5132 
   5133     /**
   5134      * Return whether this view has an attached OnClickListener.  Returns
   5135      * true if there is a listener, false if there is none.
   5136      */
   5137     public boolean hasOnClickListeners() {
   5138         ListenerInfo li = mListenerInfo;
   5139         return (li != null && li.mOnClickListener != null);
   5140     }
   5141 
   5142     /**
   5143      * Register a callback to be invoked when this view is clicked and held. If this view is not
   5144      * long clickable, it becomes long clickable.
   5145      *
   5146      * @param l The callback that will run
   5147      *
   5148      * @see #setLongClickable(boolean)
   5149      */
   5150     public void setOnLongClickListener(@Nullable OnLongClickListener l) {
   5151         if (!isLongClickable()) {
   5152             setLongClickable(true);
   5153         }
   5154         getListenerInfo().mOnLongClickListener = l;
   5155     }
   5156 
   5157     /**
   5158      * Register a callback to be invoked when this view is context clicked. If the view is not
   5159      * context clickable, it becomes context clickable.
   5160      *
   5161      * @param l The callback that will run
   5162      * @see #setContextClickable(boolean)
   5163      */
   5164     public void setOnContextClickListener(@Nullable OnContextClickListener l) {
   5165         if (!isContextClickable()) {
   5166             setContextClickable(true);
   5167         }
   5168         getListenerInfo().mOnContextClickListener = l;
   5169     }
   5170 
   5171     /**
   5172      * Register a callback to be invoked when the context menu for this view is
   5173      * being built. If this view is not long clickable, it becomes long clickable.
   5174      *
   5175      * @param l The callback that will run
   5176      *
   5177      */
   5178     public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
   5179         if (!isLongClickable()) {
   5180             setLongClickable(true);
   5181         }
   5182         getListenerInfo().mOnCreateContextMenuListener = l;
   5183     }
   5184 
   5185     /**
   5186      * Call this view's OnClickListener, if it is defined.  Performs all normal
   5187      * actions associated with clicking: reporting accessibility event, playing
   5188      * a sound, etc.
   5189      *
   5190      * @return True there was an assigned OnClickListener that was called, false
   5191      *         otherwise is returned.
   5192      */
   5193     public boolean performClick() {
   5194         final boolean result;
   5195         final ListenerInfo li = mListenerInfo;
   5196         if (li != null && li.mOnClickListener != null) {
   5197             playSoundEffect(SoundEffectConstants.CLICK);
   5198             li.mOnClickListener.onClick(this);
   5199             result = true;
   5200         } else {
   5201             result = false;
   5202         }
   5203 
   5204         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
   5205         return result;
   5206     }
   5207 
   5208     /**
   5209      * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
   5210      * this only calls the listener, and does not do any associated clicking
   5211      * actions like reporting an accessibility event.
   5212      *
   5213      * @return True there was an assigned OnClickListener that was called, false
   5214      *         otherwise is returned.
   5215      */
   5216     public boolean callOnClick() {
   5217         ListenerInfo li = mListenerInfo;
   5218         if (li != null && li.mOnClickListener != null) {
   5219             li.mOnClickListener.onClick(this);
   5220             return true;
   5221         }
   5222         return false;
   5223     }
   5224 
   5225     /**
   5226      * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
   5227      * OnLongClickListener did not consume the event.
   5228      *
   5229      * @return True if one of the above receivers consumed the event, false otherwise.
   5230      */
   5231     public boolean performLongClick() {
   5232         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
   5233 
   5234         boolean handled = false;
   5235         ListenerInfo li = mListenerInfo;
   5236         if (li != null && li.mOnLongClickListener != null) {
   5237             handled = li.mOnLongClickListener.onLongClick(View.this);
   5238         }
   5239         if (!handled) {
   5240             handled = showContextMenu();
   5241         }
   5242         if (handled) {
   5243             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
   5244         }
   5245         return handled;
   5246     }
   5247 
   5248     /**
   5249      * Call this view's OnContextClickListener, if it is defined.
   5250      *
   5251      * @return True if there was an assigned OnContextClickListener that consumed the event, false
   5252      *         otherwise.
   5253      */
   5254     public boolean performContextClick() {
   5255         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
   5256 
   5257         boolean handled = false;
   5258         ListenerInfo li = mListenerInfo;
   5259         if (li != null && li.mOnContextClickListener != null) {
   5260             handled = li.mOnContextClickListener.onContextClick(View.this);
   5261         }
   5262         if (handled) {
   5263             performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
   5264         }
   5265         return handled;
   5266     }
   5267 
   5268     /**
   5269      * Performs button-related actions during a touch down event.
   5270      *
   5271      * @param event The event.
   5272      * @return True if the down was consumed.
   5273      *
   5274      * @hide
   5275      */
   5276     protected boolean performButtonActionOnTouchDown(MotionEvent event) {
   5277         if (event.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE &&
   5278             (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
   5279             showContextMenu(event.getX(), event.getY(), event.getMetaState());
   5280             mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
   5281             return true;
   5282         }
   5283         return false;
   5284     }
   5285 
   5286     /**
   5287      * Bring up the context menu for this view.
   5288      *
   5289      * @return Whether a context menu was displayed.
   5290      */
   5291     public boolean showContextMenu() {
   5292         return getParent().showContextMenuForChild(this);
   5293     }
   5294 
   5295     /**
   5296      * Bring up the context menu for this view, referring to the item under the specified point.
   5297      *
   5298      * @param x The referenced x coordinate.
   5299      * @param y The referenced y coordinate.
   5300      * @param metaState The keyboard modifiers that were pressed.
   5301      * @return Whether a context menu was displayed.
   5302      *
   5303      * @hide
   5304      */
   5305     public boolean showContextMenu(float x, float y, int metaState) {
   5306         return showContextMenu();
   5307     }
   5308 
   5309     /**
   5310      * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
   5311      *
   5312      * @param callback Callback that will control the lifecycle of the action mode
   5313      * @return The new action mode if it is started, null otherwise
   5314      *
   5315      * @see ActionMode
   5316      * @see #startActionMode(android.view.ActionMode.Callback, int)
   5317      */
   5318     public ActionMode startActionMode(ActionMode.Callback callback) {
   5319         return startActionMode(callback, ActionMode.TYPE_PRIMARY);
   5320     }
   5321 
   5322     /**
   5323      * Start an action mode with the given type.
   5324      *
   5325      * @param callback Callback that will control the lifecycle of the action mode
   5326      * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
   5327      * @return The new action mode if it is started, null otherwise
   5328      *
   5329      * @see ActionMode
   5330      */
   5331     public ActionMode startActionMode(ActionMode.Callback callback, int type) {
   5332         ViewParent parent = getParent();
   5333         if (parent == null) return null;
   5334         try {
   5335             return parent.startActionModeForChild(this, callback, type);
   5336         } catch (AbstractMethodError ame) {
   5337             // Older implementations of custom views might not implement this.
   5338             return parent.startActionModeForChild(this, callback);
   5339         }
   5340     }
   5341 
   5342     /**
   5343      * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
   5344      * Context, creating a unique View identifier to retrieve the result.
   5345      *
   5346      * @param intent The Intent to be started.
   5347      * @param requestCode The request code to use.
   5348      * @hide
   5349      */
   5350     public void startActivityForResult(Intent intent, int requestCode) {
   5351         mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
   5352         getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
   5353     }
   5354 
   5355     /**
   5356      * If this View corresponds to the calling who, dispatches the activity result.
   5357      * @param who The identifier for the targeted View to receive the result.
   5358      * @param requestCode The integer request code originally supplied to
   5359      *                    startActivityForResult(), allowing you to identify who this
   5360      *                    result came from.
   5361      * @param resultCode The integer result code returned by the child activity
   5362      *                   through its setResult().
   5363      * @param data An Intent, which can return result data to the caller
   5364      *               (various data can be attached to Intent "extras").
   5365      * @return {@code true} if the activity result was dispatched.
   5366      * @hide
   5367      */
   5368     public boolean dispatchActivityResult(
   5369             String who, int requestCode, int resultCode, Intent data) {
   5370         if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
   5371             onActivityResult(requestCode, resultCode, data);
   5372             mStartActivityRequestWho = null;
   5373             return true;
   5374         }
   5375         return false;
   5376     }
   5377 
   5378     /**
   5379      * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
   5380      *
   5381      * @param requestCode The integer request code originally supplied to
   5382      *                    startActivityForResult(), allowing you to identify who this
   5383      *                    result came from.
   5384      * @param resultCode The integer result code returned by the child activity
   5385      *                   through its setResult().
   5386      * @param data An Intent, which can return result data to the caller
   5387      *               (various data can be attached to Intent "extras").
   5388      * @hide
   5389      */
   5390     public void onActivityResult(int requestCode, int resultCode, Intent data) {
   5391         // Do nothing.
   5392     }
   5393 
   5394     /**
   5395      * Register a callback to be invoked when a hardware key is pressed in this view.
   5396      * Key presses in software input methods will generally not trigger the methods of
   5397      * this listener.
   5398      * @param l the key listener to attach to this view
   5399      */
   5400     public void setOnKeyListener(OnKeyListener l) {
   5401         getListenerInfo().mOnKeyListener = l;
   5402     }
   5403 
   5404     /**
   5405      * Register a callback to be invoked when a touch event is sent to this view.
   5406      * @param l the touch listener to attach to this view
   5407      */
   5408     public void setOnTouchListener(OnTouchListener l) {
   5409         getListenerInfo().mOnTouchListener = l;
   5410     }
   5411 
   5412     /**
   5413      * Register a callback to be invoked when a generic motion event is sent to this view.
   5414      * @param l the generic motion listener to attach to this view
   5415      */
   5416     public void setOnGenericMotionListener(OnGenericMotionListener l) {
   5417         getListenerInfo().mOnGenericMotionListener = l;
   5418     }
   5419 
   5420     /**
   5421      * Register a callback to be invoked when a hover event is sent to this view.
   5422      * @param l the hover listener to attach to this view
   5423      */
   5424     public void setOnHoverListener(OnHoverListener l) {
   5425         getListenerInfo().mOnHoverListener = l;
   5426     }
   5427 
   5428     /**
   5429      * Register a drag event listener callback object for this View. The parameter is
   5430      * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
   5431      * View, the system calls the
   5432      * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
   5433      * @param l An implementation of {@link android.view.View.OnDragListener}.
   5434      */
   5435     public void setOnDragListener(OnDragListener l) {
   5436         getListenerInfo().mOnDragListener = l;
   5437     }
   5438 
   5439     /**
   5440      * Give this view focus. This will cause
   5441      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
   5442      *
   5443      * Note: this does not check whether this {@link View} should get focus, it just
   5444      * gives it focus no matter what.  It should only be called internally by framework
   5445      * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
   5446      *
   5447      * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
   5448      *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
   5449      *        focus moved when requestFocus() is called. It may not always
   5450      *        apply, in which case use the default View.FOCUS_DOWN.
   5451      * @param previouslyFocusedRect The rectangle of the view that had focus
   5452      *        prior in this View's coordinate system.
   5453      */
   5454     void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
   5455         if (DBG) {
   5456             System.out.println(this + " requestFocus()");
   5457         }
   5458 
   5459         if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
   5460             mPrivateFlags |= PFLAG_FOCUSED;
   5461 
   5462             View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
   5463 
   5464             if (mParent != null) {
   5465                 mParent.requestChildFocus(this, this);
   5466             }
   5467 
   5468             if (mAttachInfo != null) {
   5469                 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
   5470             }
   5471 
   5472             onFocusChanged(true, direction, previouslyFocusedRect);
   5473             refreshDrawableState();
   5474         }
   5475     }
   5476 
   5477     /**
   5478      * Populates <code>outRect</code> with the hotspot bounds. By default,
   5479      * the hotspot bounds are identical to the screen bounds.
   5480      *
   5481      * @param outRect rect to populate with hotspot bounds
   5482      * @hide Only for internal use by views and widgets.
   5483      */
   5484     public void getHotspotBounds(Rect outRect) {
   5485         final Drawable background = getBackground();
   5486         if (background != null) {
   5487             background.getHotspotBounds(outRect);
   5488         } else {
   5489             getBoundsOnScreen(outRect);
   5490         }
   5491     }
   5492 
   5493     /**
   5494      * Request that a rectangle of this view be visible on the screen,
   5495      * scrolling if necessary just enough.
   5496      *
   5497      * <p>A View should call this if it maintains some notion of which part
   5498      * of its content is interesting.  For example, a text editing view
   5499      * should call this when its cursor moves.
   5500      *
   5501      * @param rectangle The rectangle.
   5502      * @return Whether any parent scrolled.
   5503      */
   5504     public boolean requestRectangleOnScreen(Rect rectangle) {
   5505         return requestRectangleOnScreen(rectangle, false);
   5506     }
   5507 
   5508     /**
   5509      * Request that a rectangle of this view be visible on the screen,
   5510      * scrolling if necessary just enough.
   5511      *
   5512      * <p>A View should call this if it maintains some notion of which part
   5513      * of its content is interesting.  For example, a text editing view
   5514      * should call this when its cursor moves.
   5515      *
   5516      * <p>When <code>immediate</code> is set to true, scrolling will not be
   5517      * animated.
   5518      *
   5519      * @param rectangle The rectangle.
   5520      * @param immediate True to forbid animated scrolling, false otherwise
   5521      * @return Whether any parent scrolled.
   5522      */
   5523     public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
   5524         if (mParent == null) {
   5525             return false;
   5526         }
   5527 
   5528         View child = this;
   5529 
   5530         RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
   5531         position.set(rectangle);
   5532 
   5533         ViewParent parent = mParent;
   5534         boolean scrolled = false;
   5535         while (parent != null) {
   5536             rectangle.set((int) position.left, (int) position.top,
   5537                     (int) position.right, (int) position.bottom);
   5538 
   5539             scrolled |= parent.requestChildRectangleOnScreen(child,
   5540                     rectangle, immediate);
   5541 
   5542             if (!child.hasIdentityMatrix()) {
   5543                 child.getMatrix().mapRect(position);
   5544             }
   5545 
   5546             position.offset(child.mLeft, child.mTop);
   5547 
   5548             if (!(parent instanceof View)) {
   5549                 break;
   5550             }
   5551 
   5552             View parentView = (View) parent;
   5553 
   5554             position.offset(-parentView.getScrollX(), -parentView.getScrollY());
   5555 
   5556             child = parentView;
   5557             parent = child.getParent();
   5558         }
   5559 
   5560         return scrolled;
   5561     }
   5562 
   5563     /**
   5564      * Called when this view wants to give up focus. If focus is cleared
   5565      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
   5566      * <p>
   5567      * <strong>Note:</strong> When a View clears focus the framework is trying
   5568      * to give focus to the first focusable View from the top. Hence, if this
   5569      * View is the first from the top that can take focus, then all callbacks
   5570      * related to clearing focus will be invoked after which the framework will
   5571      * give focus to this view.
   5572      * </p>
   5573      */
   5574     public void clearFocus() {
   5575         if (DBG) {
   5576             System.out.println(this + " clearFocus()");
   5577         }
   5578 
   5579         clearFocusInternal(null, true, true);
   5580     }
   5581 
   5582     /**
   5583      * Clears focus from the view, optionally propagating the change up through
   5584      * the parent hierarchy and requesting that the root view place new focus.
   5585      *
   5586      * @param propagate whether to propagate the change up through the parent
   5587      *            hierarchy
   5588      * @param refocus when propagate is true, specifies whether to request the
   5589      *            root view place new focus
   5590      */
   5591     void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
   5592         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
   5593             mPrivateFlags &= ~PFLAG_FOCUSED;
   5594 
   5595             if (propagate && mParent != null) {
   5596                 mParent.clearChildFocus(this);
   5597             }
   5598 
   5599             onFocusChanged(false, 0, null);
   5600             refreshDrawableState();
   5601 
   5602             if (propagate && (!refocus || !rootViewRequestFocus())) {
   5603                 notifyGlobalFocusCleared(this);
   5604             }
   5605         }
   5606     }
   5607 
   5608     void notifyGlobalFocusCleared(View oldFocus) {
   5609         if (oldFocus != null && mAttachInfo != null) {
   5610             mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
   5611         }
   5612     }
   5613 
   5614     boolean rootViewRequestFocus() {
   5615         final View root = getRootView();
   5616         return root != null && root.requestFocus();
   5617     }
   5618 
   5619     /**
   5620      * Called internally by the view system when a new view is getting focus.
   5621      * This is what clears the old focus.
   5622      * <p>
   5623      * <b>NOTE:</b> The parent view's focused child must be updated manually
   5624      * after calling this method. Otherwise, the view hierarchy may be left in
   5625      * an inconstent state.
   5626      */
   5627     void unFocus(View focused) {
   5628         if (DBG) {
   5629             System.out.println(this + " unFocus()");
   5630         }
   5631 
   5632         clearFocusInternal(focused, false, false);
   5633     }
   5634 
   5635     /**
   5636      * Returns true if this view has focus itself, or is the ancestor of the
   5637      * view that has focus.
   5638      *
   5639      * @return True if this view has or contains focus, false otherwise.
   5640      */
   5641     @ViewDebug.ExportedProperty(category = "focus")
   5642     public boolean hasFocus() {
   5643         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
   5644     }
   5645 
   5646     /**
   5647      * Returns true if this view is focusable or if it contains a reachable View
   5648      * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
   5649      * is a View whose parents do not block descendants focus.
   5650      *
   5651      * Only {@link #VISIBLE} views are considered focusable.
   5652      *
   5653      * @return True if the view is focusable or if the view contains a focusable
   5654      *         View, false otherwise.
   5655      *
   5656      * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
   5657      * @see ViewGroup#getTouchscreenBlocksFocus()
   5658      */
   5659     public boolean hasFocusable() {
   5660         if (!isFocusableInTouchMode()) {
   5661             for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
   5662                 final ViewGroup g = (ViewGroup) p;
   5663                 if (g.shouldBlockFocusForTouchscreen()) {
   5664                     return false;
   5665                 }
   5666             }
   5667         }
   5668         return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
   5669     }
   5670 
   5671     /**
   5672      * Called by the view system when the focus state of this view changes.
   5673      * When the focus change event is caused by directional navigation, direction
   5674      * and previouslyFocusedRect provide insight into where the focus is coming from.
   5675      * When overriding, be sure to call up through to the super class so that
   5676      * the standard focus handling will occur.
   5677      *
   5678      * @param gainFocus True if the View has focus; false otherwise.
   5679      * @param direction The direction focus has moved when requestFocus()
   5680      *                  is called to give this view focus. Values are
   5681      *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
   5682      *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
   5683      *                  It may not always apply, in which case use the default.
   5684      * @param previouslyFocusedRect The rectangle, in this view's coordinate
   5685      *        system, of the previously focused view.  If applicable, this will be
   5686      *        passed in as finer grained information about where the focus is coming
   5687      *        from (in addition to direction).  Will be <code>null</code> otherwise.
   5688      */
   5689     @CallSuper
   5690     protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
   5691             @Nullable Rect previouslyFocusedRect) {
   5692         if (gainFocus) {
   5693             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
   5694         } else {
   5695             notifyViewAccessibilityStateChangedIfNeeded(
   5696                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   5697         }
   5698 
   5699         InputMethodManager imm = InputMethodManager.peekInstance();
   5700         if (!gainFocus) {
   5701             if (isPressed()) {
   5702                 setPressed(false);
   5703             }
   5704             if (imm != null && mAttachInfo != null
   5705                     && mAttachInfo.mHasWindowFocus) {
   5706                 imm.focusOut(this);
   5707             }
   5708             onFocusLost();
   5709         } else if (imm != null && mAttachInfo != null
   5710                 && mAttachInfo.mHasWindowFocus) {
   5711             imm.focusIn(this);
   5712         }
   5713 
   5714         invalidate(true);
   5715         ListenerInfo li = mListenerInfo;
   5716         if (li != null && li.mOnFocusChangeListener != null) {
   5717             li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
   5718         }
   5719 
   5720         if (mAttachInfo != null) {
   5721             mAttachInfo.mKeyDispatchState.reset(this);
   5722         }
   5723     }
   5724 
   5725     /**
   5726      * Sends an accessibility event of the given type. If accessibility is
   5727      * not enabled this method has no effect. The default implementation calls
   5728      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
   5729      * to populate information about the event source (this View), then calls
   5730      * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
   5731      * populate the text content of the event source including its descendants,
   5732      * and last calls
   5733      * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
   5734      * on its parent to request sending of the event to interested parties.
   5735      * <p>
   5736      * If an {@link AccessibilityDelegate} has been specified via calling
   5737      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   5738      * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
   5739      * responsible for handling this call.
   5740      * </p>
   5741      *
   5742      * @param eventType The type of the event to send, as defined by several types from
   5743      * {@link android.view.accessibility.AccessibilityEvent}, such as
   5744      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
   5745      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
   5746      *
   5747      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
   5748      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   5749      * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
   5750      * @see AccessibilityDelegate
   5751      */
   5752     public void sendAccessibilityEvent(int eventType) {
   5753         if (mAccessibilityDelegate != null) {
   5754             mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
   5755         } else {
   5756             sendAccessibilityEventInternal(eventType);
   5757         }
   5758     }
   5759 
   5760     /**
   5761      * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
   5762      * {@link AccessibilityEvent} to make an announcement which is related to some
   5763      * sort of a context change for which none of the events representing UI transitions
   5764      * is a good fit. For example, announcing a new page in a book. If accessibility
   5765      * is not enabled this method does nothing.
   5766      *
   5767      * @param text The announcement text.
   5768      */
   5769     public void announceForAccessibility(CharSequence text) {
   5770         if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
   5771             AccessibilityEvent event = AccessibilityEvent.obtain(
   5772                     AccessibilityEvent.TYPE_ANNOUNCEMENT);
   5773             onInitializeAccessibilityEvent(event);
   5774             event.getText().add(text);
   5775             event.setContentDescription(null);
   5776             mParent.requestSendAccessibilityEvent(this, event);
   5777         }
   5778     }
   5779 
   5780     /**
   5781      * @see #sendAccessibilityEvent(int)
   5782      *
   5783      * Note: Called from the default {@link AccessibilityDelegate}.
   5784      *
   5785      * @hide
   5786      */
   5787     public void sendAccessibilityEventInternal(int eventType) {
   5788         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
   5789             sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
   5790         }
   5791     }
   5792 
   5793     /**
   5794      * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
   5795      * takes as an argument an empty {@link AccessibilityEvent} and does not
   5796      * perform a check whether accessibility is enabled.
   5797      * <p>
   5798      * If an {@link AccessibilityDelegate} has been specified via calling
   5799      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   5800      * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
   5801      * is responsible for handling this call.
   5802      * </p>
   5803      *
   5804      * @param event The event to send.
   5805      *
   5806      * @see #sendAccessibilityEvent(int)
   5807      */
   5808     public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
   5809         if (mAccessibilityDelegate != null) {
   5810             mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
   5811         } else {
   5812             sendAccessibilityEventUncheckedInternal(event);
   5813         }
   5814     }
   5815 
   5816     /**
   5817      * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
   5818      *
   5819      * Note: Called from the default {@link AccessibilityDelegate}.
   5820      *
   5821      * @hide
   5822      */
   5823     public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
   5824         if (!isShown()) {
   5825             return;
   5826         }
   5827         onInitializeAccessibilityEvent(event);
   5828         // Only a subset of accessibility events populates text content.
   5829         if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
   5830             dispatchPopulateAccessibilityEvent(event);
   5831         }
   5832         // In the beginning we called #isShown(), so we know that getParent() is not null.
   5833         getParent().requestSendAccessibilityEvent(this, event);
   5834     }
   5835 
   5836     /**
   5837      * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
   5838      * to its children for adding their text content to the event. Note that the
   5839      * event text is populated in a separate dispatch path since we add to the
   5840      * event not only the text of the source but also the text of all its descendants.
   5841      * A typical implementation will call
   5842      * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
   5843      * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
   5844      * on each child. Override this method if custom population of the event text
   5845      * content is required.
   5846      * <p>
   5847      * If an {@link AccessibilityDelegate} has been specified via calling
   5848      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   5849      * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
   5850      * is responsible for handling this call.
   5851      * </p>
   5852      * <p>
   5853      * <em>Note:</em> Accessibility events of certain types are not dispatched for
   5854      * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
   5855      * </p>
   5856      *
   5857      * @param event The event.
   5858      *
   5859      * @return True if the event population was completed.
   5860      */
   5861     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
   5862         if (mAccessibilityDelegate != null) {
   5863             return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
   5864         } else {
   5865             return dispatchPopulateAccessibilityEventInternal(event);
   5866         }
   5867     }
   5868 
   5869     /**
   5870      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   5871      *
   5872      * Note: Called from the default {@link AccessibilityDelegate}.
   5873      *
   5874      * @hide
   5875      */
   5876     public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
   5877         onPopulateAccessibilityEvent(event);
   5878         return false;
   5879     }
   5880 
   5881     /**
   5882      * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
   5883      * giving a chance to this View to populate the accessibility event with its
   5884      * text content. While this method is free to modify event
   5885      * attributes other than text content, doing so should normally be performed in
   5886      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
   5887      * <p>
   5888      * Example: Adding formatted date string to an accessibility event in addition
   5889      *          to the text added by the super implementation:
   5890      * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
   5891      *     super.onPopulateAccessibilityEvent(event);
   5892      *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
   5893      *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
   5894      *         mCurrentDate.getTimeInMillis(), flags);
   5895      *     event.getText().add(selectedDateUtterance);
   5896      * }</pre>
   5897      * <p>
   5898      * If an {@link AccessibilityDelegate} has been specified via calling
   5899      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   5900      * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
   5901      * is responsible for handling this call.
   5902      * </p>
   5903      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
   5904      * information to the event, in case the default implementation has basic information to add.
   5905      * </p>
   5906      *
   5907      * @param event The accessibility event which to populate.
   5908      *
   5909      * @see #sendAccessibilityEvent(int)
   5910      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   5911      */
   5912     @CallSuper
   5913     public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
   5914         if (mAccessibilityDelegate != null) {
   5915             mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
   5916         } else {
   5917             onPopulateAccessibilityEventInternal(event);
   5918         }
   5919     }
   5920 
   5921     /**
   5922      * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
   5923      *
   5924      * Note: Called from the default {@link AccessibilityDelegate}.
   5925      *
   5926      * @hide
   5927      */
   5928     public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
   5929     }
   5930 
   5931     /**
   5932      * Initializes an {@link AccessibilityEvent} with information about
   5933      * this View which is the event source. In other words, the source of
   5934      * an accessibility event is the view whose state change triggered firing
   5935      * the event.
   5936      * <p>
   5937      * Example: Setting the password property of an event in addition
   5938      *          to properties set by the super implementation:
   5939      * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
   5940      *     super.onInitializeAccessibilityEvent(event);
   5941      *     event.setPassword(true);
   5942      * }</pre>
   5943      * <p>
   5944      * If an {@link AccessibilityDelegate} has been specified via calling
   5945      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   5946      * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
   5947      * is responsible for handling this call.
   5948      * </p>
   5949      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
   5950      * information to the event, in case the default implementation has basic information to add.
   5951      * </p>
   5952      * @param event The event to initialize.
   5953      *
   5954      * @see #sendAccessibilityEvent(int)
   5955      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   5956      */
   5957     @CallSuper
   5958     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
   5959         if (mAccessibilityDelegate != null) {
   5960             mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
   5961         } else {
   5962             onInitializeAccessibilityEventInternal(event);
   5963         }
   5964     }
   5965 
   5966     /**
   5967      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
   5968      *
   5969      * Note: Called from the default {@link AccessibilityDelegate}.
   5970      *
   5971      * @hide
   5972      */
   5973     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
   5974         event.setSource(this);
   5975         event.setClassName(getAccessibilityClassName());
   5976         event.setPackageName(getContext().getPackageName());
   5977         event.setEnabled(isEnabled());
   5978         event.setContentDescription(mContentDescription);
   5979 
   5980         switch (event.getEventType()) {
   5981             case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
   5982                 ArrayList<View> focusablesTempList = (mAttachInfo != null)
   5983                         ? mAttachInfo.mTempArrayList : new ArrayList<View>();
   5984                 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
   5985                 event.setItemCount(focusablesTempList.size());
   5986                 event.setCurrentItemIndex(focusablesTempList.indexOf(this));
   5987                 if (mAttachInfo != null) {
   5988                     focusablesTempList.clear();
   5989                 }
   5990             } break;
   5991             case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
   5992                 CharSequence text = getIterableTextForAccessibility();
   5993                 if (text != null && text.length() > 0) {
   5994                     event.setFromIndex(getAccessibilitySelectionStart());
   5995                     event.setToIndex(getAccessibilitySelectionEnd());
   5996                     event.setItemCount(text.length());
   5997                 }
   5998             } break;
   5999         }
   6000     }
   6001 
   6002     /**
   6003      * Returns an {@link AccessibilityNodeInfo} representing this view from the
   6004      * point of view of an {@link android.accessibilityservice.AccessibilityService}.
   6005      * This method is responsible for obtaining an accessibility node info from a
   6006      * pool of reusable instances and calling
   6007      * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
   6008      * initialize the former.
   6009      * <p>
   6010      * Note: The client is responsible for recycling the obtained instance by calling
   6011      *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
   6012      * </p>
   6013      *
   6014      * @return A populated {@link AccessibilityNodeInfo}.
   6015      *
   6016      * @see AccessibilityNodeInfo
   6017      */
   6018     public AccessibilityNodeInfo createAccessibilityNodeInfo() {
   6019         if (mAccessibilityDelegate != null) {
   6020             return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
   6021         } else {
   6022             return createAccessibilityNodeInfoInternal();
   6023         }
   6024     }
   6025 
   6026     /**
   6027      * @see #createAccessibilityNodeInfo()
   6028      *
   6029      * @hide
   6030      */
   6031     public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
   6032         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
   6033         if (provider != null) {
   6034             return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
   6035         } else {
   6036             AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
   6037             onInitializeAccessibilityNodeInfo(info);
   6038             return info;
   6039         }
   6040     }
   6041 
   6042     /**
   6043      * Initializes an {@link AccessibilityNodeInfo} with information about this view.
   6044      * The base implementation sets:
   6045      * <ul>
   6046      *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
   6047      *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
   6048      *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
   6049      *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
   6050      *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
   6051      *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
   6052      *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
   6053      *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
   6054      *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
   6055      *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
   6056      *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
   6057      *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
   6058      *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
   6059      * </ul>
   6060      * <p>
   6061      * Subclasses should override this method, call the super implementation,
   6062      * and set additional attributes.
   6063      * </p>
   6064      * <p>
   6065      * If an {@link AccessibilityDelegate} has been specified via calling
   6066      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   6067      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
   6068      * is responsible for handling this call.
   6069      * </p>
   6070      *
   6071      * @param info The instance to initialize.
   6072      */
   6073     @CallSuper
   6074     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
   6075         if (mAccessibilityDelegate != null) {
   6076             mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
   6077         } else {
   6078             onInitializeAccessibilityNodeInfoInternal(info);
   6079         }
   6080     }
   6081 
   6082     /**
   6083      * Gets the location of this view in screen coordinates.
   6084      *
   6085      * @param outRect The output location
   6086      * @hide
   6087      */
   6088     public void getBoundsOnScreen(Rect outRect) {
   6089         getBoundsOnScreen(outRect, false);
   6090     }
   6091 
   6092     /**
   6093      * Gets the location of this view in screen coordinates.
   6094      *
   6095      * @param outRect The output location
   6096      * @param clipToParent Whether to clip child bounds to the parent ones.
   6097      * @hide
   6098      */
   6099     public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
   6100         if (mAttachInfo == null) {
   6101             return;
   6102         }
   6103 
   6104         RectF position = mAttachInfo.mTmpTransformRect;
   6105         position.set(0, 0, mRight - mLeft, mBottom - mTop);
   6106 
   6107         if (!hasIdentityMatrix()) {
   6108             getMatrix().mapRect(position);
   6109         }
   6110 
   6111         position.offset(mLeft, mTop);
   6112 
   6113         ViewParent parent = mParent;
   6114         while (parent instanceof View) {
   6115             View parentView = (View) parent;
   6116 
   6117             position.offset(-parentView.mScrollX, -parentView.mScrollY);
   6118 
   6119             if (clipToParent) {
   6120                 position.left = Math.max(position.left, 0);
   6121                 position.top = Math.max(position.top, 0);
   6122                 position.right = Math.min(position.right, parentView.getWidth());
   6123                 position.bottom = Math.min(position.bottom, parentView.getHeight());
   6124             }
   6125 
   6126             if (!parentView.hasIdentityMatrix()) {
   6127                 parentView.getMatrix().mapRect(position);
   6128             }
   6129 
   6130             position.offset(parentView.mLeft, parentView.mTop);
   6131 
   6132             parent = parentView.mParent;
   6133         }
   6134 
   6135         if (parent instanceof ViewRootImpl) {
   6136             ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
   6137             position.offset(0, -viewRootImpl.mCurScrollY);
   6138         }
   6139 
   6140         position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
   6141 
   6142         outRect.set((int) (position.left + 0.5f), (int) (position.top + 0.5f),
   6143                 (int) (position.right + 0.5f), (int) (position.bottom + 0.5f));
   6144     }
   6145 
   6146     /**
   6147      * Return the class name of this object to be used for accessibility purposes.
   6148      * Subclasses should only override this if they are implementing something that
   6149      * should be seen as a completely new class of view when used by accessibility,
   6150      * unrelated to the class it is deriving from.  This is used to fill in
   6151      * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
   6152      */
   6153     public CharSequence getAccessibilityClassName() {
   6154         return View.class.getName();
   6155     }
   6156 
   6157     /**
   6158      * Called when assist structure is being retrieved from a view as part of
   6159      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
   6160      * @param structure Fill in with structured view data.  The default implementation
   6161      * fills in all data that can be inferred from the view itself.
   6162      */
   6163     public void onProvideStructure(ViewStructure structure) {
   6164         final int id = mID;
   6165         if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0
   6166                 && (id&0x0000ffff) != 0) {
   6167             String pkg, type, entry;
   6168             try {
   6169                 final Resources res = getResources();
   6170                 entry = res.getResourceEntryName(id);
   6171                 type = res.getResourceTypeName(id);
   6172                 pkg = res.getResourcePackageName(id);
   6173             } catch (Resources.NotFoundException e) {
   6174                 entry = type = pkg = null;
   6175             }
   6176             structure.setId(id, pkg, type, entry);
   6177         } else {
   6178             structure.setId(id, null, null, null);
   6179         }
   6180         structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
   6181         if (!hasIdentityMatrix()) {
   6182             structure.setTransformation(getMatrix());
   6183         }
   6184         structure.setElevation(getZ());
   6185         structure.setVisibility(getVisibility());
   6186         structure.setEnabled(isEnabled());
   6187         if (isClickable()) {
   6188             structure.setClickable(true);
   6189         }
   6190         if (isFocusable()) {
   6191             structure.setFocusable(true);
   6192         }
   6193         if (isFocused()) {
   6194             structure.setFocused(true);
   6195         }
   6196         if (isAccessibilityFocused()) {
   6197             structure.setAccessibilityFocused(true);
   6198         }
   6199         if (isSelected()) {
   6200             structure.setSelected(true);
   6201         }
   6202         if (isActivated()) {
   6203             structure.setActivated(true);
   6204         }
   6205         if (isLongClickable()) {
   6206             structure.setLongClickable(true);
   6207         }
   6208         if (this instanceof Checkable) {
   6209             structure.setCheckable(true);
   6210             if (((Checkable)this).isChecked()) {
   6211                 structure.setChecked(true);
   6212             }
   6213         }
   6214         if (isContextClickable()) {
   6215             structure.setContextClickable(true);
   6216         }
   6217         structure.setClassName(getAccessibilityClassName().toString());
   6218         structure.setContentDescription(getContentDescription());
   6219     }
   6220 
   6221     /**
   6222      * Called when assist structure is being retrieved from a view as part of
   6223      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
   6224      * generate additional virtual structure under this view.  The defaullt implementation
   6225      * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
   6226      * view's virtual accessibility nodes, if any.  You can override this for a more
   6227      * optimal implementation providing this data.
   6228      */
   6229     public void onProvideVirtualStructure(ViewStructure structure) {
   6230         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
   6231         if (provider != null) {
   6232             AccessibilityNodeInfo info = createAccessibilityNodeInfo();
   6233             structure.setChildCount(1);
   6234             ViewStructure root = structure.newChild(0);
   6235             populateVirtualStructure(root, provider, info);
   6236             info.recycle();
   6237         }
   6238     }
   6239 
   6240     private void populateVirtualStructure(ViewStructure structure,
   6241             AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
   6242         structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
   6243                 null, null, null);
   6244         Rect rect = structure.getTempRect();
   6245         info.getBoundsInParent(rect);
   6246         structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
   6247         structure.setVisibility(VISIBLE);
   6248         structure.setEnabled(info.isEnabled());
   6249         if (info.isClickable()) {
   6250             structure.setClickable(true);
   6251         }
   6252         if (info.isFocusable()) {
   6253             structure.setFocusable(true);
   6254         }
   6255         if (info.isFocused()) {
   6256             structure.setFocused(true);
   6257         }
   6258         if (info.isAccessibilityFocused()) {
   6259             structure.setAccessibilityFocused(true);
   6260         }
   6261         if (info.isSelected()) {
   6262             structure.setSelected(true);
   6263         }
   6264         if (info.isLongClickable()) {
   6265             structure.setLongClickable(true);
   6266         }
   6267         if (info.isCheckable()) {
   6268             structure.setCheckable(true);
   6269             if (info.isChecked()) {
   6270                 structure.setChecked(true);
   6271             }
   6272         }
   6273         if (info.isContextClickable()) {
   6274             structure.setContextClickable(true);
   6275         }
   6276         CharSequence cname = info.getClassName();
   6277         structure.setClassName(cname != null ? cname.toString() : null);
   6278         structure.setContentDescription(info.getContentDescription());
   6279         if (info.getText() != null || info.getError() != null) {
   6280             structure.setText(info.getText(), info.getTextSelectionStart(),
   6281                     info.getTextSelectionEnd());
   6282         }
   6283         final int NCHILDREN = info.getChildCount();
   6284         if (NCHILDREN > 0) {
   6285             structure.setChildCount(NCHILDREN);
   6286             for (int i=0; i<NCHILDREN; i++) {
   6287                 AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
   6288                         AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
   6289                 ViewStructure child = structure.newChild(i);
   6290                 populateVirtualStructure(child, provider, cinfo);
   6291                 cinfo.recycle();
   6292             }
   6293         }
   6294     }
   6295 
   6296     /**
   6297      * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
   6298      * implementation calls {@link #onProvideStructure} and
   6299      * {@link #onProvideVirtualStructure}.
   6300      */
   6301     public void dispatchProvideStructure(ViewStructure structure) {
   6302         if (!isAssistBlocked()) {
   6303             onProvideStructure(structure);
   6304             onProvideVirtualStructure(structure);
   6305         } else {
   6306             structure.setClassName(getAccessibilityClassName().toString());
   6307             structure.setAssistBlocked(true);
   6308         }
   6309     }
   6310 
   6311     /**
   6312      * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
   6313      *
   6314      * Note: Called from the default {@link AccessibilityDelegate}.
   6315      *
   6316      * @hide
   6317      */
   6318     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
   6319         if (mAttachInfo == null) {
   6320             return;
   6321         }
   6322 
   6323         Rect bounds = mAttachInfo.mTmpInvalRect;
   6324 
   6325         getDrawingRect(bounds);
   6326         info.setBoundsInParent(bounds);
   6327 
   6328         getBoundsOnScreen(bounds, true);
   6329         info.setBoundsInScreen(bounds);
   6330 
   6331         ViewParent parent = getParentForAccessibility();
   6332         if (parent instanceof View) {
   6333             info.setParent((View) parent);
   6334         }
   6335 
   6336         if (mID != View.NO_ID) {
   6337             View rootView = getRootView();
   6338             if (rootView == null) {
   6339                 rootView = this;
   6340             }
   6341 
   6342             View label = rootView.findLabelForView(this, mID);
   6343             if (label != null) {
   6344                 info.setLabeledBy(label);
   6345             }
   6346 
   6347             if ((mAttachInfo.mAccessibilityFetchFlags
   6348                     & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
   6349                     && Resources.resourceHasPackage(mID)) {
   6350                 try {
   6351                     String viewId = getResources().getResourceName(mID);
   6352                     info.setViewIdResourceName(viewId);
   6353                 } catch (Resources.NotFoundException nfe) {
   6354                     /* ignore */
   6355                 }
   6356             }
   6357         }
   6358 
   6359         if (mLabelForId != View.NO_ID) {
   6360             View rootView = getRootView();
   6361             if (rootView == null) {
   6362                 rootView = this;
   6363             }
   6364             View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
   6365             if (labeled != null) {
   6366                 info.setLabelFor(labeled);
   6367             }
   6368         }
   6369 
   6370         if (mAccessibilityTraversalBeforeId != View.NO_ID) {
   6371             View rootView = getRootView();
   6372             if (rootView == null) {
   6373                 rootView = this;
   6374             }
   6375             View next = rootView.findViewInsideOutShouldExist(this,
   6376                     mAccessibilityTraversalBeforeId);
   6377             if (next != null && next.includeForAccessibility()) {
   6378                 info.setTraversalBefore(next);
   6379             }
   6380         }
   6381 
   6382         if (mAccessibilityTraversalAfterId != View.NO_ID) {
   6383             View rootView = getRootView();
   6384             if (rootView == null) {
   6385                 rootView = this;
   6386             }
   6387             View next = rootView.findViewInsideOutShouldExist(this,
   6388                     mAccessibilityTraversalAfterId);
   6389             if (next != null && next.includeForAccessibility()) {
   6390                 info.setTraversalAfter(next);
   6391             }
   6392         }
   6393 
   6394         info.setVisibleToUser(isVisibleToUser());
   6395 
   6396         info.setPackageName(mContext.getPackageName());
   6397         info.setClassName(getAccessibilityClassName());
   6398         info.setContentDescription(getContentDescription());
   6399 
   6400         info.setEnabled(isEnabled());
   6401         info.setClickable(isClickable());
   6402         info.setFocusable(isFocusable());
   6403         info.setFocused(isFocused());
   6404         info.setAccessibilityFocused(isAccessibilityFocused());
   6405         info.setSelected(isSelected());
   6406         info.setLongClickable(isLongClickable());
   6407         info.setContextClickable(isContextClickable());
   6408         info.setLiveRegion(getAccessibilityLiveRegion());
   6409 
   6410         // TODO: These make sense only if we are in an AdapterView but all
   6411         // views can be selected. Maybe from accessibility perspective
   6412         // we should report as selectable view in an AdapterView.
   6413         info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
   6414         info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
   6415 
   6416         if (isFocusable()) {
   6417             if (isFocused()) {
   6418                 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
   6419             } else {
   6420                 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
   6421             }
   6422         }
   6423 
   6424         if (!isAccessibilityFocused()) {
   6425             info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
   6426         } else {
   6427             info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
   6428         }
   6429 
   6430         if (isClickable() && isEnabled()) {
   6431             info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
   6432         }
   6433 
   6434         if (isLongClickable() && isEnabled()) {
   6435             info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
   6436         }
   6437 
   6438         if (isContextClickable() && isEnabled()) {
   6439             info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
   6440         }
   6441 
   6442         CharSequence text = getIterableTextForAccessibility();
   6443         if (text != null && text.length() > 0) {
   6444             info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
   6445 
   6446             info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
   6447             info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
   6448             info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
   6449             info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
   6450                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
   6451                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
   6452         }
   6453 
   6454         info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
   6455     }
   6456 
   6457     private View findLabelForView(View view, int labeledId) {
   6458         if (mMatchLabelForPredicate == null) {
   6459             mMatchLabelForPredicate = new MatchLabelForPredicate();
   6460         }
   6461         mMatchLabelForPredicate.mLabeledId = labeledId;
   6462         return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
   6463     }
   6464 
   6465     /**
   6466      * Computes whether this view is visible to the user. Such a view is
   6467      * attached, visible, all its predecessors are visible, it is not clipped
   6468      * entirely by its predecessors, and has an alpha greater than zero.
   6469      *
   6470      * @return Whether the view is visible on the screen.
   6471      *
   6472      * @hide
   6473      */
   6474     protected boolean isVisibleToUser() {
   6475         return isVisibleToUser(null);
   6476     }
   6477 
   6478     /**
   6479      * Computes whether the given portion of this view is visible to the user.
   6480      * Such a view is attached, visible, all its predecessors are visible,
   6481      * has an alpha greater than zero, and the specified portion is not
   6482      * clipped entirely by its predecessors.
   6483      *
   6484      * @param boundInView the portion of the view to test; coordinates should be relative; may be
   6485      *                    <code>null</code>, and the entire view will be tested in this case.
   6486      *                    When <code>true</code> is returned by the function, the actual visible
   6487      *                    region will be stored in this parameter; that is, if boundInView is fully
   6488      *                    contained within the view, no modification will be made, otherwise regions
   6489      *                    outside of the visible area of the view will be clipped.
   6490      *
   6491      * @return Whether the specified portion of the view is visible on the screen.
   6492      *
   6493      * @hide
   6494      */
   6495     protected boolean isVisibleToUser(Rect boundInView) {
   6496         if (mAttachInfo != null) {
   6497             // Attached to invisible window means this view is not visible.
   6498             if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
   6499                 return false;
   6500             }
   6501             // An invisible predecessor or one with alpha zero means
   6502             // that this view is not visible to the user.
   6503             Object current = this;
   6504             while (current instanceof View) {
   6505                 View view = (View) current;
   6506                 // We have attach info so this view is attached and there is no
   6507                 // need to check whether we reach to ViewRootImpl on the way up.
   6508                 if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
   6509                         view.getVisibility() != VISIBLE) {
   6510                     return false;
   6511                 }
   6512                 current = view.mParent;
   6513             }
   6514             // Check if the view is entirely covered by its predecessors.
   6515             Rect visibleRect = mAttachInfo.mTmpInvalRect;
   6516             Point offset = mAttachInfo.mPoint;
   6517             if (!getGlobalVisibleRect(visibleRect, offset)) {
   6518                 return false;
   6519             }
   6520             // Check if the visible portion intersects the rectangle of interest.
   6521             if (boundInView != null) {
   6522                 visibleRect.offset(-offset.x, -offset.y);
   6523                 return boundInView.intersect(visibleRect);
   6524             }
   6525             return true;
   6526         }
   6527         return false;
   6528     }
   6529 
   6530     /**
   6531      * Returns the delegate for implementing accessibility support via
   6532      * composition. For more details see {@link AccessibilityDelegate}.
   6533      *
   6534      * @return The delegate, or null if none set.
   6535      *
   6536      * @hide
   6537      */
   6538     public AccessibilityDelegate getAccessibilityDelegate() {
   6539         return mAccessibilityDelegate;
   6540     }
   6541 
   6542     /**
   6543      * Sets a delegate for implementing accessibility support via composition as
   6544      * opposed to inheritance. The delegate's primary use is for implementing
   6545      * backwards compatible widgets. For more details see {@link AccessibilityDelegate}.
   6546      *
   6547      * @param delegate The delegate instance.
   6548      *
   6549      * @see AccessibilityDelegate
   6550      */
   6551     public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
   6552         mAccessibilityDelegate = delegate;
   6553     }
   6554 
   6555     /**
   6556      * Gets the provider for managing a virtual view hierarchy rooted at this View
   6557      * and reported to {@link android.accessibilityservice.AccessibilityService}s
   6558      * that explore the window content.
   6559      * <p>
   6560      * If this method returns an instance, this instance is responsible for managing
   6561      * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
   6562      * View including the one representing the View itself. Similarly the returned
   6563      * instance is responsible for performing accessibility actions on any virtual
   6564      * view or the root view itself.
   6565      * </p>
   6566      * <p>
   6567      * If an {@link AccessibilityDelegate} has been specified via calling
   6568      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   6569      * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
   6570      * is responsible for handling this call.
   6571      * </p>
   6572      *
   6573      * @return The provider.
   6574      *
   6575      * @see AccessibilityNodeProvider
   6576      */
   6577     public AccessibilityNodeProvider getAccessibilityNodeProvider() {
   6578         if (mAccessibilityDelegate != null) {
   6579             return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
   6580         } else {
   6581             return null;
   6582         }
   6583     }
   6584 
   6585     /**
   6586      * Gets the unique identifier of this view on the screen for accessibility purposes.
   6587      * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
   6588      *
   6589      * @return The view accessibility id.
   6590      *
   6591      * @hide
   6592      */
   6593     public int getAccessibilityViewId() {
   6594         if (mAccessibilityViewId == NO_ID) {
   6595             mAccessibilityViewId = sNextAccessibilityViewId++;
   6596         }
   6597         return mAccessibilityViewId;
   6598     }
   6599 
   6600     /**
   6601      * Gets the unique identifier of the window in which this View reseides.
   6602      *
   6603      * @return The window accessibility id.
   6604      *
   6605      * @hide
   6606      */
   6607     public int getAccessibilityWindowId() {
   6608         return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
   6609                 : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
   6610     }
   6611 
   6612     /**
   6613      * Gets the {@link View} description. It briefly describes the view and is
   6614      * primarily used for accessibility support. Set this property to enable
   6615      * better accessibility support for your application. This is especially
   6616      * true for views that do not have textual representation (For example,
   6617      * ImageButton).
   6618      *
   6619      * @return The content description.
   6620      *
   6621      * @attr ref android.R.styleable#View_contentDescription
   6622      */
   6623     @ViewDebug.ExportedProperty(category = "accessibility")
   6624     public CharSequence getContentDescription() {
   6625         return mContentDescription;
   6626     }
   6627 
   6628     /**
   6629      * Sets the {@link View} description. It briefly describes the view and is
   6630      * primarily used for accessibility support. Set this property to enable
   6631      * better accessibility support for your application. This is especially
   6632      * true for views that do not have textual representation (For example,
   6633      * ImageButton).
   6634      *
   6635      * @param contentDescription The content description.
   6636      *
   6637      * @attr ref android.R.styleable#View_contentDescription
   6638      */
   6639     @RemotableViewMethod
   6640     public void setContentDescription(CharSequence contentDescription) {
   6641         if (mContentDescription == null) {
   6642             if (contentDescription == null) {
   6643                 return;
   6644             }
   6645         } else if (mContentDescription.equals(contentDescription)) {
   6646             return;
   6647         }
   6648         mContentDescription = contentDescription;
   6649         final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
   6650         if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
   6651             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
   6652             notifySubtreeAccessibilityStateChangedIfNeeded();
   6653         } else {
   6654             notifyViewAccessibilityStateChangedIfNeeded(
   6655                     AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
   6656         }
   6657     }
   6658 
   6659     /**
   6660      * Sets the id of a view before which this one is visited in accessibility traversal.
   6661      * A screen-reader must visit the content of this view before the content of the one
   6662      * it precedes. For example, if view B is set to be before view A, then a screen-reader
   6663      * will traverse the entire content of B before traversing the entire content of A,
   6664      * regardles of what traversal strategy it is using.
   6665      * <p>
   6666      * Views that do not have specified before/after relationships are traversed in order
   6667      * determined by the screen-reader.
   6668      * </p>
   6669      * <p>
   6670      * Setting that this view is before a view that is not important for accessibility
   6671      * or if this view is not important for accessibility will have no effect as the
   6672      * screen-reader is not aware of unimportant views.
   6673      * </p>
   6674      *
   6675      * @param beforeId The id of a view this one precedes in accessibility traversal.
   6676      *
   6677      * @attr ref android.R.styleable#View_accessibilityTraversalBefore
   6678      *
   6679      * @see #setImportantForAccessibility(int)
   6680      */
   6681     @RemotableViewMethod
   6682     public void setAccessibilityTraversalBefore(int beforeId) {
   6683         if (mAccessibilityTraversalBeforeId == beforeId) {
   6684             return;
   6685         }
   6686         mAccessibilityTraversalBeforeId = beforeId;
   6687         notifyViewAccessibilityStateChangedIfNeeded(
   6688                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   6689     }
   6690 
   6691     /**
   6692      * Gets the id of a view before which this one is visited in accessibility traversal.
   6693      *
   6694      * @return The id of a view this one precedes in accessibility traversal if
   6695      *         specified, otherwise {@link #NO_ID}.
   6696      *
   6697      * @see #setAccessibilityTraversalBefore(int)
   6698      */
   6699     public int getAccessibilityTraversalBefore() {
   6700         return mAccessibilityTraversalBeforeId;
   6701     }
   6702 
   6703     /**
   6704      * Sets the id of a view after which this one is visited in accessibility traversal.
   6705      * A screen-reader must visit the content of the other view before the content of this
   6706      * one. For example, if view B is set to be after view A, then a screen-reader
   6707      * will traverse the entire content of A before traversing the entire content of B,
   6708      * regardles of what traversal strategy it is using.
   6709      * <p>
   6710      * Views that do not have specified before/after relationships are traversed in order
   6711      * determined by the screen-reader.
   6712      * </p>
   6713      * <p>
   6714      * Setting that this view is after a view that is not important for accessibility
   6715      * or if this view is not important for accessibility will have no effect as the
   6716      * screen-reader is not aware of unimportant views.
   6717      * </p>
   6718      *
   6719      * @param afterId The id of a view this one succedees in accessibility traversal.
   6720      *
   6721      * @attr ref android.R.styleable#View_accessibilityTraversalAfter
   6722      *
   6723      * @see #setImportantForAccessibility(int)
   6724      */
   6725     @RemotableViewMethod
   6726     public void setAccessibilityTraversalAfter(int afterId) {
   6727         if (mAccessibilityTraversalAfterId == afterId) {
   6728             return;
   6729         }
   6730         mAccessibilityTraversalAfterId = afterId;
   6731         notifyViewAccessibilityStateChangedIfNeeded(
   6732                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   6733     }
   6734 
   6735     /**
   6736      * Gets the id of a view after which this one is visited in accessibility traversal.
   6737      *
   6738      * @return The id of a view this one succeedes in accessibility traversal if
   6739      *         specified, otherwise {@link #NO_ID}.
   6740      *
   6741      * @see #setAccessibilityTraversalAfter(int)
   6742      */
   6743     public int getAccessibilityTraversalAfter() {
   6744         return mAccessibilityTraversalAfterId;
   6745     }
   6746 
   6747     /**
   6748      * Gets the id of a view for which this view serves as a label for
   6749      * accessibility purposes.
   6750      *
   6751      * @return The labeled view id.
   6752      */
   6753     @ViewDebug.ExportedProperty(category = "accessibility")
   6754     public int getLabelFor() {
   6755         return mLabelForId;
   6756     }
   6757 
   6758     /**
   6759      * Sets the id of a view for which this view serves as a label for
   6760      * accessibility purposes.
   6761      *
   6762      * @param id The labeled view id.
   6763      */
   6764     @RemotableViewMethod
   6765     public void setLabelFor(@IdRes int id) {
   6766         if (mLabelForId == id) {
   6767             return;
   6768         }
   6769         mLabelForId = id;
   6770         if (mLabelForId != View.NO_ID
   6771                 && mID == View.NO_ID) {
   6772             mID = generateViewId();
   6773         }
   6774         notifyViewAccessibilityStateChangedIfNeeded(
   6775                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   6776     }
   6777 
   6778     /**
   6779      * Invoked whenever this view loses focus, either by losing window focus or by losing
   6780      * focus within its window. This method can be used to clear any state tied to the
   6781      * focus. For instance, if a button is held pressed with the trackball and the window
   6782      * loses focus, this method can be used to cancel the press.
   6783      *
   6784      * Subclasses of View overriding this method should always call super.onFocusLost().
   6785      *
   6786      * @see #onFocusChanged(boolean, int, android.graphics.Rect)
   6787      * @see #onWindowFocusChanged(boolean)
   6788      *
   6789      * @hide pending API council approval
   6790      */
   6791     @CallSuper
   6792     protected void onFocusLost() {
   6793         resetPressedState();
   6794     }
   6795 
   6796     private void resetPressedState() {
   6797         if ((mViewFlags & ENABLED_MASK) == DISABLED) {
   6798             return;
   6799         }
   6800 
   6801         if (isPressed()) {
   6802             setPressed(false);
   6803 
   6804             if (!mHasPerformedLongPress) {
   6805                 removeLongPressCallback();
   6806             }
   6807         }
   6808     }
   6809 
   6810     /**
   6811      * Returns true if this view has focus
   6812      *
   6813      * @return True if this view has focus, false otherwise.
   6814      */
   6815     @ViewDebug.ExportedProperty(category = "focus")
   6816     public boolean isFocused() {
   6817         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
   6818     }
   6819 
   6820     /**
   6821      * Find the view in the hierarchy rooted at this view that currently has
   6822      * focus.
   6823      *
   6824      * @return The view that currently has focus, or null if no focused view can
   6825      *         be found.
   6826      */
   6827     public View findFocus() {
   6828         return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
   6829     }
   6830 
   6831     /**
   6832      * Indicates whether this view is one of the set of scrollable containers in
   6833      * its window.
   6834      *
   6835      * @return whether this view is one of the set of scrollable containers in
   6836      * its window
   6837      *
   6838      * @attr ref android.R.styleable#View_isScrollContainer
   6839      */
   6840     public boolean isScrollContainer() {
   6841         return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
   6842     }
   6843 
   6844     /**
   6845      * Change whether this view is one of the set of scrollable containers in
   6846      * its window.  This will be used to determine whether the window can
   6847      * resize or must pan when a soft input area is open -- scrollable
   6848      * containers allow the window to use resize mode since the container
   6849      * will appropriately shrink.
   6850      *
   6851      * @attr ref android.R.styleable#View_isScrollContainer
   6852      */
   6853     public void setScrollContainer(boolean isScrollContainer) {
   6854         if (isScrollContainer) {
   6855             if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
   6856                 mAttachInfo.mScrollContainers.add(this);
   6857                 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
   6858             }
   6859             mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
   6860         } else {
   6861             if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
   6862                 mAttachInfo.mScrollContainers.remove(this);
   6863             }
   6864             mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
   6865         }
   6866     }
   6867 
   6868     /**
   6869      * Returns the quality of the drawing cache.
   6870      *
   6871      * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
   6872      *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
   6873      *
   6874      * @see #setDrawingCacheQuality(int)
   6875      * @see #setDrawingCacheEnabled(boolean)
   6876      * @see #isDrawingCacheEnabled()
   6877      *
   6878      * @attr ref android.R.styleable#View_drawingCacheQuality
   6879      */
   6880     @DrawingCacheQuality
   6881     public int getDrawingCacheQuality() {
   6882         return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
   6883     }
   6884 
   6885     /**
   6886      * Set the drawing cache quality of this view. This value is used only when the
   6887      * drawing cache is enabled
   6888      *
   6889      * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
   6890      *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
   6891      *
   6892      * @see #getDrawingCacheQuality()
   6893      * @see #setDrawingCacheEnabled(boolean)
   6894      * @see #isDrawingCacheEnabled()
   6895      *
   6896      * @attr ref android.R.styleable#View_drawingCacheQuality
   6897      */
   6898     public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
   6899         setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
   6900     }
   6901 
   6902     /**
   6903      * Returns whether the screen should remain on, corresponding to the current
   6904      * value of {@link #KEEP_SCREEN_ON}.
   6905      *
   6906      * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
   6907      *
   6908      * @see #setKeepScreenOn(boolean)
   6909      *
   6910      * @attr ref android.R.styleable#View_keepScreenOn
   6911      */
   6912     public boolean getKeepScreenOn() {
   6913         return (mViewFlags & KEEP_SCREEN_ON) != 0;
   6914     }
   6915 
   6916     /**
   6917      * Controls whether the screen should remain on, modifying the
   6918      * value of {@link #KEEP_SCREEN_ON}.
   6919      *
   6920      * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
   6921      *
   6922      * @see #getKeepScreenOn()
   6923      *
   6924      * @attr ref android.R.styleable#View_keepScreenOn
   6925      */
   6926     public void setKeepScreenOn(boolean keepScreenOn) {
   6927         setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
   6928     }
   6929 
   6930     /**
   6931      * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
   6932      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
   6933      *
   6934      * @attr ref android.R.styleable#View_nextFocusLeft
   6935      */
   6936     public int getNextFocusLeftId() {
   6937         return mNextFocusLeftId;
   6938     }
   6939 
   6940     /**
   6941      * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
   6942      * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
   6943      * decide automatically.
   6944      *
   6945      * @attr ref android.R.styleable#View_nextFocusLeft
   6946      */
   6947     public void setNextFocusLeftId(int nextFocusLeftId) {
   6948         mNextFocusLeftId = nextFocusLeftId;
   6949     }
   6950 
   6951     /**
   6952      * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
   6953      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
   6954      *
   6955      * @attr ref android.R.styleable#View_nextFocusRight
   6956      */
   6957     public int getNextFocusRightId() {
   6958         return mNextFocusRightId;
   6959     }
   6960 
   6961     /**
   6962      * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
   6963      * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
   6964      * decide automatically.
   6965      *
   6966      * @attr ref android.R.styleable#View_nextFocusRight
   6967      */
   6968     public void setNextFocusRightId(int nextFocusRightId) {
   6969         mNextFocusRightId = nextFocusRightId;
   6970     }
   6971 
   6972     /**
   6973      * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
   6974      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
   6975      *
   6976      * @attr ref android.R.styleable#View_nextFocusUp
   6977      */
   6978     public int getNextFocusUpId() {
   6979         return mNextFocusUpId;
   6980     }
   6981 
   6982     /**
   6983      * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
   6984      * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
   6985      * decide automatically.
   6986      *
   6987      * @attr ref android.R.styleable#View_nextFocusUp
   6988      */
   6989     public void setNextFocusUpId(int nextFocusUpId) {
   6990         mNextFocusUpId = nextFocusUpId;
   6991     }
   6992 
   6993     /**
   6994      * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
   6995      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
   6996      *
   6997      * @attr ref android.R.styleable#View_nextFocusDown
   6998      */
   6999     public int getNextFocusDownId() {
   7000         return mNextFocusDownId;
   7001     }
   7002 
   7003     /**
   7004      * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
   7005      * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
   7006      * decide automatically.
   7007      *
   7008      * @attr ref android.R.styleable#View_nextFocusDown
   7009      */
   7010     public void setNextFocusDownId(int nextFocusDownId) {
   7011         mNextFocusDownId = nextFocusDownId;
   7012     }
   7013 
   7014     /**
   7015      * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
   7016      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
   7017      *
   7018      * @attr ref android.R.styleable#View_nextFocusForward
   7019      */
   7020     public int getNextFocusForwardId() {
   7021         return mNextFocusForwardId;
   7022     }
   7023 
   7024     /**
   7025      * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
   7026      * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
   7027      * decide automatically.
   7028      *
   7029      * @attr ref android.R.styleable#View_nextFocusForward
   7030      */
   7031     public void setNextFocusForwardId(int nextFocusForwardId) {
   7032         mNextFocusForwardId = nextFocusForwardId;
   7033     }
   7034 
   7035     /**
   7036      * Returns the visibility of this view and all of its ancestors
   7037      *
   7038      * @return True if this view and all of its ancestors are {@link #VISIBLE}
   7039      */
   7040     public boolean isShown() {
   7041         View current = this;
   7042         //noinspection ConstantConditions
   7043         do {
   7044             if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
   7045                 return false;
   7046             }
   7047             ViewParent parent = current.mParent;
   7048             if (parent == null) {
   7049                 return false; // We are not attached to the view root
   7050             }
   7051             if (!(parent instanceof View)) {
   7052                 return true;
   7053             }
   7054             current = (View) parent;
   7055         } while (current != null);
   7056 
   7057         return false;
   7058     }
   7059 
   7060     /**
   7061      * Called by the view hierarchy when the content insets for a window have
   7062      * changed, to allow it to adjust its content to fit within those windows.
   7063      * The content insets tell you the space that the status bar, input method,
   7064      * and other system windows infringe on the application's window.
   7065      *
   7066      * <p>You do not normally need to deal with this function, since the default
   7067      * window decoration given to applications takes care of applying it to the
   7068      * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
   7069      * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
   7070      * and your content can be placed under those system elements.  You can then
   7071      * use this method within your view hierarchy if you have parts of your UI
   7072      * which you would like to ensure are not being covered.
   7073      *
   7074      * <p>The default implementation of this method simply applies the content
   7075      * insets to the view's padding, consuming that content (modifying the
   7076      * insets to be 0), and returning true.  This behavior is off by default, but can
   7077      * be enabled through {@link #setFitsSystemWindows(boolean)}.
   7078      *
   7079      * <p>This function's traversal down the hierarchy is depth-first.  The same content
   7080      * insets object is propagated down the hierarchy, so any changes made to it will
   7081      * be seen by all following views (including potentially ones above in
   7082      * the hierarchy since this is a depth-first traversal).  The first view
   7083      * that returns true will abort the entire traversal.
   7084      *
   7085      * <p>The default implementation works well for a situation where it is
   7086      * used with a container that covers the entire window, allowing it to
   7087      * apply the appropriate insets to its content on all edges.  If you need
   7088      * a more complicated layout (such as two different views fitting system
   7089      * windows, one on the top of the window, and one on the bottom),
   7090      * you can override the method and handle the insets however you would like.
   7091      * Note that the insets provided by the framework are always relative to the
   7092      * far edges of the window, not accounting for the location of the called view
   7093      * within that window.  (In fact when this method is called you do not yet know
   7094      * where the layout will place the view, as it is done before layout happens.)
   7095      *
   7096      * <p>Note: unlike many View methods, there is no dispatch phase to this
   7097      * call.  If you are overriding it in a ViewGroup and want to allow the
   7098      * call to continue to your children, you must be sure to call the super
   7099      * implementation.
   7100      *
   7101      * <p>Here is a sample layout that makes use of fitting system windows
   7102      * to have controls for a video view placed inside of the window decorations
   7103      * that it hides and shows.  This can be used with code like the second
   7104      * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
   7105      *
   7106      * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
   7107      *
   7108      * @param insets Current content insets of the window.  Prior to
   7109      * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
   7110      * the insets or else you and Android will be unhappy.
   7111      *
   7112      * @return {@code true} if this view applied the insets and it should not
   7113      * continue propagating further down the hierarchy, {@code false} otherwise.
   7114      * @see #getFitsSystemWindows()
   7115      * @see #setFitsSystemWindows(boolean)
   7116      * @see #setSystemUiVisibility(int)
   7117      *
   7118      * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
   7119      * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
   7120      * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
   7121      * to implement handling their own insets.
   7122      */
   7123     protected boolean fitSystemWindows(Rect insets) {
   7124         if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
   7125             if (insets == null) {
   7126                 // Null insets by definition have already been consumed.
   7127                 // This call cannot apply insets since there are none to apply,
   7128                 // so return false.
   7129                 return false;
   7130             }
   7131             // If we're not in the process of dispatching the newer apply insets call,
   7132             // that means we're not in the compatibility path. Dispatch into the newer
   7133             // apply insets path and take things from there.
   7134             try {
   7135                 mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
   7136                 return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
   7137             } finally {
   7138                 mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
   7139             }
   7140         } else {
   7141             // We're being called from the newer apply insets path.
   7142             // Perform the standard fallback behavior.
   7143             return fitSystemWindowsInt(insets);
   7144         }
   7145     }
   7146 
   7147     private boolean fitSystemWindowsInt(Rect insets) {
   7148         if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
   7149             mUserPaddingStart = UNDEFINED_PADDING;
   7150             mUserPaddingEnd = UNDEFINED_PADDING;
   7151             Rect localInsets = sThreadLocal.get();
   7152             if (localInsets == null) {
   7153                 localInsets = new Rect();
   7154                 sThreadLocal.set(localInsets);
   7155             }
   7156             boolean res = computeFitSystemWindows(insets, localInsets);
   7157             mUserPaddingLeftInitial = localInsets.left;
   7158             mUserPaddingRightInitial = localInsets.right;
   7159             internalSetPadding(localInsets.left, localInsets.top,
   7160                     localInsets.right, localInsets.bottom);
   7161             return res;
   7162         }
   7163         return false;
   7164     }
   7165 
   7166     /**
   7167      * Called when the view should apply {@link WindowInsets} according to its internal policy.
   7168      *
   7169      * <p>This method should be overridden by views that wish to apply a policy different from or
   7170      * in addition to the default behavior. Clients that wish to force a view subtree
   7171      * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
   7172      *
   7173      * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
   7174      * it will be called during dispatch instead of this method. The listener may optionally
   7175      * call this method from its own implementation if it wishes to apply the view's default
   7176      * insets policy in addition to its own.</p>
   7177      *
   7178      * <p>Implementations of this method should either return the insets parameter unchanged
   7179      * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
   7180      * that this view applied itself. This allows new inset types added in future platform
   7181      * versions to pass through existing implementations unchanged without being erroneously
   7182      * consumed.</p>
   7183      *
   7184      * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
   7185      * property is set then the view will consume the system window insets and apply them
   7186      * as padding for the view.</p>
   7187      *
   7188      * @param insets Insets to apply
   7189      * @return The supplied insets with any applied insets consumed
   7190      */
   7191     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
   7192         if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
   7193             // We weren't called from within a direct call to fitSystemWindows,
   7194             // call into it as a fallback in case we're in a class that overrides it
   7195             // and has logic to perform.
   7196             if (fitSystemWindows(insets.getSystemWindowInsets())) {
   7197                 return insets.consumeSystemWindowInsets();
   7198             }
   7199         } else {
   7200             // We were called from within a direct call to fitSystemWindows.
   7201             if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
   7202                 return insets.consumeSystemWindowInsets();
   7203             }
   7204         }
   7205         return insets;
   7206     }
   7207 
   7208     /**
   7209      * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
   7210      * window insets to this view. The listener's
   7211      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
   7212      * method will be called instead of the view's
   7213      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
   7214      *
   7215      * @param listener Listener to set
   7216      *
   7217      * @see #onApplyWindowInsets(WindowInsets)
   7218      */
   7219     public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
   7220         getListenerInfo().mOnApplyWindowInsetsListener = listener;
   7221     }
   7222 
   7223     /**
   7224      * Request to apply the given window insets to this view or another view in its subtree.
   7225      *
   7226      * <p>This method should be called by clients wishing to apply insets corresponding to areas
   7227      * obscured by window decorations or overlays. This can include the status and navigation bars,
   7228      * action bars, input methods and more. New inset categories may be added in the future.
   7229      * The method returns the insets provided minus any that were applied by this view or its
   7230      * children.</p>
   7231      *
   7232      * <p>Clients wishing to provide custom behavior should override the
   7233      * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
   7234      * {@link OnApplyWindowInsetsListener} via the
   7235      * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
   7236      * method.</p>
   7237      *
   7238      * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
   7239      * </p>
   7240      *
   7241      * @param insets Insets to apply
   7242      * @return The provided insets minus the insets that were consumed
   7243      */
   7244     public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
   7245         try {
   7246             mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
   7247             if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
   7248                 return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
   7249             } else {
   7250                 return onApplyWindowInsets(insets);
   7251             }
   7252         } finally {
   7253             mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
   7254         }
   7255     }
   7256 
   7257     /**
   7258      * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
   7259      * only available if the view is attached.
   7260      *
   7261      * @return WindowInsets from the top of the view hierarchy or null if View is detached
   7262      */
   7263     public WindowInsets getRootWindowInsets() {
   7264         if (mAttachInfo != null) {
   7265             return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
   7266         }
   7267         return null;
   7268     }
   7269 
   7270     /**
   7271      * @hide Compute the insets that should be consumed by this view and the ones
   7272      * that should propagate to those under it.
   7273      */
   7274     protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
   7275         if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
   7276                 || mAttachInfo == null
   7277                 || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
   7278                         && !mAttachInfo.mOverscanRequested)) {
   7279             outLocalInsets.set(inoutInsets);
   7280             inoutInsets.set(0, 0, 0, 0);
   7281             return true;
   7282         } else {
   7283             // The application wants to take care of fitting system window for
   7284             // the content...  however we still need to take care of any overscan here.
   7285             final Rect overscan = mAttachInfo.mOverscanInsets;
   7286             outLocalInsets.set(overscan);
   7287             inoutInsets.left -= overscan.left;
   7288             inoutInsets.top -= overscan.top;
   7289             inoutInsets.right -= overscan.right;
   7290             inoutInsets.bottom -= overscan.bottom;
   7291             return false;
   7292         }
   7293     }
   7294 
   7295     /**
   7296      * Compute insets that should be consumed by this view and the ones that should propagate
   7297      * to those under it.
   7298      *
   7299      * @param in Insets currently being processed by this View, likely received as a parameter
   7300      *           to {@link #onApplyWindowInsets(WindowInsets)}.
   7301      * @param outLocalInsets A Rect that will receive the insets that should be consumed
   7302      *                       by this view
   7303      * @return Insets that should be passed along to views under this one
   7304      */
   7305     public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
   7306         if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
   7307                 || mAttachInfo == null
   7308                 || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
   7309             outLocalInsets.set(in.getSystemWindowInsets());
   7310             return in.consumeSystemWindowInsets();
   7311         } else {
   7312             outLocalInsets.set(0, 0, 0, 0);
   7313             return in;
   7314         }
   7315     }
   7316 
   7317     /**
   7318      * Sets whether or not this view should account for system screen decorations
   7319      * such as the status bar and inset its content; that is, controlling whether
   7320      * the default implementation of {@link #fitSystemWindows(Rect)} will be
   7321      * executed.  See that method for more details.
   7322      *
   7323      * <p>Note that if you are providing your own implementation of
   7324      * {@link #fitSystemWindows(Rect)}, then there is no need to set this
   7325      * flag to true -- your implementation will be overriding the default
   7326      * implementation that checks this flag.
   7327      *
   7328      * @param fitSystemWindows If true, then the default implementation of
   7329      * {@link #fitSystemWindows(Rect)} will be executed.
   7330      *
   7331      * @attr ref android.R.styleable#View_fitsSystemWindows
   7332      * @see #getFitsSystemWindows()
   7333      * @see #fitSystemWindows(Rect)
   7334      * @see #setSystemUiVisibility(int)
   7335      */
   7336     public void setFitsSystemWindows(boolean fitSystemWindows) {
   7337         setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
   7338     }
   7339 
   7340     /**
   7341      * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
   7342      * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
   7343      * will be executed.
   7344      *
   7345      * @return {@code true} if the default implementation of
   7346      * {@link #fitSystemWindows(Rect)} will be executed.
   7347      *
   7348      * @attr ref android.R.styleable#View_fitsSystemWindows
   7349      * @see #setFitsSystemWindows(boolean)
   7350      * @see #fitSystemWindows(Rect)
   7351      * @see #setSystemUiVisibility(int)
   7352      */
   7353     @ViewDebug.ExportedProperty
   7354     public boolean getFitsSystemWindows() {
   7355         return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
   7356     }
   7357 
   7358     /** @hide */
   7359     public boolean fitsSystemWindows() {
   7360         return getFitsSystemWindows();
   7361     }
   7362 
   7363     /**
   7364      * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
   7365      * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
   7366      */
   7367     public void requestFitSystemWindows() {
   7368         if (mParent != null) {
   7369             mParent.requestFitSystemWindows();
   7370         }
   7371     }
   7372 
   7373     /**
   7374      * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
   7375      */
   7376     public void requestApplyInsets() {
   7377         requestFitSystemWindows();
   7378     }
   7379 
   7380     /**
   7381      * For use by PhoneWindow to make its own system window fitting optional.
   7382      * @hide
   7383      */
   7384     public void makeOptionalFitsSystemWindows() {
   7385         setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
   7386     }
   7387 
   7388     /**
   7389      * Returns the outsets, which areas of the device that aren't a surface, but we would like to
   7390      * treat them as such.
   7391      * @hide
   7392      */
   7393     public void getOutsets(Rect outOutsetRect) {
   7394         if (mAttachInfo != null) {
   7395             outOutsetRect.set(mAttachInfo.mOutsets);
   7396         } else {
   7397             outOutsetRect.setEmpty();
   7398         }
   7399     }
   7400 
   7401     /**
   7402      * Returns the visibility status for this view.
   7403      *
   7404      * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
   7405      * @attr ref android.R.styleable#View_visibility
   7406      */
   7407     @ViewDebug.ExportedProperty(mapping = {
   7408         @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
   7409         @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
   7410         @ViewDebug.IntToString(from = GONE,      to = "GONE")
   7411     })
   7412     @Visibility
   7413     public int getVisibility() {
   7414         return mViewFlags & VISIBILITY_MASK;
   7415     }
   7416 
   7417     /**
   7418      * Set the enabled state of this view.
   7419      *
   7420      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
   7421      * @attr ref android.R.styleable#View_visibility
   7422      */
   7423     @RemotableViewMethod
   7424     public void setVisibility(@Visibility int visibility) {
   7425         setFlags(visibility, VISIBILITY_MASK);
   7426     }
   7427 
   7428     /**
   7429      * Returns the enabled status for this view. The interpretation of the
   7430      * enabled state varies by subclass.
   7431      *
   7432      * @return True if this view is enabled, false otherwise.
   7433      */
   7434     @ViewDebug.ExportedProperty
   7435     public boolean isEnabled() {
   7436         return (mViewFlags & ENABLED_MASK) == ENABLED;
   7437     }
   7438 
   7439     /**
   7440      * Set the enabled state of this view. The interpretation of the enabled
   7441      * state varies by subclass.
   7442      *
   7443      * @param enabled True if this view is enabled, false otherwise.
   7444      */
   7445     @RemotableViewMethod
   7446     public void setEnabled(boolean enabled) {
   7447         if (enabled == isEnabled()) return;
   7448 
   7449         setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
   7450 
   7451         /*
   7452          * The View most likely has to change its appearance, so refresh
   7453          * the drawable state.
   7454          */
   7455         refreshDrawableState();
   7456 
   7457         // Invalidate too, since the default behavior for views is to be
   7458         // be drawn at 50% alpha rather than to change the drawable.
   7459         invalidate(true);
   7460 
   7461         if (!enabled) {
   7462             cancelPendingInputEvents();
   7463         }
   7464     }
   7465 
   7466     /**
   7467      * Set whether this view can receive the focus.
   7468      *
   7469      * Setting this to false will also ensure that this view is not focusable
   7470      * in touch mode.
   7471      *
   7472      * @param focusable If true, this view can receive the focus.
   7473      *
   7474      * @see #setFocusableInTouchMode(boolean)
   7475      * @attr ref android.R.styleable#View_focusable
   7476      */
   7477     public void setFocusable(boolean focusable) {
   7478         if (!focusable) {
   7479             setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
   7480         }
   7481         setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
   7482     }
   7483 
   7484     /**
   7485      * Set whether this view can receive focus while in touch mode.
   7486      *
   7487      * Setting this to true will also ensure that this view is focusable.
   7488      *
   7489      * @param focusableInTouchMode If true, this view can receive the focus while
   7490      *   in touch mode.
   7491      *
   7492      * @see #setFocusable(boolean)
   7493      * @attr ref android.R.styleable#View_focusableInTouchMode
   7494      */
   7495     public void setFocusableInTouchMode(boolean focusableInTouchMode) {
   7496         // Focusable in touch mode should always be set before the focusable flag
   7497         // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
   7498         // which, in touch mode, will not successfully request focus on this view
   7499         // because the focusable in touch mode flag is not set
   7500         setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
   7501         if (focusableInTouchMode) {
   7502             setFlags(FOCUSABLE, FOCUSABLE_MASK);
   7503         }
   7504     }
   7505 
   7506     /**
   7507      * Set whether this view should have sound effects enabled for events such as
   7508      * clicking and touching.
   7509      *
   7510      * <p>You may wish to disable sound effects for a view if you already play sounds,
   7511      * for instance, a dial key that plays dtmf tones.
   7512      *
   7513      * @param soundEffectsEnabled whether sound effects are enabled for this view.
   7514      * @see #isSoundEffectsEnabled()
   7515      * @see #playSoundEffect(int)
   7516      * @attr ref android.R.styleable#View_soundEffectsEnabled
   7517      */
   7518     public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
   7519         setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
   7520     }
   7521 
   7522     /**
   7523      * @return whether this view should have sound effects enabled for events such as
   7524      *     clicking and touching.
   7525      *
   7526      * @see #setSoundEffectsEnabled(boolean)
   7527      * @see #playSoundEffect(int)
   7528      * @attr ref android.R.styleable#View_soundEffectsEnabled
   7529      */
   7530     @ViewDebug.ExportedProperty
   7531     public boolean isSoundEffectsEnabled() {
   7532         return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
   7533     }
   7534 
   7535     /**
   7536      * Set whether this view should have haptic feedback for events such as
   7537      * long presses.
   7538      *
   7539      * <p>You may wish to disable haptic feedback if your view already controls
   7540      * its own haptic feedback.
   7541      *
   7542      * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
   7543      * @see #isHapticFeedbackEnabled()
   7544      * @see #performHapticFeedback(int)
   7545      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
   7546      */
   7547     public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
   7548         setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
   7549     }
   7550 
   7551     /**
   7552      * @return whether this view should have haptic feedback enabled for events
   7553      * long presses.
   7554      *
   7555      * @see #setHapticFeedbackEnabled(boolean)
   7556      * @see #performHapticFeedback(int)
   7557      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
   7558      */
   7559     @ViewDebug.ExportedProperty
   7560     public boolean isHapticFeedbackEnabled() {
   7561         return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
   7562     }
   7563 
   7564     /**
   7565      * Returns the layout direction for this view.
   7566      *
   7567      * @return One of {@link #LAYOUT_DIRECTION_LTR},
   7568      *   {@link #LAYOUT_DIRECTION_RTL},
   7569      *   {@link #LAYOUT_DIRECTION_INHERIT} or
   7570      *   {@link #LAYOUT_DIRECTION_LOCALE}.
   7571      *
   7572      * @attr ref android.R.styleable#View_layoutDirection
   7573      *
   7574      * @hide
   7575      */
   7576     @ViewDebug.ExportedProperty(category = "layout", mapping = {
   7577         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
   7578         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
   7579         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
   7580         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
   7581     })
   7582     @LayoutDir
   7583     public int getRawLayoutDirection() {
   7584         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
   7585     }
   7586 
   7587     /**
   7588      * Set the layout direction for this view. This will propagate a reset of layout direction
   7589      * resolution to the view's children and resolve layout direction for this view.
   7590      *
   7591      * @param layoutDirection the layout direction to set. Should be one of:
   7592      *
   7593      * {@link #LAYOUT_DIRECTION_LTR},
   7594      * {@link #LAYOUT_DIRECTION_RTL},
   7595      * {@link #LAYOUT_DIRECTION_INHERIT},
   7596      * {@link #LAYOUT_DIRECTION_LOCALE}.
   7597      *
   7598      * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
   7599      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
   7600      * will return the default {@link #LAYOUT_DIRECTION_LTR}.
   7601      *
   7602      * @attr ref android.R.styleable#View_layoutDirection
   7603      */
   7604     @RemotableViewMethod
   7605     public void setLayoutDirection(@LayoutDir int layoutDirection) {
   7606         if (getRawLayoutDirection() != layoutDirection) {
   7607             // Reset the current layout direction and the resolved one
   7608             mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
   7609             resetRtlProperties();
   7610             // Set the new layout direction (filtered)
   7611             mPrivateFlags2 |=
   7612                     ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
   7613             // We need to resolve all RTL properties as they all depend on layout direction
   7614             resolveRtlPropertiesIfNeeded();
   7615             requestLayout();
   7616             invalidate(true);
   7617         }
   7618     }
   7619 
   7620     /**
   7621      * Returns the resolved layout direction for this view.
   7622      *
   7623      * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
   7624      * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
   7625      *
   7626      * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
   7627      * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
   7628      *
   7629      * @attr ref android.R.styleable#View_layoutDirection
   7630      */
   7631     @ViewDebug.ExportedProperty(category = "layout", mapping = {
   7632         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
   7633         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
   7634     })
   7635     @ResolvedLayoutDir
   7636     public int getLayoutDirection() {
   7637         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
   7638         if (targetSdkVersion < JELLY_BEAN_MR1) {
   7639             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
   7640             return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
   7641         }
   7642         return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
   7643                 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
   7644     }
   7645 
   7646     /**
   7647      * Indicates whether or not this view's layout is right-to-left. This is resolved from
   7648      * layout attribute and/or the inherited value from the parent
   7649      *
   7650      * @return true if the layout is right-to-left.
   7651      *
   7652      * @hide
   7653      */
   7654     @ViewDebug.ExportedProperty(category = "layout")
   7655     public boolean isLayoutRtl() {
   7656         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
   7657     }
   7658 
   7659     /**
   7660      * Indicates whether the view is currently tracking transient state that the
   7661      * app should not need to concern itself with saving and restoring, but that
   7662      * the framework should take special note to preserve when possible.
   7663      *
   7664      * <p>A view with transient state cannot be trivially rebound from an external
   7665      * data source, such as an adapter binding item views in a list. This may be
   7666      * because the view is performing an animation, tracking user selection
   7667      * of content, or similar.</p>
   7668      *
   7669      * @return true if the view has transient state
   7670      */
   7671     @ViewDebug.ExportedProperty(category = "layout")
   7672     public boolean hasTransientState() {
   7673         return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
   7674     }
   7675 
   7676     /**
   7677      * Set whether this view is currently tracking transient state that the
   7678      * framework should attempt to preserve when possible. This flag is reference counted,
   7679      * so every call to setHasTransientState(true) should be paired with a later call
   7680      * to setHasTransientState(false).
   7681      *
   7682      * <p>A view with transient state cannot be trivially rebound from an external
   7683      * data source, such as an adapter binding item views in a list. This may be
   7684      * because the view is performing an animation, tracking user selection
   7685      * of content, or similar.</p>
   7686      *
   7687      * @param hasTransientState true if this view has transient state
   7688      */
   7689     public void setHasTransientState(boolean hasTransientState) {
   7690         mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
   7691                 mTransientStateCount - 1;
   7692         if (mTransientStateCount < 0) {
   7693             mTransientStateCount = 0;
   7694             Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
   7695                     "unmatched pair of setHasTransientState calls");
   7696         } else if ((hasTransientState && mTransientStateCount == 1) ||
   7697                 (!hasTransientState && mTransientStateCount == 0)) {
   7698             // update flag if we've just incremented up from 0 or decremented down to 0
   7699             mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
   7700                     (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
   7701             if (mParent != null) {
   7702                 try {
   7703                     mParent.childHasTransientStateChanged(this, hasTransientState);
   7704                 } catch (AbstractMethodError e) {
   7705                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   7706                             " does not fully implement ViewParent", e);
   7707                 }
   7708             }
   7709         }
   7710     }
   7711 
   7712     /**
   7713      * Returns true if this view is currently attached to a window.
   7714      */
   7715     public boolean isAttachedToWindow() {
   7716         return mAttachInfo != null;
   7717     }
   7718 
   7719     /**
   7720      * Returns true if this view has been through at least one layout since it
   7721      * was last attached to or detached from a window.
   7722      */
   7723     public boolean isLaidOut() {
   7724         return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
   7725     }
   7726 
   7727     /**
   7728      * If this view doesn't do any drawing on its own, set this flag to
   7729      * allow further optimizations. By default, this flag is not set on
   7730      * View, but could be set on some View subclasses such as ViewGroup.
   7731      *
   7732      * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
   7733      * you should clear this flag.
   7734      *
   7735      * @param willNotDraw whether or not this View draw on its own
   7736      */
   7737     public void setWillNotDraw(boolean willNotDraw) {
   7738         setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
   7739     }
   7740 
   7741     /**
   7742      * Returns whether or not this View draws on its own.
   7743      *
   7744      * @return true if this view has nothing to draw, false otherwise
   7745      */
   7746     @ViewDebug.ExportedProperty(category = "drawing")
   7747     public boolean willNotDraw() {
   7748         return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
   7749     }
   7750 
   7751     /**
   7752      * When a View's drawing cache is enabled, drawing is redirected to an
   7753      * offscreen bitmap. Some views, like an ImageView, must be able to
   7754      * bypass this mechanism if they already draw a single bitmap, to avoid
   7755      * unnecessary usage of the memory.
   7756      *
   7757      * @param willNotCacheDrawing true if this view does not cache its
   7758      *        drawing, false otherwise
   7759      */
   7760     public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
   7761         setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
   7762     }
   7763 
   7764     /**
   7765      * Returns whether or not this View can cache its drawing or not.
   7766      *
   7767      * @return true if this view does not cache its drawing, false otherwise
   7768      */
   7769     @ViewDebug.ExportedProperty(category = "drawing")
   7770     public boolean willNotCacheDrawing() {
   7771         return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
   7772     }
   7773 
   7774     /**
   7775      * Indicates whether this view reacts to click events or not.
   7776      *
   7777      * @return true if the view is clickable, false otherwise
   7778      *
   7779      * @see #setClickable(boolean)
   7780      * @attr ref android.R.styleable#View_clickable
   7781      */
   7782     @ViewDebug.ExportedProperty
   7783     public boolean isClickable() {
   7784         return (mViewFlags & CLICKABLE) == CLICKABLE;
   7785     }
   7786 
   7787     /**
   7788      * Enables or disables click events for this view. When a view
   7789      * is clickable it will change its state to "pressed" on every click.
   7790      * Subclasses should set the view clickable to visually react to
   7791      * user's clicks.
   7792      *
   7793      * @param clickable true to make the view clickable, false otherwise
   7794      *
   7795      * @see #isClickable()
   7796      * @attr ref android.R.styleable#View_clickable
   7797      */
   7798     public void setClickable(boolean clickable) {
   7799         setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
   7800     }
   7801 
   7802     /**
   7803      * Indicates whether this view reacts to long click events or not.
   7804      *
   7805      * @return true if the view is long clickable, false otherwise
   7806      *
   7807      * @see #setLongClickable(boolean)
   7808      * @attr ref android.R.styleable#View_longClickable
   7809      */
   7810     public boolean isLongClickable() {
   7811         return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
   7812     }
   7813 
   7814     /**
   7815      * Enables or disables long click events for this view. When a view is long
   7816      * clickable it reacts to the user holding down the button for a longer
   7817      * duration than a tap. This event can either launch the listener or a
   7818      * context menu.
   7819      *
   7820      * @param longClickable true to make the view long clickable, false otherwise
   7821      * @see #isLongClickable()
   7822      * @attr ref android.R.styleable#View_longClickable
   7823      */
   7824     public void setLongClickable(boolean longClickable) {
   7825         setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
   7826     }
   7827 
   7828     /**
   7829      * Indicates whether this view reacts to context clicks or not.
   7830      *
   7831      * @return true if the view is context clickable, false otherwise
   7832      * @see #setContextClickable(boolean)
   7833      * @attr ref android.R.styleable#View_contextClickable
   7834      */
   7835     public boolean isContextClickable() {
   7836         return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
   7837     }
   7838 
   7839     /**
   7840      * Enables or disables context clicking for this view. This event can launch the listener.
   7841      *
   7842      * @param contextClickable true to make the view react to a context click, false otherwise
   7843      * @see #isContextClickable()
   7844      * @attr ref android.R.styleable#View_contextClickable
   7845      */
   7846     public void setContextClickable(boolean contextClickable) {
   7847         setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
   7848     }
   7849 
   7850     /**
   7851      * Sets the pressed state for this view and provides a touch coordinate for
   7852      * animation hinting.
   7853      *
   7854      * @param pressed Pass true to set the View's internal state to "pressed",
   7855      *            or false to reverts the View's internal state from a
   7856      *            previously set "pressed" state.
   7857      * @param x The x coordinate of the touch that caused the press
   7858      * @param y The y coordinate of the touch that caused the press
   7859      */
   7860     private void setPressed(boolean pressed, float x, float y) {
   7861         if (pressed) {
   7862             drawableHotspotChanged(x, y);
   7863         }
   7864 
   7865         setPressed(pressed);
   7866     }
   7867 
   7868     /**
   7869      * Sets the pressed state for this view.
   7870      *
   7871      * @see #isClickable()
   7872      * @see #setClickable(boolean)
   7873      *
   7874      * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
   7875      *        the View's internal state from a previously set "pressed" state.
   7876      */
   7877     public void setPressed(boolean pressed) {
   7878         final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
   7879 
   7880         if (pressed) {
   7881             mPrivateFlags |= PFLAG_PRESSED;
   7882         } else {
   7883             mPrivateFlags &= ~PFLAG_PRESSED;
   7884         }
   7885 
   7886         if (needsRefresh) {
   7887             refreshDrawableState();
   7888         }
   7889         dispatchSetPressed(pressed);
   7890     }
   7891 
   7892     /**
   7893      * Dispatch setPressed to all of this View's children.
   7894      *
   7895      * @see #setPressed(boolean)
   7896      *
   7897      * @param pressed The new pressed state
   7898      */
   7899     protected void dispatchSetPressed(boolean pressed) {
   7900     }
   7901 
   7902     /**
   7903      * Indicates whether the view is currently in pressed state. Unless
   7904      * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
   7905      * the pressed state.
   7906      *
   7907      * @see #setPressed(boolean)
   7908      * @see #isClickable()
   7909      * @see #setClickable(boolean)
   7910      *
   7911      * @return true if the view is currently pressed, false otherwise
   7912      */
   7913     @ViewDebug.ExportedProperty
   7914     public boolean isPressed() {
   7915         return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
   7916     }
   7917 
   7918     /**
   7919      * @hide
   7920      * Indicates whether this view will participate in data collection through
   7921      * {@link ViewStructure}.  If true, it will not provide any data
   7922      * for itself or its children.  If false, the normal data collection will be allowed.
   7923      *
   7924      * @return Returns false if assist data collection is not blocked, else true.
   7925      *
   7926      * @see #setAssistBlocked(boolean)
   7927      * @attr ref android.R.styleable#View_assistBlocked
   7928      */
   7929     public boolean isAssistBlocked() {
   7930         return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
   7931     }
   7932 
   7933     /**
   7934      * @hide
   7935      * Controls whether assist data collection from this view and its children is enabled
   7936      * (that is, whether {@link #onProvideStructure} and
   7937      * {@link #onProvideVirtualStructure} will be called).  The default value is false,
   7938      * allowing normal assist collection.  Setting this to false will disable assist collection.
   7939      *
   7940      * @param enabled Set to true to <em>disable</em> assist data collection, or false
   7941      * (the default) to allow it.
   7942      *
   7943      * @see #isAssistBlocked()
   7944      * @see #onProvideStructure
   7945      * @see #onProvideVirtualStructure
   7946      * @attr ref android.R.styleable#View_assistBlocked
   7947      */
   7948     public void setAssistBlocked(boolean enabled) {
   7949         if (enabled) {
   7950             mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
   7951         } else {
   7952             mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
   7953         }
   7954     }
   7955 
   7956     /**
   7957      * Indicates whether this view will save its state (that is,
   7958      * whether its {@link #onSaveInstanceState} method will be called).
   7959      *
   7960      * @return Returns true if the view state saving is enabled, else false.
   7961      *
   7962      * @see #setSaveEnabled(boolean)
   7963      * @attr ref android.R.styleable#View_saveEnabled
   7964      */
   7965     public boolean isSaveEnabled() {
   7966         return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
   7967     }
   7968 
   7969     /**
   7970      * Controls whether the saving of this view's state is
   7971      * enabled (that is, whether its {@link #onSaveInstanceState} method
   7972      * will be called).  Note that even if freezing is enabled, the
   7973      * view still must have an id assigned to it (via {@link #setId(int)})
   7974      * for its state to be saved.  This flag can only disable the
   7975      * saving of this view; any child views may still have their state saved.
   7976      *
   7977      * @param enabled Set to false to <em>disable</em> state saving, or true
   7978      * (the default) to allow it.
   7979      *
   7980      * @see #isSaveEnabled()
   7981      * @see #setId(int)
   7982      * @see #onSaveInstanceState()
   7983      * @attr ref android.R.styleable#View_saveEnabled
   7984      */
   7985     public void setSaveEnabled(boolean enabled) {
   7986         setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
   7987     }
   7988 
   7989     /**
   7990      * Gets whether the framework should discard touches when the view's
   7991      * window is obscured by another visible window.
   7992      * Refer to the {@link View} security documentation for more details.
   7993      *
   7994      * @return True if touch filtering is enabled.
   7995      *
   7996      * @see #setFilterTouchesWhenObscured(boolean)
   7997      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
   7998      */
   7999     @ViewDebug.ExportedProperty
   8000     public boolean getFilterTouchesWhenObscured() {
   8001         return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
   8002     }
   8003 
   8004     /**
   8005      * Sets whether the framework should discard touches when the view's
   8006      * window is obscured by another visible window.
   8007      * Refer to the {@link View} security documentation for more details.
   8008      *
   8009      * @param enabled True if touch filtering should be enabled.
   8010      *
   8011      * @see #getFilterTouchesWhenObscured
   8012      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
   8013      */
   8014     public void setFilterTouchesWhenObscured(boolean enabled) {
   8015         setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
   8016                 FILTER_TOUCHES_WHEN_OBSCURED);
   8017     }
   8018 
   8019     /**
   8020      * Indicates whether the entire hierarchy under this view will save its
   8021      * state when a state saving traversal occurs from its parent.  The default
   8022      * is true; if false, these views will not be saved unless
   8023      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
   8024      *
   8025      * @return Returns true if the view state saving from parent is enabled, else false.
   8026      *
   8027      * @see #setSaveFromParentEnabled(boolean)
   8028      */
   8029     public boolean isSaveFromParentEnabled() {
   8030         return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
   8031     }
   8032 
   8033     /**
   8034      * Controls whether the entire hierarchy under this view will save its
   8035      * state when a state saving traversal occurs from its parent.  The default
   8036      * is true; if false, these views will not be saved unless
   8037      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
   8038      *
   8039      * @param enabled Set to false to <em>disable</em> state saving, or true
   8040      * (the default) to allow it.
   8041      *
   8042      * @see #isSaveFromParentEnabled()
   8043      * @see #setId(int)
   8044      * @see #onSaveInstanceState()
   8045      */
   8046     public void setSaveFromParentEnabled(boolean enabled) {
   8047         setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
   8048     }
   8049 
   8050 
   8051     /**
   8052      * Returns whether this View is able to take focus.
   8053      *
   8054      * @return True if this view can take focus, or false otherwise.
   8055      * @attr ref android.R.styleable#View_focusable
   8056      */
   8057     @ViewDebug.ExportedProperty(category = "focus")
   8058     public final boolean isFocusable() {
   8059         return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
   8060     }
   8061 
   8062     /**
   8063      * When a view is focusable, it may not want to take focus when in touch mode.
   8064      * For example, a button would like focus when the user is navigating via a D-pad
   8065      * so that the user can click on it, but once the user starts touching the screen,
   8066      * the button shouldn't take focus
   8067      * @return Whether the view is focusable in touch mode.
   8068      * @attr ref android.R.styleable#View_focusableInTouchMode
   8069      */
   8070     @ViewDebug.ExportedProperty
   8071     public final boolean isFocusableInTouchMode() {
   8072         return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
   8073     }
   8074 
   8075     /**
   8076      * Find the nearest view in the specified direction that can take focus.
   8077      * This does not actually give focus to that view.
   8078      *
   8079      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
   8080      *
   8081      * @return The nearest focusable in the specified direction, or null if none
   8082      *         can be found.
   8083      */
   8084     public View focusSearch(@FocusRealDirection int direction) {
   8085         if (mParent != null) {
   8086             return mParent.focusSearch(this, direction);
   8087         } else {
   8088             return null;
   8089         }
   8090     }
   8091 
   8092     /**
   8093      * This method is the last chance for the focused view and its ancestors to
   8094      * respond to an arrow key. This is called when the focused view did not
   8095      * consume the key internally, nor could the view system find a new view in
   8096      * the requested direction to give focus to.
   8097      *
   8098      * @param focused The currently focused view.
   8099      * @param direction The direction focus wants to move. One of FOCUS_UP,
   8100      *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
   8101      * @return True if the this view consumed this unhandled move.
   8102      */
   8103     public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
   8104         return false;
   8105     }
   8106 
   8107     /**
   8108      * If a user manually specified the next view id for a particular direction,
   8109      * use the root to look up the view.
   8110      * @param root The root view of the hierarchy containing this view.
   8111      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
   8112      * or FOCUS_BACKWARD.
   8113      * @return The user specified next view, or null if there is none.
   8114      */
   8115     View findUserSetNextFocus(View root, @FocusDirection int direction) {
   8116         switch (direction) {
   8117             case FOCUS_LEFT:
   8118                 if (mNextFocusLeftId == View.NO_ID) return null;
   8119                 return findViewInsideOutShouldExist(root, mNextFocusLeftId);
   8120             case FOCUS_RIGHT:
   8121                 if (mNextFocusRightId == View.NO_ID) return null;
   8122                 return findViewInsideOutShouldExist(root, mNextFocusRightId);
   8123             case FOCUS_UP:
   8124                 if (mNextFocusUpId == View.NO_ID) return null;
   8125                 return findViewInsideOutShouldExist(root, mNextFocusUpId);
   8126             case FOCUS_DOWN:
   8127                 if (mNextFocusDownId == View.NO_ID) return null;
   8128                 return findViewInsideOutShouldExist(root, mNextFocusDownId);
   8129             case FOCUS_FORWARD:
   8130                 if (mNextFocusForwardId == View.NO_ID) return null;
   8131                 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
   8132             case FOCUS_BACKWARD: {
   8133                 if (mID == View.NO_ID) return null;
   8134                 final int id = mID;
   8135                 return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
   8136                     @Override
   8137                     public boolean apply(View t) {
   8138                         return t.mNextFocusForwardId == id;
   8139                     }
   8140                 });
   8141             }
   8142         }
   8143         return null;
   8144     }
   8145 
   8146     private View findViewInsideOutShouldExist(View root, int id) {
   8147         if (mMatchIdPredicate == null) {
   8148             mMatchIdPredicate = new MatchIdPredicate();
   8149         }
   8150         mMatchIdPredicate.mId = id;
   8151         View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
   8152         if (result == null) {
   8153             Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
   8154         }
   8155         return result;
   8156     }
   8157 
   8158     /**
   8159      * Find and return all focusable views that are descendants of this view,
   8160      * possibly including this view if it is focusable itself.
   8161      *
   8162      * @param direction The direction of the focus
   8163      * @return A list of focusable views
   8164      */
   8165     public ArrayList<View> getFocusables(@FocusDirection int direction) {
   8166         ArrayList<View> result = new ArrayList<View>(24);
   8167         addFocusables(result, direction);
   8168         return result;
   8169     }
   8170 
   8171     /**
   8172      * Add any focusable views that are descendants of this view (possibly
   8173      * including this view if it is focusable itself) to views.  If we are in touch mode,
   8174      * only add views that are also focusable in touch mode.
   8175      *
   8176      * @param views Focusable views found so far
   8177      * @param direction The direction of the focus
   8178      */
   8179     public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
   8180         addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
   8181     }
   8182 
   8183     /**
   8184      * Adds any focusable views that are descendants of this view (possibly
   8185      * including this view if it is focusable itself) to views. This method
   8186      * adds all focusable views regardless if we are in touch mode or
   8187      * only views focusable in touch mode if we are in touch mode or
   8188      * only views that can take accessibility focus if accessibility is enabled
   8189      * depending on the focusable mode parameter.
   8190      *
   8191      * @param views Focusable views found so far or null if all we are interested is
   8192      *        the number of focusables.
   8193      * @param direction The direction of the focus.
   8194      * @param focusableMode The type of focusables to be added.
   8195      *
   8196      * @see #FOCUSABLES_ALL
   8197      * @see #FOCUSABLES_TOUCH_MODE
   8198      */
   8199     public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
   8200             @FocusableMode int focusableMode) {
   8201         if (views == null) {
   8202             return;
   8203         }
   8204         if (!isFocusable()) {
   8205             return;
   8206         }
   8207         if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
   8208                 && isInTouchMode() && !isFocusableInTouchMode()) {
   8209             return;
   8210         }
   8211         views.add(this);
   8212     }
   8213 
   8214     /**
   8215      * Finds the Views that contain given text. The containment is case insensitive.
   8216      * The search is performed by either the text that the View renders or the content
   8217      * description that describes the view for accessibility purposes and the view does
   8218      * not render or both. Clients can specify how the search is to be performed via
   8219      * passing the {@link #FIND_VIEWS_WITH_TEXT} and
   8220      * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
   8221      *
   8222      * @param outViews The output list of matching Views.
   8223      * @param searched The text to match against.
   8224      *
   8225      * @see #FIND_VIEWS_WITH_TEXT
   8226      * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
   8227      * @see #setContentDescription(CharSequence)
   8228      */
   8229     public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
   8230             @FindViewFlags int flags) {
   8231         if (getAccessibilityNodeProvider() != null) {
   8232             if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
   8233                 outViews.add(this);
   8234             }
   8235         } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
   8236                 && (searched != null && searched.length() > 0)
   8237                 && (mContentDescription != null && mContentDescription.length() > 0)) {
   8238             String searchedLowerCase = searched.toString().toLowerCase();
   8239             String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
   8240             if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
   8241                 outViews.add(this);
   8242             }
   8243         }
   8244     }
   8245 
   8246     /**
   8247      * Find and return all touchable views that are descendants of this view,
   8248      * possibly including this view if it is touchable itself.
   8249      *
   8250      * @return A list of touchable views
   8251      */
   8252     public ArrayList<View> getTouchables() {
   8253         ArrayList<View> result = new ArrayList<View>();
   8254         addTouchables(result);
   8255         return result;
   8256     }
   8257 
   8258     /**
   8259      * Add any touchable views that are descendants of this view (possibly
   8260      * including this view if it is touchable itself) to views.
   8261      *
   8262      * @param views Touchable views found so far
   8263      */
   8264     public void addTouchables(ArrayList<View> views) {
   8265         final int viewFlags = mViewFlags;
   8266 
   8267         if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
   8268                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
   8269                 && (viewFlags & ENABLED_MASK) == ENABLED) {
   8270             views.add(this);
   8271         }
   8272     }
   8273 
   8274     /**
   8275      * Returns whether this View is accessibility focused.
   8276      *
   8277      * @return True if this View is accessibility focused.
   8278      */
   8279     public boolean isAccessibilityFocused() {
   8280         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
   8281     }
   8282 
   8283     /**
   8284      * Call this to try to give accessibility focus to this view.
   8285      *
   8286      * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
   8287      * returns false or the view is no visible or the view already has accessibility
   8288      * focus.
   8289      *
   8290      * See also {@link #focusSearch(int)}, which is what you call to say that you
   8291      * have focus, and you want your parent to look for the next one.
   8292      *
   8293      * @return Whether this view actually took accessibility focus.
   8294      *
   8295      * @hide
   8296      */
   8297     public boolean requestAccessibilityFocus() {
   8298         AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
   8299         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
   8300             return false;
   8301         }
   8302         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
   8303             return false;
   8304         }
   8305         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
   8306             mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
   8307             ViewRootImpl viewRootImpl = getViewRootImpl();
   8308             if (viewRootImpl != null) {
   8309                 viewRootImpl.setAccessibilityFocus(this, null);
   8310             }
   8311             invalidate();
   8312             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
   8313             return true;
   8314         }
   8315         return false;
   8316     }
   8317 
   8318     /**
   8319      * Call this to try to clear accessibility focus of this view.
   8320      *
   8321      * See also {@link #focusSearch(int)}, which is what you call to say that you
   8322      * have focus, and you want your parent to look for the next one.
   8323      *
   8324      * @hide
   8325      */
   8326     public void clearAccessibilityFocus() {
   8327         clearAccessibilityFocusNoCallbacks();
   8328         // Clear the global reference of accessibility focus if this
   8329         // view or any of its descendants had accessibility focus.
   8330         ViewRootImpl viewRootImpl = getViewRootImpl();
   8331         if (viewRootImpl != null) {
   8332             View focusHost = viewRootImpl.getAccessibilityFocusedHost();
   8333             if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
   8334                 viewRootImpl.setAccessibilityFocus(null, null);
   8335             }
   8336         }
   8337     }
   8338 
   8339     private void sendAccessibilityHoverEvent(int eventType) {
   8340         // Since we are not delivering to a client accessibility events from not
   8341         // important views (unless the clinet request that) we need to fire the
   8342         // event from the deepest view exposed to the client. As a consequence if
   8343         // the user crosses a not exposed view the client will see enter and exit
   8344         // of the exposed predecessor followed by and enter and exit of that same
   8345         // predecessor when entering and exiting the not exposed descendant. This
   8346         // is fine since the client has a clear idea which view is hovered at the
   8347         // price of a couple more events being sent. This is a simple and
   8348         // working solution.
   8349         View source = this;
   8350         while (true) {
   8351             if (source.includeForAccessibility()) {
   8352                 source.sendAccessibilityEvent(eventType);
   8353                 return;
   8354             }
   8355             ViewParent parent = source.getParent();
   8356             if (parent instanceof View) {
   8357                 source = (View) parent;
   8358             } else {
   8359                 return;
   8360             }
   8361         }
   8362     }
   8363 
   8364     /**
   8365      * Clears accessibility focus without calling any callback methods
   8366      * normally invoked in {@link #clearAccessibilityFocus()}. This method
   8367      * is used for clearing accessibility focus when giving this focus to
   8368      * another view.
   8369      */
   8370     void clearAccessibilityFocusNoCallbacks() {
   8371         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
   8372             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
   8373             invalidate();
   8374             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
   8375         }
   8376     }
   8377 
   8378     /**
   8379      * Call this to try to give focus to a specific view or to one of its
   8380      * descendants.
   8381      *
   8382      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
   8383      * false), or if it is focusable and it is not focusable in touch mode
   8384      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
   8385      *
   8386      * See also {@link #focusSearch(int)}, which is what you call to say that you
   8387      * have focus, and you want your parent to look for the next one.
   8388      *
   8389      * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
   8390      * {@link #FOCUS_DOWN} and <code>null</code>.
   8391      *
   8392      * @return Whether this view or one of its descendants actually took focus.
   8393      */
   8394     public final boolean requestFocus() {
   8395         return requestFocus(View.FOCUS_DOWN);
   8396     }
   8397 
   8398     /**
   8399      * Call this to try to give focus to a specific view or to one of its
   8400      * descendants and give it a hint about what direction focus is heading.
   8401      *
   8402      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
   8403      * false), or if it is focusable and it is not focusable in touch mode
   8404      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
   8405      *
   8406      * See also {@link #focusSearch(int)}, which is what you call to say that you
   8407      * have focus, and you want your parent to look for the next one.
   8408      *
   8409      * This is equivalent to calling {@link #requestFocus(int, Rect)} with
   8410      * <code>null</code> set for the previously focused rectangle.
   8411      *
   8412      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
   8413      * @return Whether this view or one of its descendants actually took focus.
   8414      */
   8415     public final boolean requestFocus(int direction) {
   8416         return requestFocus(direction, null);
   8417     }
   8418 
   8419     /**
   8420      * Call this to try to give focus to a specific view or to one of its descendants
   8421      * and give it hints about the direction and a specific rectangle that the focus
   8422      * is coming from.  The rectangle can help give larger views a finer grained hint
   8423      * about where focus is coming from, and therefore, where to show selection, or
   8424      * forward focus change internally.
   8425      *
   8426      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
   8427      * false), or if it is focusable and it is not focusable in touch mode
   8428      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
   8429      *
   8430      * A View will not take focus if it is not visible.
   8431      *
   8432      * A View will not take focus if one of its parents has
   8433      * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
   8434      * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
   8435      *
   8436      * See also {@link #focusSearch(int)}, which is what you call to say that you
   8437      * have focus, and you want your parent to look for the next one.
   8438      *
   8439      * You may wish to override this method if your custom {@link View} has an internal
   8440      * {@link View} that it wishes to forward the request to.
   8441      *
   8442      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
   8443      * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
   8444      *        to give a finer grained hint about where focus is coming from.  May be null
   8445      *        if there is no hint.
   8446      * @return Whether this view or one of its descendants actually took focus.
   8447      */
   8448     public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
   8449         return requestFocusNoSearch(direction, previouslyFocusedRect);
   8450     }
   8451 
   8452     private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
   8453         // need to be focusable
   8454         if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
   8455                 (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
   8456             return false;
   8457         }
   8458 
   8459         // need to be focusable in touch mode if in touch mode
   8460         if (isInTouchMode() &&
   8461             (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
   8462                return false;
   8463         }
   8464 
   8465         // need to not have any parents blocking us
   8466         if (hasAncestorThatBlocksDescendantFocus()) {
   8467             return false;
   8468         }
   8469 
   8470         handleFocusGainInternal(direction, previouslyFocusedRect);
   8471         return true;
   8472     }
   8473 
   8474     /**
   8475      * Call this to try to give focus to a specific view or to one of its descendants. This is a
   8476      * special variant of {@link #requestFocus() } that will allow views that are not focusable in
   8477      * touch mode to request focus when they are touched.
   8478      *
   8479      * @return Whether this view or one of its descendants actually took focus.
   8480      *
   8481      * @see #isInTouchMode()
   8482      *
   8483      */
   8484     public final boolean requestFocusFromTouch() {
   8485         // Leave touch mode if we need to
   8486         if (isInTouchMode()) {
   8487             ViewRootImpl viewRoot = getViewRootImpl();
   8488             if (viewRoot != null) {
   8489                 viewRoot.ensureTouchMode(false);
   8490             }
   8491         }
   8492         return requestFocus(View.FOCUS_DOWN);
   8493     }
   8494 
   8495     /**
   8496      * @return Whether any ancestor of this view blocks descendant focus.
   8497      */
   8498     private boolean hasAncestorThatBlocksDescendantFocus() {
   8499         final boolean focusableInTouchMode = isFocusableInTouchMode();
   8500         ViewParent ancestor = mParent;
   8501         while (ancestor instanceof ViewGroup) {
   8502             final ViewGroup vgAncestor = (ViewGroup) ancestor;
   8503             if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
   8504                     || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
   8505                 return true;
   8506             } else {
   8507                 ancestor = vgAncestor.getParent();
   8508             }
   8509         }
   8510         return false;
   8511     }
   8512 
   8513     /**
   8514      * Gets the mode for determining whether this View is important for accessibility
   8515      * which is if it fires accessibility events and if it is reported to
   8516      * accessibility services that query the screen.
   8517      *
   8518      * @return The mode for determining whether a View is important for accessibility.
   8519      *
   8520      * @attr ref android.R.styleable#View_importantForAccessibility
   8521      *
   8522      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
   8523      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
   8524      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
   8525      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
   8526      */
   8527     @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
   8528             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
   8529             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
   8530             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
   8531             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
   8532                     to = "noHideDescendants")
   8533         })
   8534     public int getImportantForAccessibility() {
   8535         return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
   8536                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
   8537     }
   8538 
   8539     /**
   8540      * Sets the live region mode for this view. This indicates to accessibility
   8541      * services whether they should automatically notify the user about changes
   8542      * to the view's content description or text, or to the content descriptions
   8543      * or text of the view's children (where applicable).
   8544      * <p>
   8545      * For example, in a login screen with a TextView that displays an "incorrect
   8546      * password" notification, that view should be marked as a live region with
   8547      * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
   8548      * <p>
   8549      * To disable change notifications for this view, use
   8550      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
   8551      * mode for most views.
   8552      * <p>
   8553      * To indicate that the user should be notified of changes, use
   8554      * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
   8555      * <p>
   8556      * If the view's changes should interrupt ongoing speech and notify the user
   8557      * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
   8558      *
   8559      * @param mode The live region mode for this view, one of:
   8560      *        <ul>
   8561      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
   8562      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
   8563      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
   8564      *        </ul>
   8565      * @attr ref android.R.styleable#View_accessibilityLiveRegion
   8566      */
   8567     public void setAccessibilityLiveRegion(int mode) {
   8568         if (mode != getAccessibilityLiveRegion()) {
   8569             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
   8570             mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
   8571                     & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
   8572             notifyViewAccessibilityStateChangedIfNeeded(
   8573                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   8574         }
   8575     }
   8576 
   8577     /**
   8578      * Gets the live region mode for this View.
   8579      *
   8580      * @return The live region mode for the view.
   8581      *
   8582      * @attr ref android.R.styleable#View_accessibilityLiveRegion
   8583      *
   8584      * @see #setAccessibilityLiveRegion(int)
   8585      */
   8586     public int getAccessibilityLiveRegion() {
   8587         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
   8588                 >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
   8589     }
   8590 
   8591     /**
   8592      * Sets how to determine whether this view is important for accessibility
   8593      * which is if it fires accessibility events and if it is reported to
   8594      * accessibility services that query the screen.
   8595      *
   8596      * @param mode How to determine whether this view is important for accessibility.
   8597      *
   8598      * @attr ref android.R.styleable#View_importantForAccessibility
   8599      *
   8600      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
   8601      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
   8602      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
   8603      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
   8604      */
   8605     public void setImportantForAccessibility(int mode) {
   8606         final int oldMode = getImportantForAccessibility();
   8607         if (mode != oldMode) {
   8608             // If we're moving between AUTO and another state, we might not need
   8609             // to send a subtree changed notification. We'll store the computed
   8610             // importance, since we'll need to check it later to make sure.
   8611             final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
   8612                     || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
   8613             final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
   8614             mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
   8615             mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
   8616                     & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
   8617             if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
   8618                 notifySubtreeAccessibilityStateChangedIfNeeded();
   8619             } else {
   8620                 notifyViewAccessibilityStateChangedIfNeeded(
   8621                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   8622             }
   8623         }
   8624     }
   8625 
   8626     /**
   8627      * Computes whether this view should be exposed for accessibility. In
   8628      * general, views that are interactive or provide information are exposed
   8629      * while views that serve only as containers are hidden.
   8630      * <p>
   8631      * If an ancestor of this view has importance
   8632      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
   8633      * returns <code>false</code>.
   8634      * <p>
   8635      * Otherwise, the value is computed according to the view's
   8636      * {@link #getImportantForAccessibility()} value:
   8637      * <ol>
   8638      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
   8639      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
   8640      * </code>
   8641      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
   8642      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
   8643      * view satisfies any of the following:
   8644      * <ul>
   8645      * <li>Is actionable, e.g. {@link #isClickable()},
   8646      * {@link #isLongClickable()}, or {@link #isFocusable()}
   8647      * <li>Has an {@link AccessibilityDelegate}
   8648      * <li>Has an interaction listener, e.g. {@link OnTouchListener},
   8649      * {@link OnKeyListener}, etc.
   8650      * <li>Is an accessibility live region, e.g.
   8651      * {@link #getAccessibilityLiveRegion()} is not
   8652      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
   8653      * </ul>
   8654      * </ol>
   8655      *
   8656      * @return Whether the view is exposed for accessibility.
   8657      * @see #setImportantForAccessibility(int)
   8658      * @see #getImportantForAccessibility()
   8659      */
   8660     public boolean isImportantForAccessibility() {
   8661         final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
   8662                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
   8663         if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
   8664                 || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
   8665             return false;
   8666         }
   8667 
   8668         // Check parent mode to ensure we're not hidden.
   8669         ViewParent parent = mParent;
   8670         while (parent instanceof View) {
   8671             if (((View) parent).getImportantForAccessibility()
   8672                     == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
   8673                 return false;
   8674             }
   8675             parent = parent.getParent();
   8676         }
   8677 
   8678         return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
   8679                 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
   8680                 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
   8681     }
   8682 
   8683     /**
   8684      * Gets the parent for accessibility purposes. Note that the parent for
   8685      * accessibility is not necessary the immediate parent. It is the first
   8686      * predecessor that is important for accessibility.
   8687      *
   8688      * @return The parent for accessibility purposes.
   8689      */
   8690     public ViewParent getParentForAccessibility() {
   8691         if (mParent instanceof View) {
   8692             View parentView = (View) mParent;
   8693             if (parentView.includeForAccessibility()) {
   8694                 return mParent;
   8695             } else {
   8696                 return mParent.getParentForAccessibility();
   8697             }
   8698         }
   8699         return null;
   8700     }
   8701 
   8702     /**
   8703      * Adds the children of this View relevant for accessibility to the given list
   8704      * as output. Since some Views are not important for accessibility the added
   8705      * child views are not necessarily direct children of this view, rather they are
   8706      * the first level of descendants important for accessibility.
   8707      *
   8708      * @param outChildren The output list that will receive children for accessibility.
   8709      */
   8710     public void addChildrenForAccessibility(ArrayList<View> outChildren) {
   8711 
   8712     }
   8713 
   8714     /**
   8715      * Whether to regard this view for accessibility. A view is regarded for
   8716      * accessibility if it is important for accessibility or the querying
   8717      * accessibility service has explicitly requested that view not
   8718      * important for accessibility are regarded.
   8719      *
   8720      * @return Whether to regard the view for accessibility.
   8721      *
   8722      * @hide
   8723      */
   8724     public boolean includeForAccessibility() {
   8725         if (mAttachInfo != null) {
   8726             return (mAttachInfo.mAccessibilityFetchFlags
   8727                     & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
   8728                     || isImportantForAccessibility();
   8729         }
   8730         return false;
   8731     }
   8732 
   8733     /**
   8734      * Returns whether the View is considered actionable from
   8735      * accessibility perspective. Such view are important for
   8736      * accessibility.
   8737      *
   8738      * @return True if the view is actionable for accessibility.
   8739      *
   8740      * @hide
   8741      */
   8742     public boolean isActionableForAccessibility() {
   8743         return (isClickable() || isLongClickable() || isFocusable());
   8744     }
   8745 
   8746     /**
   8747      * Returns whether the View has registered callbacks which makes it
   8748      * important for accessibility.
   8749      *
   8750      * @return True if the view is actionable for accessibility.
   8751      */
   8752     private boolean hasListenersForAccessibility() {
   8753         ListenerInfo info = getListenerInfo();
   8754         return mTouchDelegate != null || info.mOnKeyListener != null
   8755                 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
   8756                 || info.mOnHoverListener != null || info.mOnDragListener != null;
   8757     }
   8758 
   8759     /**
   8760      * Notifies that the accessibility state of this view changed. The change
   8761      * is local to this view and does not represent structural changes such
   8762      * as children and parent. For example, the view became focusable. The
   8763      * notification is at at most once every
   8764      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
   8765      * to avoid unnecessary load to the system. Also once a view has a pending
   8766      * notification this method is a NOP until the notification has been sent.
   8767      *
   8768      * @hide
   8769      */
   8770     public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
   8771         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
   8772             return;
   8773         }
   8774         if (mSendViewStateChangedAccessibilityEvent == null) {
   8775             mSendViewStateChangedAccessibilityEvent =
   8776                     new SendViewStateChangedAccessibilityEvent();
   8777         }
   8778         mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
   8779     }
   8780 
   8781     /**
   8782      * Notifies that the accessibility state of this view changed. The change
   8783      * is *not* local to this view and does represent structural changes such
   8784      * as children and parent. For example, the view size changed. The
   8785      * notification is at at most once every
   8786      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
   8787      * to avoid unnecessary load to the system. Also once a view has a pending
   8788      * notification this method is a NOP until the notification has been sent.
   8789      *
   8790      * @hide
   8791      */
   8792     public void notifySubtreeAccessibilityStateChangedIfNeeded() {
   8793         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
   8794             return;
   8795         }
   8796         if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
   8797             mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
   8798             if (mParent != null) {
   8799                 try {
   8800                     mParent.notifySubtreeAccessibilityStateChanged(
   8801                             this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
   8802                 } catch (AbstractMethodError e) {
   8803                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   8804                             " does not fully implement ViewParent", e);
   8805                 }
   8806             }
   8807         }
   8808     }
   8809 
   8810     /**
   8811      * Change the visibility of the View without triggering any other changes. This is
   8812      * important for transitions, where visibility changes should not adjust focus or
   8813      * trigger a new layout. This is only used when the visibility has already been changed
   8814      * and we need a transient value during an animation. When the animation completes,
   8815      * the original visibility value is always restored.
   8816      *
   8817      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
   8818      * @hide
   8819      */
   8820     public void setTransitionVisibility(@Visibility int visibility) {
   8821         mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
   8822     }
   8823 
   8824     /**
   8825      * Reset the flag indicating the accessibility state of the subtree rooted
   8826      * at this view changed.
   8827      */
   8828     void resetSubtreeAccessibilityStateChanged() {
   8829         mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
   8830     }
   8831 
   8832     /**
   8833      * Report an accessibility action to this view's parents for delegated processing.
   8834      *
   8835      * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
   8836      * call this method to delegate an accessibility action to a supporting parent. If the parent
   8837      * returns true from its
   8838      * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
   8839      * method this method will return true to signify that the action was consumed.</p>
   8840      *
   8841      * <p>This method is useful for implementing nested scrolling child views. If
   8842      * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
   8843      * a custom view implementation may invoke this method to allow a parent to consume the
   8844      * scroll first. If this method returns true the custom view should skip its own scrolling
   8845      * behavior.</p>
   8846      *
   8847      * @param action Accessibility action to delegate
   8848      * @param arguments Optional action arguments
   8849      * @return true if the action was consumed by a parent
   8850      */
   8851     public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
   8852         for (ViewParent p = getParent(); p != null; p = p.getParent()) {
   8853             if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
   8854                 return true;
   8855             }
   8856         }
   8857         return false;
   8858     }
   8859 
   8860     /**
   8861      * Performs the specified accessibility action on the view. For
   8862      * possible accessibility actions look at {@link AccessibilityNodeInfo}.
   8863      * <p>
   8864      * If an {@link AccessibilityDelegate} has been specified via calling
   8865      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
   8866      * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
   8867      * is responsible for handling this call.
   8868      * </p>
   8869      *
   8870      * <p>The default implementation will delegate
   8871      * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
   8872      * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
   8873      * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
   8874      *
   8875      * @param action The action to perform.
   8876      * @param arguments Optional action arguments.
   8877      * @return Whether the action was performed.
   8878      */
   8879     public boolean performAccessibilityAction(int action, Bundle arguments) {
   8880       if (mAccessibilityDelegate != null) {
   8881           return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
   8882       } else {
   8883           return performAccessibilityActionInternal(action, arguments);
   8884       }
   8885     }
   8886 
   8887    /**
   8888     * @see #performAccessibilityAction(int, Bundle)
   8889     *
   8890     * Note: Called from the default {@link AccessibilityDelegate}.
   8891     *
   8892     * @hide
   8893     */
   8894     public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
   8895         if (isNestedScrollingEnabled()
   8896                 && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
   8897                 || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
   8898                 || action == R.id.accessibilityActionScrollUp
   8899                 || action == R.id.accessibilityActionScrollLeft
   8900                 || action == R.id.accessibilityActionScrollDown
   8901                 || action == R.id.accessibilityActionScrollRight)) {
   8902             if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
   8903                 return true;
   8904             }
   8905         }
   8906 
   8907         switch (action) {
   8908             case AccessibilityNodeInfo.ACTION_CLICK: {
   8909                 if (isClickable()) {
   8910                     performClick();
   8911                     return true;
   8912                 }
   8913             } break;
   8914             case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
   8915                 if (isLongClickable()) {
   8916                     performLongClick();
   8917                     return true;
   8918                 }
   8919             } break;
   8920             case AccessibilityNodeInfo.ACTION_FOCUS: {
   8921                 if (!hasFocus()) {
   8922                     // Get out of touch mode since accessibility
   8923                     // wants to move focus around.
   8924                     getViewRootImpl().ensureTouchMode(false);
   8925                     return requestFocus();
   8926                 }
   8927             } break;
   8928             case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
   8929                 if (hasFocus()) {
   8930                     clearFocus();
   8931                     return !isFocused();
   8932                 }
   8933             } break;
   8934             case AccessibilityNodeInfo.ACTION_SELECT: {
   8935                 if (!isSelected()) {
   8936                     setSelected(true);
   8937                     return isSelected();
   8938                 }
   8939             } break;
   8940             case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
   8941                 if (isSelected()) {
   8942                     setSelected(false);
   8943                     return !isSelected();
   8944                 }
   8945             } break;
   8946             case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
   8947                 if (!isAccessibilityFocused()) {
   8948                     return requestAccessibilityFocus();
   8949                 }
   8950             } break;
   8951             case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
   8952                 if (isAccessibilityFocused()) {
   8953                     clearAccessibilityFocus();
   8954                     return true;
   8955                 }
   8956             } break;
   8957             case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
   8958                 if (arguments != null) {
   8959                     final int granularity = arguments.getInt(
   8960                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
   8961                     final boolean extendSelection = arguments.getBoolean(
   8962                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
   8963                     return traverseAtGranularity(granularity, true, extendSelection);
   8964                 }
   8965             } break;
   8966             case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
   8967                 if (arguments != null) {
   8968                     final int granularity = arguments.getInt(
   8969                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
   8970                     final boolean extendSelection = arguments.getBoolean(
   8971                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
   8972                     return traverseAtGranularity(granularity, false, extendSelection);
   8973                 }
   8974             } break;
   8975             case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
   8976                 CharSequence text = getIterableTextForAccessibility();
   8977                 if (text == null) {
   8978                     return false;
   8979                 }
   8980                 final int start = (arguments != null) ? arguments.getInt(
   8981                         AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
   8982                 final int end = (arguments != null) ? arguments.getInt(
   8983                 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
   8984                 // Only cursor position can be specified (selection length == 0)
   8985                 if ((getAccessibilitySelectionStart() != start
   8986                         || getAccessibilitySelectionEnd() != end)
   8987                         && (start == end)) {
   8988                     setAccessibilitySelection(start, end);
   8989                     notifyViewAccessibilityStateChangedIfNeeded(
   8990                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   8991                     return true;
   8992                 }
   8993             } break;
   8994             case R.id.accessibilityActionShowOnScreen: {
   8995                 if (mAttachInfo != null) {
   8996                     final Rect r = mAttachInfo.mTmpInvalRect;
   8997                     getDrawingRect(r);
   8998                     return requestRectangleOnScreen(r, true);
   8999                 }
   9000             } break;
   9001             case R.id.accessibilityActionContextClick: {
   9002                 if (isContextClickable()) {
   9003                     performContextClick();
   9004                     return true;
   9005                 }
   9006             } break;
   9007         }
   9008         return false;
   9009     }
   9010 
   9011     private boolean traverseAtGranularity(int granularity, boolean forward,
   9012             boolean extendSelection) {
   9013         CharSequence text = getIterableTextForAccessibility();
   9014         if (text == null || text.length() == 0) {
   9015             return false;
   9016         }
   9017         TextSegmentIterator iterator = getIteratorForGranularity(granularity);
   9018         if (iterator == null) {
   9019             return false;
   9020         }
   9021         int current = getAccessibilitySelectionEnd();
   9022         if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
   9023             current = forward ? 0 : text.length();
   9024         }
   9025         final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
   9026         if (range == null) {
   9027             return false;
   9028         }
   9029         final int segmentStart = range[0];
   9030         final int segmentEnd = range[1];
   9031         int selectionStart;
   9032         int selectionEnd;
   9033         if (extendSelection && isAccessibilitySelectionExtendable()) {
   9034             selectionStart = getAccessibilitySelectionStart();
   9035             if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
   9036                 selectionStart = forward ? segmentStart : segmentEnd;
   9037             }
   9038             selectionEnd = forward ? segmentEnd : segmentStart;
   9039         } else {
   9040             selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
   9041         }
   9042         setAccessibilitySelection(selectionStart, selectionEnd);
   9043         final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
   9044                 : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
   9045         sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
   9046         return true;
   9047     }
   9048 
   9049     /**
   9050      * Gets the text reported for accessibility purposes.
   9051      *
   9052      * @return The accessibility text.
   9053      *
   9054      * @hide
   9055      */
   9056     public CharSequence getIterableTextForAccessibility() {
   9057         return getContentDescription();
   9058     }
   9059 
   9060     /**
   9061      * Gets whether accessibility selection can be extended.
   9062      *
   9063      * @return If selection is extensible.
   9064      *
   9065      * @hide
   9066      */
   9067     public boolean isAccessibilitySelectionExtendable() {
   9068         return false;
   9069     }
   9070 
   9071     /**
   9072      * @hide
   9073      */
   9074     public int getAccessibilitySelectionStart() {
   9075         return mAccessibilityCursorPosition;
   9076     }
   9077 
   9078     /**
   9079      * @hide
   9080      */
   9081     public int getAccessibilitySelectionEnd() {
   9082         return getAccessibilitySelectionStart();
   9083     }
   9084 
   9085     /**
   9086      * @hide
   9087      */
   9088     public void setAccessibilitySelection(int start, int end) {
   9089         if (start ==  end && end == mAccessibilityCursorPosition) {
   9090             return;
   9091         }
   9092         if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
   9093             mAccessibilityCursorPosition = start;
   9094         } else {
   9095             mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
   9096         }
   9097         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
   9098     }
   9099 
   9100     private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
   9101             int fromIndex, int toIndex) {
   9102         if (mParent == null) {
   9103             return;
   9104         }
   9105         AccessibilityEvent event = AccessibilityEvent.obtain(
   9106                 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
   9107         onInitializeAccessibilityEvent(event);
   9108         onPopulateAccessibilityEvent(event);
   9109         event.setFromIndex(fromIndex);
   9110         event.setToIndex(toIndex);
   9111         event.setAction(action);
   9112         event.setMovementGranularity(granularity);
   9113         mParent.requestSendAccessibilityEvent(this, event);
   9114     }
   9115 
   9116     /**
   9117      * @hide
   9118      */
   9119     public TextSegmentIterator getIteratorForGranularity(int granularity) {
   9120         switch (granularity) {
   9121             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
   9122                 CharSequence text = getIterableTextForAccessibility();
   9123                 if (text != null && text.length() > 0) {
   9124                     CharacterTextSegmentIterator iterator =
   9125                         CharacterTextSegmentIterator.getInstance(
   9126                                 mContext.getResources().getConfiguration().locale);
   9127                     iterator.initialize(text.toString());
   9128                     return iterator;
   9129                 }
   9130             } break;
   9131             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
   9132                 CharSequence text = getIterableTextForAccessibility();
   9133                 if (text != null && text.length() > 0) {
   9134                     WordTextSegmentIterator iterator =
   9135                         WordTextSegmentIterator.getInstance(
   9136                                 mContext.getResources().getConfiguration().locale);
   9137                     iterator.initialize(text.toString());
   9138                     return iterator;
   9139                 }
   9140             } break;
   9141             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
   9142                 CharSequence text = getIterableTextForAccessibility();
   9143                 if (text != null && text.length() > 0) {
   9144                     ParagraphTextSegmentIterator iterator =
   9145                         ParagraphTextSegmentIterator.getInstance();
   9146                     iterator.initialize(text.toString());
   9147                     return iterator;
   9148                 }
   9149             } break;
   9150         }
   9151         return null;
   9152     }
   9153 
   9154     /**
   9155      * @hide
   9156      */
   9157     public void dispatchStartTemporaryDetach() {
   9158         onStartTemporaryDetach();
   9159     }
   9160 
   9161     /**
   9162      * This is called when a container is going to temporarily detach a child, with
   9163      * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
   9164      * It will either be followed by {@link #onFinishTemporaryDetach()} or
   9165      * {@link #onDetachedFromWindow()} when the container is done.
   9166      */
   9167     public void onStartTemporaryDetach() {
   9168         removeUnsetPressCallback();
   9169         mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
   9170     }
   9171 
   9172     /**
   9173      * @hide
   9174      */
   9175     public void dispatchFinishTemporaryDetach() {
   9176         onFinishTemporaryDetach();
   9177     }
   9178 
   9179     /**
   9180      * Called after {@link #onStartTemporaryDetach} when the container is done
   9181      * changing the view.
   9182      */
   9183     public void onFinishTemporaryDetach() {
   9184     }
   9185 
   9186     /**
   9187      * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
   9188      * for this view's window.  Returns null if the view is not currently attached
   9189      * to the window.  Normally you will not need to use this directly, but
   9190      * just use the standard high-level event callbacks like
   9191      * {@link #onKeyDown(int, KeyEvent)}.
   9192      */
   9193     public KeyEvent.DispatcherState getKeyDispatcherState() {
   9194         return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
   9195     }
   9196 
   9197     /**
   9198      * Dispatch a key event before it is processed by any input method
   9199      * associated with the view hierarchy.  This can be used to intercept
   9200      * key events in special situations before the IME consumes them; a
   9201      * typical example would be handling the BACK key to update the application's
   9202      * UI instead of allowing the IME to see it and close itself.
   9203      *
   9204      * @param event The key event to be dispatched.
   9205      * @return True if the event was handled, false otherwise.
   9206      */
   9207     public boolean dispatchKeyEventPreIme(KeyEvent event) {
   9208         return onKeyPreIme(event.getKeyCode(), event);
   9209     }
   9210 
   9211     /**
   9212      * Dispatch a key event to the next view on the focus path. This path runs
   9213      * from the top of the view tree down to the currently focused view. If this
   9214      * view has focus, it will dispatch to itself. Otherwise it will dispatch
   9215      * the next node down the focus path. This method also fires any key
   9216      * listeners.
   9217      *
   9218      * @param event The key event to be dispatched.
   9219      * @return True if the event was handled, false otherwise.
   9220      */
   9221     public boolean dispatchKeyEvent(KeyEvent event) {
   9222         if (mInputEventConsistencyVerifier != null) {
   9223             mInputEventConsistencyVerifier.onKeyEvent(event, 0);
   9224         }
   9225 
   9226         // Give any attached key listener a first crack at the event.
   9227         //noinspection SimplifiableIfStatement
   9228         ListenerInfo li = mListenerInfo;
   9229         if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
   9230                 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
   9231             return true;
   9232         }
   9233 
   9234         if (event.dispatch(this, mAttachInfo != null
   9235                 ? mAttachInfo.mKeyDispatchState : null, this)) {
   9236             return true;
   9237         }
   9238 
   9239         if (mInputEventConsistencyVerifier != null) {
   9240             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
   9241         }
   9242         return false;
   9243     }
   9244 
   9245     /**
   9246      * Dispatches a key shortcut event.
   9247      *
   9248      * @param event The key event to be dispatched.
   9249      * @return True if the event was handled by the view, false otherwise.
   9250      */
   9251     public boolean dispatchKeyShortcutEvent(KeyEvent event) {
   9252         return onKeyShortcut(event.getKeyCode(), event);
   9253     }
   9254 
   9255     /**
   9256      * Pass the touch screen motion event down to the target view, or this
   9257      * view if it is the target.
   9258      *
   9259      * @param event The motion event to be dispatched.
   9260      * @return True if the event was handled by the view, false otherwise.
   9261      */
   9262     public boolean dispatchTouchEvent(MotionEvent event) {
   9263         // If the event should be handled by accessibility focus first.
   9264         if (event.isTargetAccessibilityFocus()) {
   9265             // We don't have focus or no virtual descendant has it, do not handle the event.
   9266             if (!isAccessibilityFocusedViewOrHost()) {
   9267                 return false;
   9268             }
   9269             // We have focus and got the event, then use normal event dispatch.
   9270             event.setTargetAccessibilityFocus(false);
   9271         }
   9272 
   9273         boolean result = false;
   9274 
   9275         if (mInputEventConsistencyVerifier != null) {
   9276             mInputEventConsistencyVerifier.onTouchEvent(event, 0);
   9277         }
   9278 
   9279         final int actionMasked = event.getActionMasked();
   9280         if (actionMasked == MotionEvent.ACTION_DOWN) {
   9281             // Defensive cleanup for new gesture
   9282             stopNestedScroll();
   9283         }
   9284 
   9285         if (onFilterTouchEventForSecurity(event)) {
   9286             //noinspection SimplifiableIfStatement
   9287             ListenerInfo li = mListenerInfo;
   9288             if (li != null && li.mOnTouchListener != null
   9289                     && (mViewFlags & ENABLED_MASK) == ENABLED
   9290                     && li.mOnTouchListener.onTouch(this, event)) {
   9291                 result = true;
   9292             }
   9293 
   9294             if (!result && onTouchEvent(event)) {
   9295                 result = true;
   9296             }
   9297         }
   9298 
   9299         if (!result && mInputEventConsistencyVerifier != null) {
   9300             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
   9301         }
   9302 
   9303         // Clean up after nested scrolls if this is the end of a gesture;
   9304         // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
   9305         // of the gesture.
   9306         if (actionMasked == MotionEvent.ACTION_UP ||
   9307                 actionMasked == MotionEvent.ACTION_CANCEL ||
   9308                 (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
   9309             stopNestedScroll();
   9310         }
   9311 
   9312         return result;
   9313     }
   9314 
   9315     boolean isAccessibilityFocusedViewOrHost() {
   9316         return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
   9317                 .getAccessibilityFocusedHost() == this);
   9318     }
   9319 
   9320     /**
   9321      * Filter the touch event to apply security policies.
   9322      *
   9323      * @param event The motion event to be filtered.
   9324      * @return True if the event should be dispatched, false if the event should be dropped.
   9325      *
   9326      * @see #getFilterTouchesWhenObscured
   9327      */
   9328     public boolean onFilterTouchEventForSecurity(MotionEvent event) {
   9329         //noinspection RedundantIfStatement
   9330         if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
   9331                 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
   9332             // Window is obscured, drop this touch.
   9333             return false;
   9334         }
   9335         return true;
   9336     }
   9337 
   9338     /**
   9339      * Pass a trackball motion event down to the focused view.
   9340      *
   9341      * @param event The motion event to be dispatched.
   9342      * @return True if the event was handled by the view, false otherwise.
   9343      */
   9344     public boolean dispatchTrackballEvent(MotionEvent event) {
   9345         if (mInputEventConsistencyVerifier != null) {
   9346             mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
   9347         }
   9348 
   9349         return onTrackballEvent(event);
   9350     }
   9351 
   9352     /**
   9353      * Dispatch a generic motion event.
   9354      * <p>
   9355      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
   9356      * are delivered to the view under the pointer.  All other generic motion events are
   9357      * delivered to the focused view.  Hover events are handled specially and are delivered
   9358      * to {@link #onHoverEvent(MotionEvent)}.
   9359      * </p>
   9360      *
   9361      * @param event The motion event to be dispatched.
   9362      * @return True if the event was handled by the view, false otherwise.
   9363      */
   9364     public boolean dispatchGenericMotionEvent(MotionEvent event) {
   9365         if (mInputEventConsistencyVerifier != null) {
   9366             mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
   9367         }
   9368 
   9369         final int source = event.getSource();
   9370         if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
   9371             final int action = event.getAction();
   9372             if (action == MotionEvent.ACTION_HOVER_ENTER
   9373                     || action == MotionEvent.ACTION_HOVER_MOVE
   9374                     || action == MotionEvent.ACTION_HOVER_EXIT) {
   9375                 if (dispatchHoverEvent(event)) {
   9376                     return true;
   9377                 }
   9378             } else if (dispatchGenericPointerEvent(event)) {
   9379                 return true;
   9380             }
   9381         } else if (dispatchGenericFocusedEvent(event)) {
   9382             return true;
   9383         }
   9384 
   9385         if (dispatchGenericMotionEventInternal(event)) {
   9386             return true;
   9387         }
   9388 
   9389         if (mInputEventConsistencyVerifier != null) {
   9390             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
   9391         }
   9392         return false;
   9393     }
   9394 
   9395     private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
   9396         //noinspection SimplifiableIfStatement
   9397         ListenerInfo li = mListenerInfo;
   9398         if (li != null && li.mOnGenericMotionListener != null
   9399                 && (mViewFlags & ENABLED_MASK) == ENABLED
   9400                 && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
   9401             return true;
   9402         }
   9403 
   9404         if (onGenericMotionEvent(event)) {
   9405             return true;
   9406         }
   9407 
   9408         final int actionButton = event.getActionButton();
   9409         switch (event.getActionMasked()) {
   9410             case MotionEvent.ACTION_BUTTON_PRESS:
   9411                 if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
   9412                         && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
   9413                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
   9414                     if (performContextClick()) {
   9415                         mInContextButtonPress = true;
   9416                         setPressed(true, event.getX(), event.getY());
   9417                         removeTapCallback();
   9418                         removeLongPressCallback();
   9419                         return true;
   9420                     }
   9421                 }
   9422                 break;
   9423 
   9424             case MotionEvent.ACTION_BUTTON_RELEASE:
   9425                 if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
   9426                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
   9427                     mInContextButtonPress = false;
   9428                     mIgnoreNextUpEvent = true;
   9429                 }
   9430                 break;
   9431         }
   9432 
   9433         if (mInputEventConsistencyVerifier != null) {
   9434             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
   9435         }
   9436         return false;
   9437     }
   9438 
   9439     /**
   9440      * Dispatch a hover event.
   9441      * <p>
   9442      * Do not call this method directly.
   9443      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
   9444      * </p>
   9445      *
   9446      * @param event The motion event to be dispatched.
   9447      * @return True if the event was handled by the view, false otherwise.
   9448      */
   9449     protected boolean dispatchHoverEvent(MotionEvent event) {
   9450         ListenerInfo li = mListenerInfo;
   9451         //noinspection SimplifiableIfStatement
   9452         if (li != null && li.mOnHoverListener != null
   9453                 && (mViewFlags & ENABLED_MASK) == ENABLED
   9454                 && li.mOnHoverListener.onHover(this, event)) {
   9455             return true;
   9456         }
   9457 
   9458         return onHoverEvent(event);
   9459     }
   9460 
   9461     /**
   9462      * Returns true if the view has a child to which it has recently sent
   9463      * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
   9464      * it does not have a hovered child, then it must be the innermost hovered view.
   9465      * @hide
   9466      */
   9467     protected boolean hasHoveredChild() {
   9468         return false;
   9469     }
   9470 
   9471     /**
   9472      * Dispatch a generic motion event to the view under the first pointer.
   9473      * <p>
   9474      * Do not call this method directly.
   9475      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
   9476      * </p>
   9477      *
   9478      * @param event The motion event to be dispatched.
   9479      * @return True if the event was handled by the view, false otherwise.
   9480      */
   9481     protected boolean dispatchGenericPointerEvent(MotionEvent event) {
   9482         return false;
   9483     }
   9484 
   9485     /**
   9486      * Dispatch a generic motion event to the currently focused view.
   9487      * <p>
   9488      * Do not call this method directly.
   9489      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
   9490      * </p>
   9491      *
   9492      * @param event The motion event to be dispatched.
   9493      * @return True if the event was handled by the view, false otherwise.
   9494      */
   9495     protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
   9496         return false;
   9497     }
   9498 
   9499     /**
   9500      * Dispatch a pointer event.
   9501      * <p>
   9502      * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
   9503      * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
   9504      * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
   9505      * and should not be expected to handle other pointing device features.
   9506      * </p>
   9507      *
   9508      * @param event The motion event to be dispatched.
   9509      * @return True if the event was handled by the view, false otherwise.
   9510      * @hide
   9511      */
   9512     public final boolean dispatchPointerEvent(MotionEvent event) {
   9513         if (event.isTouchEvent()) {
   9514             return dispatchTouchEvent(event);
   9515         } else {
   9516             return dispatchGenericMotionEvent(event);
   9517         }
   9518     }
   9519 
   9520     /**
   9521      * Called when the window containing this view gains or loses window focus.
   9522      * ViewGroups should override to route to their children.
   9523      *
   9524      * @param hasFocus True if the window containing this view now has focus,
   9525      *        false otherwise.
   9526      */
   9527     public void dispatchWindowFocusChanged(boolean hasFocus) {
   9528         onWindowFocusChanged(hasFocus);
   9529     }
   9530 
   9531     /**
   9532      * Called when the window containing this view gains or loses focus.  Note
   9533      * that this is separate from view focus: to receive key events, both
   9534      * your view and its window must have focus.  If a window is displayed
   9535      * on top of yours that takes input focus, then your own window will lose
   9536      * focus but the view focus will remain unchanged.
   9537      *
   9538      * @param hasWindowFocus True if the window containing this view now has
   9539      *        focus, false otherwise.
   9540      */
   9541     public void onWindowFocusChanged(boolean hasWindowFocus) {
   9542         InputMethodManager imm = InputMethodManager.peekInstance();
   9543         if (!hasWindowFocus) {
   9544             if (isPressed()) {
   9545                 setPressed(false);
   9546             }
   9547             if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
   9548                 imm.focusOut(this);
   9549             }
   9550             removeLongPressCallback();
   9551             removeTapCallback();
   9552             onFocusLost();
   9553         } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
   9554             imm.focusIn(this);
   9555         }
   9556         refreshDrawableState();
   9557     }
   9558 
   9559     /**
   9560      * Returns true if this view is in a window that currently has window focus.
   9561      * Note that this is not the same as the view itself having focus.
   9562      *
   9563      * @return True if this view is in a window that currently has window focus.
   9564      */
   9565     public boolean hasWindowFocus() {
   9566         return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
   9567     }
   9568 
   9569     /**
   9570      * Dispatch a view visibility change down the view hierarchy.
   9571      * ViewGroups should override to route to their children.
   9572      * @param changedView The view whose visibility changed. Could be 'this' or
   9573      * an ancestor view.
   9574      * @param visibility The new visibility of changedView: {@link #VISIBLE},
   9575      * {@link #INVISIBLE} or {@link #GONE}.
   9576      */
   9577     protected void dispatchVisibilityChanged(@NonNull View changedView,
   9578             @Visibility int visibility) {
   9579         onVisibilityChanged(changedView, visibility);
   9580     }
   9581 
   9582     /**
   9583      * Called when the visibility of the view or an ancestor of the view has
   9584      * changed.
   9585      *
   9586      * @param changedView The view whose visibility changed. May be
   9587      *                    {@code this} or an ancestor view.
   9588      * @param visibility The new visibility, one of {@link #VISIBLE},
   9589      *                   {@link #INVISIBLE} or {@link #GONE}.
   9590      */
   9591     protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
   9592         final boolean visible = visibility == VISIBLE && getVisibility() == VISIBLE;
   9593         if (visible && mAttachInfo != null) {
   9594             initialAwakenScrollBars();
   9595         }
   9596 
   9597         final Drawable dr = mBackground;
   9598         if (dr != null && visible != dr.isVisible()) {
   9599             dr.setVisible(visible, false);
   9600         }
   9601         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
   9602         if (fg != null && visible != fg.isVisible()) {
   9603             fg.setVisible(visible, false);
   9604         }
   9605     }
   9606 
   9607     /**
   9608      * Dispatch a hint about whether this view is displayed. For instance, when
   9609      * a View moves out of the screen, it might receives a display hint indicating
   9610      * the view is not displayed. Applications should not <em>rely</em> on this hint
   9611      * as there is no guarantee that they will receive one.
   9612      *
   9613      * @param hint A hint about whether or not this view is displayed:
   9614      * {@link #VISIBLE} or {@link #INVISIBLE}.
   9615      */
   9616     public void dispatchDisplayHint(@Visibility int hint) {
   9617         onDisplayHint(hint);
   9618     }
   9619 
   9620     /**
   9621      * Gives this view a hint about whether is displayed or not. For instance, when
   9622      * a View moves out of the screen, it might receives a display hint indicating
   9623      * the view is not displayed. Applications should not <em>rely</em> on this hint
   9624      * as there is no guarantee that they will receive one.
   9625      *
   9626      * @param hint A hint about whether or not this view is displayed:
   9627      * {@link #VISIBLE} or {@link #INVISIBLE}.
   9628      */
   9629     protected void onDisplayHint(@Visibility int hint) {
   9630     }
   9631 
   9632     /**
   9633      * Dispatch a window visibility change down the view hierarchy.
   9634      * ViewGroups should override to route to their children.
   9635      *
   9636      * @param visibility The new visibility of the window.
   9637      *
   9638      * @see #onWindowVisibilityChanged(int)
   9639      */
   9640     public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
   9641         onWindowVisibilityChanged(visibility);
   9642     }
   9643 
   9644     /**
   9645      * Called when the window containing has change its visibility
   9646      * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
   9647      * that this tells you whether or not your window is being made visible
   9648      * to the window manager; this does <em>not</em> tell you whether or not
   9649      * your window is obscured by other windows on the screen, even if it
   9650      * is itself visible.
   9651      *
   9652      * @param visibility The new visibility of the window.
   9653      */
   9654     protected void onWindowVisibilityChanged(@Visibility int visibility) {
   9655         if (visibility == VISIBLE) {
   9656             initialAwakenScrollBars();
   9657         }
   9658     }
   9659 
   9660     /**
   9661      * Returns the current visibility of the window this view is attached to
   9662      * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
   9663      *
   9664      * @return Returns the current visibility of the view's window.
   9665      */
   9666     @Visibility
   9667     public int getWindowVisibility() {
   9668         return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
   9669     }
   9670 
   9671     /**
   9672      * Retrieve the overall visible display size in which the window this view is
   9673      * attached to has been positioned in.  This takes into account screen
   9674      * decorations above the window, for both cases where the window itself
   9675      * is being position inside of them or the window is being placed under
   9676      * then and covered insets are used for the window to position its content
   9677      * inside.  In effect, this tells you the available area where content can
   9678      * be placed and remain visible to users.
   9679      *
   9680      * <p>This function requires an IPC back to the window manager to retrieve
   9681      * the requested information, so should not be used in performance critical
   9682      * code like drawing.
   9683      *
   9684      * @param outRect Filled in with the visible display frame.  If the view
   9685      * is not attached to a window, this is simply the raw display size.
   9686      */
   9687     public void getWindowVisibleDisplayFrame(Rect outRect) {
   9688         if (mAttachInfo != null) {
   9689             try {
   9690                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
   9691             } catch (RemoteException e) {
   9692                 return;
   9693             }
   9694             // XXX This is really broken, and probably all needs to be done
   9695             // in the window manager, and we need to know more about whether
   9696             // we want the area behind or in front of the IME.
   9697             final Rect insets = mAttachInfo.mVisibleInsets;
   9698             outRect.left += insets.left;
   9699             outRect.top += insets.top;
   9700             outRect.right -= insets.right;
   9701             outRect.bottom -= insets.bottom;
   9702             return;
   9703         }
   9704         // The view is not attached to a display so we don't have a context.
   9705         // Make a best guess about the display size.
   9706         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
   9707         d.getRectSize(outRect);
   9708     }
   9709 
   9710     /**
   9711      * Dispatch a notification about a resource configuration change down
   9712      * the view hierarchy.
   9713      * ViewGroups should override to route to their children.
   9714      *
   9715      * @param newConfig The new resource configuration.
   9716      *
   9717      * @see #onConfigurationChanged(android.content.res.Configuration)
   9718      */
   9719     public void dispatchConfigurationChanged(Configuration newConfig) {
   9720         onConfigurationChanged(newConfig);
   9721     }
   9722 
   9723     /**
   9724      * Called when the current configuration of the resources being used
   9725      * by the application have changed.  You can use this to decide when
   9726      * to reload resources that can changed based on orientation and other
   9727      * configuration characteristics.  You only need to use this if you are
   9728      * not relying on the normal {@link android.app.Activity} mechanism of
   9729      * recreating the activity instance upon a configuration change.
   9730      *
   9731      * @param newConfig The new resource configuration.
   9732      */
   9733     protected void onConfigurationChanged(Configuration newConfig) {
   9734     }
   9735 
   9736     /**
   9737      * Private function to aggregate all per-view attributes in to the view
   9738      * root.
   9739      */
   9740     void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
   9741         performCollectViewAttributes(attachInfo, visibility);
   9742     }
   9743 
   9744     void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
   9745         if ((visibility & VISIBILITY_MASK) == VISIBLE) {
   9746             if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
   9747                 attachInfo.mKeepScreenOn = true;
   9748             }
   9749             attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
   9750             ListenerInfo li = mListenerInfo;
   9751             if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
   9752                 attachInfo.mHasSystemUiListeners = true;
   9753             }
   9754         }
   9755     }
   9756 
   9757     void needGlobalAttributesUpdate(boolean force) {
   9758         final AttachInfo ai = mAttachInfo;
   9759         if (ai != null && !ai.mRecomputeGlobalAttributes) {
   9760             if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
   9761                     || ai.mHasSystemUiListeners) {
   9762                 ai.mRecomputeGlobalAttributes = true;
   9763             }
   9764         }
   9765     }
   9766 
   9767     /**
   9768      * Returns whether the device is currently in touch mode.  Touch mode is entered
   9769      * once the user begins interacting with the device by touch, and affects various
   9770      * things like whether focus is always visible to the user.
   9771      *
   9772      * @return Whether the device is in touch mode.
   9773      */
   9774     @ViewDebug.ExportedProperty
   9775     public boolean isInTouchMode() {
   9776         if (mAttachInfo != null) {
   9777             return mAttachInfo.mInTouchMode;
   9778         } else {
   9779             return ViewRootImpl.isInTouchMode();
   9780         }
   9781     }
   9782 
   9783     /**
   9784      * Returns the context the view is running in, through which it can
   9785      * access the current theme, resources, etc.
   9786      *
   9787      * @return The view's Context.
   9788      */
   9789     @ViewDebug.CapturedViewProperty
   9790     public final Context getContext() {
   9791         return mContext;
   9792     }
   9793 
   9794     /**
   9795      * Handle a key event before it is processed by any input method
   9796      * associated with the view hierarchy.  This can be used to intercept
   9797      * key events in special situations before the IME consumes them; a
   9798      * typical example would be handling the BACK key to update the application's
   9799      * UI instead of allowing the IME to see it and close itself.
   9800      *
   9801      * @param keyCode The value in event.getKeyCode().
   9802      * @param event Description of the key event.
   9803      * @return If you handled the event, return true. If you want to allow the
   9804      *         event to be handled by the next receiver, return false.
   9805      */
   9806     public boolean onKeyPreIme(int keyCode, KeyEvent event) {
   9807         return false;
   9808     }
   9809 
   9810     /**
   9811      * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
   9812      * KeyEvent.Callback.onKeyDown()}: perform press of the view
   9813      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
   9814      * is released, if the view is enabled and clickable.
   9815      *
   9816      * <p>Key presses in software keyboards will generally NOT trigger this listener,
   9817      * although some may elect to do so in some situations. Do not rely on this to
   9818      * catch software key presses.
   9819      *
   9820      * @param keyCode A key code that represents the button pressed, from
   9821      *                {@link android.view.KeyEvent}.
   9822      * @param event   The KeyEvent object that defines the button action.
   9823      */
   9824     public boolean onKeyDown(int keyCode, KeyEvent event) {
   9825         boolean result = false;
   9826 
   9827         if (KeyEvent.isConfirmKey(keyCode)) {
   9828             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
   9829                 return true;
   9830             }
   9831             // Long clickable items don't necessarily have to be clickable
   9832             if (((mViewFlags & CLICKABLE) == CLICKABLE ||
   9833                     (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
   9834                     (event.getRepeatCount() == 0)) {
   9835                 setPressed(true);
   9836                 checkForLongClick(0);
   9837                 return true;
   9838             }
   9839         }
   9840         return result;
   9841     }
   9842 
   9843     /**
   9844      * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
   9845      * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
   9846      * the event).
   9847      * <p>Key presses in software keyboards will generally NOT trigger this listener,
   9848      * although some may elect to do so in some situations. Do not rely on this to
   9849      * catch software key presses.
   9850      */
   9851     public boolean onKeyLongPress(int keyCode, KeyEvent event) {
   9852         return false;
   9853     }
   9854 
   9855     /**
   9856      * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
   9857      * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
   9858      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
   9859      * {@link KeyEvent#KEYCODE_ENTER} is released.
   9860      * <p>Key presses in software keyboards will generally NOT trigger this listener,
   9861      * although some may elect to do so in some situations. Do not rely on this to
   9862      * catch software key presses.
   9863      *
   9864      * @param keyCode A key code that represents the button pressed, from
   9865      *                {@link android.view.KeyEvent}.
   9866      * @param event   The KeyEvent object that defines the button action.
   9867      */
   9868     public boolean onKeyUp(int keyCode, KeyEvent event) {
   9869         if (KeyEvent.isConfirmKey(keyCode)) {
   9870             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
   9871                 return true;
   9872             }
   9873             if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
   9874                 setPressed(false);
   9875 
   9876                 if (!mHasPerformedLongPress) {
   9877                     // This is a tap, so remove the longpress check
   9878                     removeLongPressCallback();
   9879                     return performClick();
   9880                 }
   9881             }
   9882         }
   9883         return false;
   9884     }
   9885 
   9886     /**
   9887      * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
   9888      * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
   9889      * the event).
   9890      * <p>Key presses in software keyboards will generally NOT trigger this listener,
   9891      * although some may elect to do so in some situations. Do not rely on this to
   9892      * catch software key presses.
   9893      *
   9894      * @param keyCode     A key code that represents the button pressed, from
   9895      *                    {@link android.view.KeyEvent}.
   9896      * @param repeatCount The number of times the action was made.
   9897      * @param event       The KeyEvent object that defines the button action.
   9898      */
   9899     public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
   9900         return false;
   9901     }
   9902 
   9903     /**
   9904      * Called on the focused view when a key shortcut event is not handled.
   9905      * Override this method to implement local key shortcuts for the View.
   9906      * Key shortcuts can also be implemented by setting the
   9907      * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
   9908      *
   9909      * @param keyCode The value in event.getKeyCode().
   9910      * @param event Description of the key event.
   9911      * @return If you handled the event, return true. If you want to allow the
   9912      *         event to be handled by the next receiver, return false.
   9913      */
   9914     public boolean onKeyShortcut(int keyCode, KeyEvent event) {
   9915         return false;
   9916     }
   9917 
   9918     /**
   9919      * Check whether the called view is a text editor, in which case it
   9920      * would make sense to automatically display a soft input window for
   9921      * it.  Subclasses should override this if they implement
   9922      * {@link #onCreateInputConnection(EditorInfo)} to return true if
   9923      * a call on that method would return a non-null InputConnection, and
   9924      * they are really a first-class editor that the user would normally
   9925      * start typing on when the go into a window containing your view.
   9926      *
   9927      * <p>The default implementation always returns false.  This does
   9928      * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
   9929      * will not be called or the user can not otherwise perform edits on your
   9930      * view; it is just a hint to the system that this is not the primary
   9931      * purpose of this view.
   9932      *
   9933      * @return Returns true if this view is a text editor, else false.
   9934      */
   9935     public boolean onCheckIsTextEditor() {
   9936         return false;
   9937     }
   9938 
   9939     /**
   9940      * Create a new InputConnection for an InputMethod to interact
   9941      * with the view.  The default implementation returns null, since it doesn't
   9942      * support input methods.  You can override this to implement such support.
   9943      * This is only needed for views that take focus and text input.
   9944      *
   9945      * <p>When implementing this, you probably also want to implement
   9946      * {@link #onCheckIsTextEditor()} to indicate you will return a
   9947      * non-null InputConnection.</p>
   9948      *
   9949      * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
   9950      * object correctly and in its entirety, so that the connected IME can rely
   9951      * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
   9952      * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
   9953      * must be filled in with the correct cursor position for IMEs to work correctly
   9954      * with your application.</p>
   9955      *
   9956      * @param outAttrs Fill in with attribute information about the connection.
   9957      */
   9958     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
   9959         return null;
   9960     }
   9961 
   9962     /**
   9963      * Called by the {@link android.view.inputmethod.InputMethodManager}
   9964      * when a view who is not the current
   9965      * input connection target is trying to make a call on the manager.  The
   9966      * default implementation returns false; you can override this to return
   9967      * true for certain views if you are performing InputConnection proxying
   9968      * to them.
   9969      * @param view The View that is making the InputMethodManager call.
   9970      * @return Return true to allow the call, false to reject.
   9971      */
   9972     public boolean checkInputConnectionProxy(View view) {
   9973         return false;
   9974     }
   9975 
   9976     /**
   9977      * Show the context menu for this view. It is not safe to hold on to the
   9978      * menu after returning from this method.
   9979      *
   9980      * You should normally not overload this method. Overload
   9981      * {@link #onCreateContextMenu(ContextMenu)} or define an
   9982      * {@link OnCreateContextMenuListener} to add items to the context menu.
   9983      *
   9984      * @param menu The context menu to populate
   9985      */
   9986     public void createContextMenu(ContextMenu menu) {
   9987         ContextMenuInfo menuInfo = getContextMenuInfo();
   9988 
   9989         // Sets the current menu info so all items added to menu will have
   9990         // my extra info set.
   9991         ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
   9992 
   9993         onCreateContextMenu(menu);
   9994         ListenerInfo li = mListenerInfo;
   9995         if (li != null && li.mOnCreateContextMenuListener != null) {
   9996             li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
   9997         }
   9998 
   9999         // Clear the extra information so subsequent items that aren't mine don't
   10000         // have my extra info.
   10001         ((MenuBuilder)menu).setCurrentMenuInfo(null);
   10002 
   10003         if (mParent != null) {
   10004             mParent.createContextMenu(menu);
   10005         }
   10006     }
   10007 
   10008     /**
   10009      * Views should implement this if they have extra information to associate
   10010      * with the context menu. The return result is supplied as a parameter to
   10011      * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
   10012      * callback.
   10013      *
   10014      * @return Extra information about the item for which the context menu
   10015      *         should be shown. This information will vary across different
   10016      *         subclasses of View.
   10017      */
   10018     protected ContextMenuInfo getContextMenuInfo() {
   10019         return null;
   10020     }
   10021 
   10022     /**
   10023      * Views should implement this if the view itself is going to add items to
   10024      * the context menu.
   10025      *
   10026      * @param menu the context menu to populate
   10027      */
   10028     protected void onCreateContextMenu(ContextMenu menu) {
   10029     }
   10030 
   10031     /**
   10032      * Implement this method to handle trackball motion events.  The
   10033      * <em>relative</em> movement of the trackball since the last event
   10034      * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
   10035      * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
   10036      * that a movement of 1 corresponds to the user pressing one DPAD key (so
   10037      * they will often be fractional values, representing the more fine-grained
   10038      * movement information available from a trackball).
   10039      *
   10040      * @param event The motion event.
   10041      * @return True if the event was handled, false otherwise.
   10042      */
   10043     public boolean onTrackballEvent(MotionEvent event) {
   10044         return false;
   10045     }
   10046 
   10047     /**
   10048      * Implement this method to handle generic motion events.
   10049      * <p>
   10050      * Generic motion events describe joystick movements, mouse hovers, track pad
   10051      * touches, scroll wheel movements and other input events.  The
   10052      * {@link MotionEvent#getSource() source} of the motion event specifies
   10053      * the class of input that was received.  Implementations of this method
   10054      * must examine the bits in the source before processing the event.
   10055      * The following code example shows how this is done.
   10056      * </p><p>
   10057      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
   10058      * are delivered to the view under the pointer.  All other generic motion events are
   10059      * delivered to the focused view.
   10060      * </p>
   10061      * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
   10062      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
   10063      *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
   10064      *             // process the joystick movement...
   10065      *             return true;
   10066      *         }
   10067      *     }
   10068      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
   10069      *         switch (event.getAction()) {
   10070      *             case MotionEvent.ACTION_HOVER_MOVE:
   10071      *                 // process the mouse hover movement...
   10072      *                 return true;
   10073      *             case MotionEvent.ACTION_SCROLL:
   10074      *                 // process the scroll wheel movement...
   10075      *                 return true;
   10076      *         }
   10077      *     }
   10078      *     return super.onGenericMotionEvent(event);
   10079      * }</pre>
   10080      *
   10081      * @param event The generic motion event being processed.
   10082      * @return True if the event was handled, false otherwise.
   10083      */
   10084     public boolean onGenericMotionEvent(MotionEvent event) {
   10085         return false;
   10086     }
   10087 
   10088     /**
   10089      * Implement this method to handle hover events.
   10090      * <p>
   10091      * This method is called whenever a pointer is hovering into, over, or out of the
   10092      * bounds of a view and the view is not currently being touched.
   10093      * Hover events are represented as pointer events with action
   10094      * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
   10095      * or {@link MotionEvent#ACTION_HOVER_EXIT}.
   10096      * </p>
   10097      * <ul>
   10098      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
   10099      * when the pointer enters the bounds of the view.</li>
   10100      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
   10101      * when the pointer has already entered the bounds of the view and has moved.</li>
   10102      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
   10103      * when the pointer has exited the bounds of the view or when the pointer is
   10104      * about to go down due to a button click, tap, or similar user action that
   10105      * causes the view to be touched.</li>
   10106      * </ul>
   10107      * <p>
   10108      * The view should implement this method to return true to indicate that it is
   10109      * handling the hover event, such as by changing its drawable state.
   10110      * </p><p>
   10111      * The default implementation calls {@link #setHovered} to update the hovered state
   10112      * of the view when a hover enter or hover exit event is received, if the view
   10113      * is enabled and is clickable.  The default implementation also sends hover
   10114      * accessibility events.
   10115      * </p>
   10116      *
   10117      * @param event The motion event that describes the hover.
   10118      * @return True if the view handled the hover event.
   10119      *
   10120      * @see #isHovered
   10121      * @see #setHovered
   10122      * @see #onHoverChanged
   10123      */
   10124     public boolean onHoverEvent(MotionEvent event) {
   10125         // The root view may receive hover (or touch) events that are outside the bounds of
   10126         // the window.  This code ensures that we only send accessibility events for
   10127         // hovers that are actually within the bounds of the root view.
   10128         final int action = event.getActionMasked();
   10129         if (!mSendingHoverAccessibilityEvents) {
   10130             if ((action == MotionEvent.ACTION_HOVER_ENTER
   10131                     || action == MotionEvent.ACTION_HOVER_MOVE)
   10132                     && !hasHoveredChild()
   10133                     && pointInView(event.getX(), event.getY())) {
   10134                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
   10135                 mSendingHoverAccessibilityEvents = true;
   10136             }
   10137         } else {
   10138             if (action == MotionEvent.ACTION_HOVER_EXIT
   10139                     || (action == MotionEvent.ACTION_MOVE
   10140                             && !pointInView(event.getX(), event.getY()))) {
   10141                 mSendingHoverAccessibilityEvents = false;
   10142                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
   10143             }
   10144         }
   10145 
   10146         if (isHoverable()) {
   10147             switch (action) {
   10148                 case MotionEvent.ACTION_HOVER_ENTER:
   10149                     setHovered(true);
   10150                     break;
   10151                 case MotionEvent.ACTION_HOVER_EXIT:
   10152                     setHovered(false);
   10153                     break;
   10154             }
   10155 
   10156             // Dispatch the event to onGenericMotionEvent before returning true.
   10157             // This is to provide compatibility with existing applications that
   10158             // handled HOVER_MOVE events in onGenericMotionEvent and that would
   10159             // break because of the new default handling for hoverable views
   10160             // in onHoverEvent.
   10161             // Note that onGenericMotionEvent will be called by default when
   10162             // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
   10163             dispatchGenericMotionEventInternal(event);
   10164             // The event was already handled by calling setHovered(), so always
   10165             // return true.
   10166             return true;
   10167         }
   10168 
   10169         return false;
   10170     }
   10171 
   10172     /**
   10173      * Returns true if the view should handle {@link #onHoverEvent}
   10174      * by calling {@link #setHovered} to change its hovered state.
   10175      *
   10176      * @return True if the view is hoverable.
   10177      */
   10178     private boolean isHoverable() {
   10179         final int viewFlags = mViewFlags;
   10180         if ((viewFlags & ENABLED_MASK) == DISABLED) {
   10181             return false;
   10182         }
   10183 
   10184         return (viewFlags & CLICKABLE) == CLICKABLE
   10185                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
   10186                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
   10187     }
   10188 
   10189     /**
   10190      * Returns true if the view is currently hovered.
   10191      *
   10192      * @return True if the view is currently hovered.
   10193      *
   10194      * @see #setHovered
   10195      * @see #onHoverChanged
   10196      */
   10197     @ViewDebug.ExportedProperty
   10198     public boolean isHovered() {
   10199         return (mPrivateFlags & PFLAG_HOVERED) != 0;
   10200     }
   10201 
   10202     /**
   10203      * Sets whether the view is currently hovered.
   10204      * <p>
   10205      * Calling this method also changes the drawable state of the view.  This
   10206      * enables the view to react to hover by using different drawable resources
   10207      * to change its appearance.
   10208      * </p><p>
   10209      * The {@link #onHoverChanged} method is called when the hovered state changes.
   10210      * </p>
   10211      *
   10212      * @param hovered True if the view is hovered.
   10213      *
   10214      * @see #isHovered
   10215      * @see #onHoverChanged
   10216      */
   10217     public void setHovered(boolean hovered) {
   10218         if (hovered) {
   10219             if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
   10220                 mPrivateFlags |= PFLAG_HOVERED;
   10221                 refreshDrawableState();
   10222                 onHoverChanged(true);
   10223             }
   10224         } else {
   10225             if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
   10226                 mPrivateFlags &= ~PFLAG_HOVERED;
   10227                 refreshDrawableState();
   10228                 onHoverChanged(false);
   10229             }
   10230         }
   10231     }
   10232 
   10233     /**
   10234      * Implement this method to handle hover state changes.
   10235      * <p>
   10236      * This method is called whenever the hover state changes as a result of a
   10237      * call to {@link #setHovered}.
   10238      * </p>
   10239      *
   10240      * @param hovered The current hover state, as returned by {@link #isHovered}.
   10241      *
   10242      * @see #isHovered
   10243      * @see #setHovered
   10244      */
   10245     public void onHoverChanged(boolean hovered) {
   10246     }
   10247 
   10248     /**
   10249      * Implement this method to handle touch screen motion events.
   10250      * <p>
   10251      * If this method is used to detect click actions, it is recommended that
   10252      * the actions be performed by implementing and calling
   10253      * {@link #performClick()}. This will ensure consistent system behavior,
   10254      * including:
   10255      * <ul>
   10256      * <li>obeying click sound preferences
   10257      * <li>dispatching OnClickListener calls
   10258      * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
   10259      * accessibility features are enabled
   10260      * </ul>
   10261      *
   10262      * @param event The motion event.
   10263      * @return True if the event was handled, false otherwise.
   10264      */
   10265     public boolean onTouchEvent(MotionEvent event) {
   10266         final float x = event.getX();
   10267         final float y = event.getY();
   10268         final int viewFlags = mViewFlags;
   10269         final int action = event.getAction();
   10270 
   10271         if ((viewFlags & ENABLED_MASK) == DISABLED) {
   10272             if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
   10273                 setPressed(false);
   10274             }
   10275             // A disabled view that is clickable still consumes the touch
   10276             // events, it just doesn't respond to them.
   10277             return (((viewFlags & CLICKABLE) == CLICKABLE
   10278                     || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
   10279                     || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE);
   10280         }
   10281 
   10282         if (mTouchDelegate != null) {
   10283             if (mTouchDelegate.onTouchEvent(event)) {
   10284                 return true;
   10285             }
   10286         }
   10287 
   10288         if (((viewFlags & CLICKABLE) == CLICKABLE ||
   10289                 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||
   10290                 (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) {
   10291             switch (action) {
   10292                 case MotionEvent.ACTION_UP:
   10293                     boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
   10294                     if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
   10295                         // take focus if we don't have it already and we should in
   10296                         // touch mode.
   10297                         boolean focusTaken = false;
   10298                         if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
   10299                             focusTaken = requestFocus();
   10300                         }
   10301 
   10302                         if (prepressed) {
   10303                             // The button is being released before we actually
   10304                             // showed it as pressed.  Make it show the pressed
   10305                             // state now (before scheduling the click) to ensure
   10306                             // the user sees it.
   10307                             setPressed(true, x, y);
   10308                        }
   10309 
   10310                         if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
   10311                             // This is a tap, so remove the longpress check
   10312                             removeLongPressCallback();
   10313 
   10314                             // Only perform take click actions if we were in the pressed state
   10315                             if (!focusTaken) {
   10316                                 // Use a Runnable and post this rather than calling
   10317                                 // performClick directly. This lets other visual state
   10318                                 // of the view update before click actions start.
   10319                                 if (mPerformClick == null) {
   10320                                     mPerformClick = new PerformClick();
   10321                                 }
   10322                                 if (!post(mPerformClick)) {
   10323                                     performClick();
   10324                                 }
   10325                             }
   10326                         }
   10327 
   10328                         if (mUnsetPressedState == null) {
   10329                             mUnsetPressedState = new UnsetPressedState();
   10330                         }
   10331 
   10332                         if (prepressed) {
   10333                             postDelayed(mUnsetPressedState,
   10334                                     ViewConfiguration.getPressedStateDuration());
   10335                         } else if (!post(mUnsetPressedState)) {
   10336                             // If the post failed, unpress right now
   10337                             mUnsetPressedState.run();
   10338                         }
   10339 
   10340                         removeTapCallback();
   10341                     }
   10342                     mIgnoreNextUpEvent = false;
   10343                     break;
   10344 
   10345                 case MotionEvent.ACTION_DOWN:
   10346                     mHasPerformedLongPress = false;
   10347 
   10348                     if (performButtonActionOnTouchDown(event)) {
   10349                         break;
   10350                     }
   10351 
   10352                     // Walk up the hierarchy to determine if we're inside a scrolling container.
   10353                     boolean isInScrollingContainer = isInScrollingContainer();
   10354 
   10355                     // For views inside a scrolling container, delay the pressed feedback for
   10356                     // a short period in case this is a scroll.
   10357                     if (isInScrollingContainer) {
   10358                         mPrivateFlags |= PFLAG_PREPRESSED;
   10359                         if (mPendingCheckForTap == null) {
   10360                             mPendingCheckForTap = new CheckForTap();
   10361                         }
   10362                         mPendingCheckForTap.x = event.getX();
   10363                         mPendingCheckForTap.y = event.getY();
   10364                         postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
   10365                     } else {
   10366                         // Not inside a scrolling container, so show the feedback right away
   10367                         setPressed(true, x, y);
   10368                         checkForLongClick(0);
   10369                     }
   10370                     break;
   10371 
   10372                 case MotionEvent.ACTION_CANCEL:
   10373                     setPressed(false);
   10374                     removeTapCallback();
   10375                     removeLongPressCallback();
   10376                     mInContextButtonPress = false;
   10377                     mHasPerformedLongPress = false;
   10378                     mIgnoreNextUpEvent = false;
   10379                     break;
   10380 
   10381                 case MotionEvent.ACTION_MOVE:
   10382                     drawableHotspotChanged(x, y);
   10383 
   10384                     // Be lenient about moving outside of buttons
   10385                     if (!pointInView(x, y, mTouchSlop)) {
   10386                         // Outside button
   10387                         removeTapCallback();
   10388                         if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
   10389                             // Remove any future long press/tap checks
   10390                             removeLongPressCallback();
   10391 
   10392                             setPressed(false);
   10393                         }
   10394                     }
   10395                     break;
   10396             }
   10397 
   10398             return true;
   10399         }
   10400 
   10401         return false;
   10402     }
   10403 
   10404     /**
   10405      * @hide
   10406      */
   10407     public boolean isInScrollingContainer() {
   10408         ViewParent p = getParent();
   10409         while (p != null && p instanceof ViewGroup) {
   10410             if (((ViewGroup) p).shouldDelayChildPressedState()) {
   10411                 return true;
   10412             }
   10413             p = p.getParent();
   10414         }
   10415         return false;
   10416     }
   10417 
   10418     /**
   10419      * Remove the longpress detection timer.
   10420      */
   10421     private void removeLongPressCallback() {
   10422         if (mPendingCheckForLongPress != null) {
   10423           removeCallbacks(mPendingCheckForLongPress);
   10424         }
   10425     }
   10426 
   10427     /**
   10428      * Remove the pending click action
   10429      */
   10430     private void removePerformClickCallback() {
   10431         if (mPerformClick != null) {
   10432             removeCallbacks(mPerformClick);
   10433         }
   10434     }
   10435 
   10436     /**
   10437      * Remove the prepress detection timer.
   10438      */
   10439     private void removeUnsetPressCallback() {
   10440         if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
   10441             setPressed(false);
   10442             removeCallbacks(mUnsetPressedState);
   10443         }
   10444     }
   10445 
   10446     /**
   10447      * Remove the tap detection timer.
   10448      */
   10449     private void removeTapCallback() {
   10450         if (mPendingCheckForTap != null) {
   10451             mPrivateFlags &= ~PFLAG_PREPRESSED;
   10452             removeCallbacks(mPendingCheckForTap);
   10453         }
   10454     }
   10455 
   10456     /**
   10457      * Cancels a pending long press.  Your subclass can use this if you
   10458      * want the context menu to come up if the user presses and holds
   10459      * at the same place, but you don't want it to come up if they press
   10460      * and then move around enough to cause scrolling.
   10461      */
   10462     public void cancelLongPress() {
   10463         removeLongPressCallback();
   10464 
   10465         /*
   10466          * The prepressed state handled by the tap callback is a display
   10467          * construct, but the tap callback will post a long press callback
   10468          * less its own timeout. Remove it here.
   10469          */
   10470         removeTapCallback();
   10471     }
   10472 
   10473     /**
   10474      * Remove the pending callback for sending a
   10475      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
   10476      */
   10477     private void removeSendViewScrolledAccessibilityEventCallback() {
   10478         if (mSendViewScrolledAccessibilityEvent != null) {
   10479             removeCallbacks(mSendViewScrolledAccessibilityEvent);
   10480             mSendViewScrolledAccessibilityEvent.mIsPending = false;
   10481         }
   10482     }
   10483 
   10484     /**
   10485      * Sets the TouchDelegate for this View.
   10486      */
   10487     public void setTouchDelegate(TouchDelegate delegate) {
   10488         mTouchDelegate = delegate;
   10489     }
   10490 
   10491     /**
   10492      * Gets the TouchDelegate for this View.
   10493      */
   10494     public TouchDelegate getTouchDelegate() {
   10495         return mTouchDelegate;
   10496     }
   10497 
   10498     /**
   10499      * Request unbuffered dispatch of the given stream of MotionEvents to this View.
   10500      *
   10501      * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
   10502      * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
   10503      * available. This method should only be called for touch events.
   10504      *
   10505      * <p class="note">This api is not intended for most applications. Buffered dispatch
   10506      * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
   10507      * streams will not improve your input latency. Side effects include: increased latency,
   10508      * jittery scrolls and inability to take advantage of system resampling. Talk to your input
   10509      * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
   10510      * you.</p>
   10511      */
   10512     public final void requestUnbufferedDispatch(MotionEvent event) {
   10513         final int action = event.getAction();
   10514         if (mAttachInfo == null
   10515                 || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
   10516                 || !event.isTouchEvent()) {
   10517             return;
   10518         }
   10519         mAttachInfo.mUnbufferedDispatchRequested = true;
   10520     }
   10521 
   10522     /**
   10523      * Set flags controlling behavior of this view.
   10524      *
   10525      * @param flags Constant indicating the value which should be set
   10526      * @param mask Constant indicating the bit range that should be changed
   10527      */
   10528     void setFlags(int flags, int mask) {
   10529         final boolean accessibilityEnabled =
   10530                 AccessibilityManager.getInstance(mContext).isEnabled();
   10531         final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
   10532 
   10533         int old = mViewFlags;
   10534         mViewFlags = (mViewFlags & ~mask) | (flags & mask);
   10535 
   10536         int changed = mViewFlags ^ old;
   10537         if (changed == 0) {
   10538             return;
   10539         }
   10540         int privateFlags = mPrivateFlags;
   10541 
   10542         /* Check if the FOCUSABLE bit has changed */
   10543         if (((changed & FOCUSABLE_MASK) != 0) &&
   10544                 ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
   10545             if (((old & FOCUSABLE_MASK) == FOCUSABLE)
   10546                     && ((privateFlags & PFLAG_FOCUSED) != 0)) {
   10547                 /* Give up focus if we are no longer focusable */
   10548                 clearFocus();
   10549             } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
   10550                     && ((privateFlags & PFLAG_FOCUSED) == 0)) {
   10551                 /*
   10552                  * Tell the view system that we are now available to take focus
   10553                  * if no one else already has it.
   10554                  */
   10555                 if (mParent != null) mParent.focusableViewAvailable(this);
   10556             }
   10557         }
   10558 
   10559         final int newVisibility = flags & VISIBILITY_MASK;
   10560         if (newVisibility == VISIBLE) {
   10561             if ((changed & VISIBILITY_MASK) != 0) {
   10562                 /*
   10563                  * If this view is becoming visible, invalidate it in case it changed while
   10564                  * it was not visible. Marking it drawn ensures that the invalidation will
   10565                  * go through.
   10566                  */
   10567                 mPrivateFlags |= PFLAG_DRAWN;
   10568                 invalidate(true);
   10569 
   10570                 needGlobalAttributesUpdate(true);
   10571 
   10572                 // a view becoming visible is worth notifying the parent
   10573                 // about in case nothing has focus.  even if this specific view
   10574                 // isn't focusable, it may contain something that is, so let
   10575                 // the root view try to give this focus if nothing else does.
   10576                 if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
   10577                     mParent.focusableViewAvailable(this);
   10578                 }
   10579             }
   10580         }
   10581 
   10582         /* Check if the GONE bit has changed */
   10583         if ((changed & GONE) != 0) {
   10584             needGlobalAttributesUpdate(false);
   10585             requestLayout();
   10586 
   10587             if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
   10588                 if (hasFocus()) clearFocus();
   10589                 clearAccessibilityFocus();
   10590                 destroyDrawingCache();
   10591                 if (mParent instanceof View) {
   10592                     // GONE views noop invalidation, so invalidate the parent
   10593                     ((View) mParent).invalidate(true);
   10594                 }
   10595                 // Mark the view drawn to ensure that it gets invalidated properly the next
   10596                 // time it is visible and gets invalidated
   10597                 mPrivateFlags |= PFLAG_DRAWN;
   10598             }
   10599             if (mAttachInfo != null) {
   10600                 mAttachInfo.mViewVisibilityChanged = true;
   10601             }
   10602         }
   10603 
   10604         /* Check if the VISIBLE bit has changed */
   10605         if ((changed & INVISIBLE) != 0) {
   10606             needGlobalAttributesUpdate(false);
   10607             /*
   10608              * If this view is becoming invisible, set the DRAWN flag so that
   10609              * the next invalidate() will not be skipped.
   10610              */
   10611             mPrivateFlags |= PFLAG_DRAWN;
   10612 
   10613             if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
   10614                 // root view becoming invisible shouldn't clear focus and accessibility focus
   10615                 if (getRootView() != this) {
   10616                     if (hasFocus()) clearFocus();
   10617                     clearAccessibilityFocus();
   10618                 }
   10619             }
   10620             if (mAttachInfo != null) {
   10621                 mAttachInfo.mViewVisibilityChanged = true;
   10622             }
   10623         }
   10624 
   10625         if ((changed & VISIBILITY_MASK) != 0) {
   10626             // If the view is invisible, cleanup its display list to free up resources
   10627             if (newVisibility != VISIBLE && mAttachInfo != null) {
   10628                 cleanupDraw();
   10629             }
   10630 
   10631             if (mParent instanceof ViewGroup) {
   10632                 ((ViewGroup) mParent).onChildVisibilityChanged(this,
   10633                         (changed & VISIBILITY_MASK), newVisibility);
   10634                 ((View) mParent).invalidate(true);
   10635             } else if (mParent != null) {
   10636                 mParent.invalidateChild(this, null);
   10637             }
   10638 
   10639             if (mAttachInfo != null) {
   10640                 dispatchVisibilityChanged(this, newVisibility);
   10641                 notifySubtreeAccessibilityStateChangedIfNeeded();
   10642             }
   10643         }
   10644 
   10645         if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
   10646             destroyDrawingCache();
   10647         }
   10648 
   10649         if ((changed & DRAWING_CACHE_ENABLED) != 0) {
   10650             destroyDrawingCache();
   10651             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
   10652             invalidateParentCaches();
   10653         }
   10654 
   10655         if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
   10656             destroyDrawingCache();
   10657             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
   10658         }
   10659 
   10660         if ((changed & DRAW_MASK) != 0) {
   10661             if ((mViewFlags & WILL_NOT_DRAW) != 0) {
   10662                 if (mBackground != null
   10663                         || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
   10664                     mPrivateFlags &= ~PFLAG_SKIP_DRAW;
   10665                 } else {
   10666                     mPrivateFlags |= PFLAG_SKIP_DRAW;
   10667                 }
   10668             } else {
   10669                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
   10670             }
   10671             requestLayout();
   10672             invalidate(true);
   10673         }
   10674 
   10675         if ((changed & KEEP_SCREEN_ON) != 0) {
   10676             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
   10677                 mParent.recomputeViewAttributes(this);
   10678             }
   10679         }
   10680 
   10681         if (accessibilityEnabled) {
   10682             if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
   10683                     || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
   10684                     || (changed & CONTEXT_CLICKABLE) != 0) {
   10685                 if (oldIncludeForAccessibility != includeForAccessibility()) {
   10686                     notifySubtreeAccessibilityStateChangedIfNeeded();
   10687                 } else {
   10688                     notifyViewAccessibilityStateChangedIfNeeded(
   10689                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   10690                 }
   10691             } else if ((changed & ENABLED_MASK) != 0) {
   10692                 notifyViewAccessibilityStateChangedIfNeeded(
   10693                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   10694             }
   10695         }
   10696     }
   10697 
   10698     /**
   10699      * Change the view's z order in the tree, so it's on top of other sibling
   10700      * views. This ordering change may affect layout, if the parent container
   10701      * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
   10702      * to {@link android.os.Build.VERSION_CODES#KITKAT} this
   10703      * method should be followed by calls to {@link #requestLayout()} and
   10704      * {@link View#invalidate()} on the view's parent to force the parent to redraw
   10705      * with the new child ordering.
   10706      *
   10707      * @see ViewGroup#bringChildToFront(View)
   10708      */
   10709     public void bringToFront() {
   10710         if (mParent != null) {
   10711             mParent.bringChildToFront(this);
   10712         }
   10713     }
   10714 
   10715     /**
   10716      * This is called in response to an internal scroll in this view (i.e., the
   10717      * view scrolled its own contents). This is typically as a result of
   10718      * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
   10719      * called.
   10720      *
   10721      * @param l Current horizontal scroll origin.
   10722      * @param t Current vertical scroll origin.
   10723      * @param oldl Previous horizontal scroll origin.
   10724      * @param oldt Previous vertical scroll origin.
   10725      */
   10726     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
   10727         notifySubtreeAccessibilityStateChangedIfNeeded();
   10728 
   10729         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
   10730             postSendViewScrolledAccessibilityEventCallback();
   10731         }
   10732 
   10733         mBackgroundSizeChanged = true;
   10734         if (mForegroundInfo != null) {
   10735             mForegroundInfo.mBoundsChanged = true;
   10736         }
   10737 
   10738         final AttachInfo ai = mAttachInfo;
   10739         if (ai != null) {
   10740             ai.mViewScrollChanged = true;
   10741         }
   10742 
   10743         if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
   10744             mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
   10745         }
   10746     }
   10747 
   10748     /**
   10749      * Interface definition for a callback to be invoked when the scroll
   10750      * X or Y positions of a view change.
   10751      * <p>
   10752      * <b>Note:</b> Some views handle scrolling independently from View and may
   10753      * have their own separate listeners for scroll-type events. For example,
   10754      * {@link android.widget.ListView ListView} allows clients to register an
   10755      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
   10756      * to listen for changes in list scroll position.
   10757      *
   10758      * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
   10759      */
   10760     public interface OnScrollChangeListener {
   10761         /**
   10762          * Called when the scroll position of a view changes.
   10763          *
   10764          * @param v The view whose scroll position has changed.
   10765          * @param scrollX Current horizontal scroll origin.
   10766          * @param scrollY Current vertical scroll origin.
   10767          * @param oldScrollX Previous horizontal scroll origin.
   10768          * @param oldScrollY Previous vertical scroll origin.
   10769          */
   10770         void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
   10771     }
   10772 
   10773     /**
   10774      * Interface definition for a callback to be invoked when the layout bounds of a view
   10775      * changes due to layout processing.
   10776      */
   10777     public interface OnLayoutChangeListener {
   10778         /**
   10779          * Called when the layout bounds of a view changes due to layout processing.
   10780          *
   10781          * @param v The view whose bounds have changed.
   10782          * @param left The new value of the view's left property.
   10783          * @param top The new value of the view's top property.
   10784          * @param right The new value of the view's right property.
   10785          * @param bottom The new value of the view's bottom property.
   10786          * @param oldLeft The previous value of the view's left property.
   10787          * @param oldTop The previous value of the view's top property.
   10788          * @param oldRight The previous value of the view's right property.
   10789          * @param oldBottom The previous value of the view's bottom property.
   10790          */
   10791         void onLayoutChange(View v, int left, int top, int right, int bottom,
   10792             int oldLeft, int oldTop, int oldRight, int oldBottom);
   10793     }
   10794 
   10795     /**
   10796      * This is called during layout when the size of this view has changed. If
   10797      * you were just added to the view hierarchy, you're called with the old
   10798      * values of 0.
   10799      *
   10800      * @param w Current width of this view.
   10801      * @param h Current height of this view.
   10802      * @param oldw Old width of this view.
   10803      * @param oldh Old height of this view.
   10804      */
   10805     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
   10806     }
   10807 
   10808     /**
   10809      * Called by draw to draw the child views. This may be overridden
   10810      * by derived classes to gain control just before its children are drawn
   10811      * (but after its own view has been drawn).
   10812      * @param canvas the canvas on which to draw the view
   10813      */
   10814     protected void dispatchDraw(Canvas canvas) {
   10815 
   10816     }
   10817 
   10818     /**
   10819      * Gets the parent of this view. Note that the parent is a
   10820      * ViewParent and not necessarily a View.
   10821      *
   10822      * @return Parent of this view.
   10823      */
   10824     public final ViewParent getParent() {
   10825         return mParent;
   10826     }
   10827 
   10828     /**
   10829      * Set the horizontal scrolled position of your view. This will cause a call to
   10830      * {@link #onScrollChanged(int, int, int, int)} and the view will be
   10831      * invalidated.
   10832      * @param value the x position to scroll to
   10833      */
   10834     public void setScrollX(int value) {
   10835         scrollTo(value, mScrollY);
   10836     }
   10837 
   10838     /**
   10839      * Set the vertical scrolled position of your view. This will cause a call to
   10840      * {@link #onScrollChanged(int, int, int, int)} and the view will be
   10841      * invalidated.
   10842      * @param value the y position to scroll to
   10843      */
   10844     public void setScrollY(int value) {
   10845         scrollTo(mScrollX, value);
   10846     }
   10847 
   10848     /**
   10849      * Return the scrolled left position of this view. This is the left edge of
   10850      * the displayed part of your view. You do not need to draw any pixels
   10851      * farther left, since those are outside of the frame of your view on
   10852      * screen.
   10853      *
   10854      * @return The left edge of the displayed part of your view, in pixels.
   10855      */
   10856     public final int getScrollX() {
   10857         return mScrollX;
   10858     }
   10859 
   10860     /**
   10861      * Return the scrolled top position of this view. This is the top edge of
   10862      * the displayed part of your view. You do not need to draw any pixels above
   10863      * it, since those are outside of the frame of your view on screen.
   10864      *
   10865      * @return The top edge of the displayed part of your view, in pixels.
   10866      */
   10867     public final int getScrollY() {
   10868         return mScrollY;
   10869     }
   10870 
   10871     /**
   10872      * Return the width of the your view.
   10873      *
   10874      * @return The width of your view, in pixels.
   10875      */
   10876     @ViewDebug.ExportedProperty(category = "layout")
   10877     public final int getWidth() {
   10878         return mRight - mLeft;
   10879     }
   10880 
   10881     /**
   10882      * Return the height of your view.
   10883      *
   10884      * @return The height of your view, in pixels.
   10885      */
   10886     @ViewDebug.ExportedProperty(category = "layout")
   10887     public final int getHeight() {
   10888         return mBottom - mTop;
   10889     }
   10890 
   10891     /**
   10892      * Return the visible drawing bounds of your view. Fills in the output
   10893      * rectangle with the values from getScrollX(), getScrollY(),
   10894      * getWidth(), and getHeight(). These bounds do not account for any
   10895      * transformation properties currently set on the view, such as
   10896      * {@link #setScaleX(float)} or {@link #setRotation(float)}.
   10897      *
   10898      * @param outRect The (scrolled) drawing bounds of the view.
   10899      */
   10900     public void getDrawingRect(Rect outRect) {
   10901         outRect.left = mScrollX;
   10902         outRect.top = mScrollY;
   10903         outRect.right = mScrollX + (mRight - mLeft);
   10904         outRect.bottom = mScrollY + (mBottom - mTop);
   10905     }
   10906 
   10907     /**
   10908      * Like {@link #getMeasuredWidthAndState()}, but only returns the
   10909      * raw width component (that is the result is masked by
   10910      * {@link #MEASURED_SIZE_MASK}).
   10911      *
   10912      * @return The raw measured width of this view.
   10913      */
   10914     public final int getMeasuredWidth() {
   10915         return mMeasuredWidth & MEASURED_SIZE_MASK;
   10916     }
   10917 
   10918     /**
   10919      * Return the full width measurement information for this view as computed
   10920      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
   10921      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
   10922      * This should be used during measurement and layout calculations only. Use
   10923      * {@link #getWidth()} to see how wide a view is after layout.
   10924      *
   10925      * @return The measured width of this view as a bit mask.
   10926      */
   10927     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
   10928             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
   10929                     name = "MEASURED_STATE_TOO_SMALL"),
   10930     })
   10931     public final int getMeasuredWidthAndState() {
   10932         return mMeasuredWidth;
   10933     }
   10934 
   10935     /**
   10936      * Like {@link #getMeasuredHeightAndState()}, but only returns the
   10937      * raw width component (that is the result is masked by
   10938      * {@link #MEASURED_SIZE_MASK}).
   10939      *
   10940      * @return The raw measured height of this view.
   10941      */
   10942     public final int getMeasuredHeight() {
   10943         return mMeasuredHeight & MEASURED_SIZE_MASK;
   10944     }
   10945 
   10946     /**
   10947      * Return the full height measurement information for this view as computed
   10948      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
   10949      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
   10950      * This should be used during measurement and layout calculations only. Use
   10951      * {@link #getHeight()} to see how wide a view is after layout.
   10952      *
   10953      * @return The measured width of this view as a bit mask.
   10954      */
   10955     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
   10956             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
   10957                     name = "MEASURED_STATE_TOO_SMALL"),
   10958     })
   10959     public final int getMeasuredHeightAndState() {
   10960         return mMeasuredHeight;
   10961     }
   10962 
   10963     /**
   10964      * Return only the state bits of {@link #getMeasuredWidthAndState()}
   10965      * and {@link #getMeasuredHeightAndState()}, combined into one integer.
   10966      * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
   10967      * and the height component is at the shifted bits
   10968      * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
   10969      */
   10970     public final int getMeasuredState() {
   10971         return (mMeasuredWidth&MEASURED_STATE_MASK)
   10972                 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
   10973                         & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
   10974     }
   10975 
   10976     /**
   10977      * The transform matrix of this view, which is calculated based on the current
   10978      * rotation, scale, and pivot properties.
   10979      *
   10980      * @see #getRotation()
   10981      * @see #getScaleX()
   10982      * @see #getScaleY()
   10983      * @see #getPivotX()
   10984      * @see #getPivotY()
   10985      * @return The current transform matrix for the view
   10986      */
   10987     public Matrix getMatrix() {
   10988         ensureTransformationInfo();
   10989         final Matrix matrix = mTransformationInfo.mMatrix;
   10990         mRenderNode.getMatrix(matrix);
   10991         return matrix;
   10992     }
   10993 
   10994     /**
   10995      * Returns true if the transform matrix is the identity matrix.
   10996      * Recomputes the matrix if necessary.
   10997      *
   10998      * @return True if the transform matrix is the identity matrix, false otherwise.
   10999      */
   11000     final boolean hasIdentityMatrix() {
   11001         return mRenderNode.hasIdentityMatrix();
   11002     }
   11003 
   11004     void ensureTransformationInfo() {
   11005         if (mTransformationInfo == null) {
   11006             mTransformationInfo = new TransformationInfo();
   11007         }
   11008     }
   11009 
   11010    /**
   11011      * Utility method to retrieve the inverse of the current mMatrix property.
   11012      * We cache the matrix to avoid recalculating it when transform properties
   11013      * have not changed.
   11014      *
   11015      * @return The inverse of the current matrix of this view.
   11016      * @hide
   11017      */
   11018     public final Matrix getInverseMatrix() {
   11019         ensureTransformationInfo();
   11020         if (mTransformationInfo.mInverseMatrix == null) {
   11021             mTransformationInfo.mInverseMatrix = new Matrix();
   11022         }
   11023         final Matrix matrix = mTransformationInfo.mInverseMatrix;
   11024         mRenderNode.getInverseMatrix(matrix);
   11025         return matrix;
   11026     }
   11027 
   11028     /**
   11029      * Gets the distance along the Z axis from the camera to this view.
   11030      *
   11031      * @see #setCameraDistance(float)
   11032      *
   11033      * @return The distance along the Z axis.
   11034      */
   11035     public float getCameraDistance() {
   11036         final float dpi = mResources.getDisplayMetrics().densityDpi;
   11037         return -(mRenderNode.getCameraDistance() * dpi);
   11038     }
   11039 
   11040     /**
   11041      * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
   11042      * views are drawn) from the camera to this view. The camera's distance
   11043      * affects 3D transformations, for instance rotations around the X and Y
   11044      * axis. If the rotationX or rotationY properties are changed and this view is
   11045      * large (more than half the size of the screen), it is recommended to always
   11046      * use a camera distance that's greater than the height (X axis rotation) or
   11047      * the width (Y axis rotation) of this view.</p>
   11048      *
   11049      * <p>The distance of the camera from the view plane can have an affect on the
   11050      * perspective distortion of the view when it is rotated around the x or y axis.
   11051      * For example, a large distance will result in a large viewing angle, and there
   11052      * will not be much perspective distortion of the view as it rotates. A short
   11053      * distance may cause much more perspective distortion upon rotation, and can
   11054      * also result in some drawing artifacts if the rotated view ends up partially
   11055      * behind the camera (which is why the recommendation is to use a distance at
   11056      * least as far as the size of the view, if the view is to be rotated.)</p>
   11057      *
   11058      * <p>The distance is expressed in "depth pixels." The default distance depends
   11059      * on the screen density. For instance, on a medium density display, the
   11060      * default distance is 1280. On a high density display, the default distance
   11061      * is 1920.</p>
   11062      *
   11063      * <p>If you want to specify a distance that leads to visually consistent
   11064      * results across various densities, use the following formula:</p>
   11065      * <pre>
   11066      * float scale = context.getResources().getDisplayMetrics().density;
   11067      * view.setCameraDistance(distance * scale);
   11068      * </pre>
   11069      *
   11070      * <p>The density scale factor of a high density display is 1.5,
   11071      * and 1920 = 1280 * 1.5.</p>
   11072      *
   11073      * @param distance The distance in "depth pixels", if negative the opposite
   11074      *        value is used
   11075      *
   11076      * @see #setRotationX(float)
   11077      * @see #setRotationY(float)
   11078      */
   11079     public void setCameraDistance(float distance) {
   11080         final float dpi = mResources.getDisplayMetrics().densityDpi;
   11081 
   11082         invalidateViewProperty(true, false);
   11083         mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
   11084         invalidateViewProperty(false, false);
   11085 
   11086         invalidateParentIfNeededAndWasQuickRejected();
   11087     }
   11088 
   11089     /**
   11090      * The degrees that the view is rotated around the pivot point.
   11091      *
   11092      * @see #setRotation(float)
   11093      * @see #getPivotX()
   11094      * @see #getPivotY()
   11095      *
   11096      * @return The degrees of rotation.
   11097      */
   11098     @ViewDebug.ExportedProperty(category = "drawing")
   11099     public float getRotation() {
   11100         return mRenderNode.getRotation();
   11101     }
   11102 
   11103     /**
   11104      * Sets the degrees that the view is rotated around the pivot point. Increasing values
   11105      * result in clockwise rotation.
   11106      *
   11107      * @param rotation The degrees of rotation.
   11108      *
   11109      * @see #getRotation()
   11110      * @see #getPivotX()
   11111      * @see #getPivotY()
   11112      * @see #setRotationX(float)
   11113      * @see #setRotationY(float)
   11114      *
   11115      * @attr ref android.R.styleable#View_rotation
   11116      */
   11117     public void setRotation(float rotation) {
   11118         if (rotation != getRotation()) {
   11119             // Double-invalidation is necessary to capture view's old and new areas
   11120             invalidateViewProperty(true, false);
   11121             mRenderNode.setRotation(rotation);
   11122             invalidateViewProperty(false, true);
   11123 
   11124             invalidateParentIfNeededAndWasQuickRejected();
   11125             notifySubtreeAccessibilityStateChangedIfNeeded();
   11126         }
   11127     }
   11128 
   11129     /**
   11130      * The degrees that the view is rotated around the vertical axis through the pivot point.
   11131      *
   11132      * @see #getPivotX()
   11133      * @see #getPivotY()
   11134      * @see #setRotationY(float)
   11135      *
   11136      * @return The degrees of Y rotation.
   11137      */
   11138     @ViewDebug.ExportedProperty(category = "drawing")
   11139     public float getRotationY() {
   11140         return mRenderNode.getRotationY();
   11141     }
   11142 
   11143     /**
   11144      * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
   11145      * Increasing values result in counter-clockwise rotation from the viewpoint of looking
   11146      * down the y axis.
   11147      *
   11148      * When rotating large views, it is recommended to adjust the camera distance
   11149      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
   11150      *
   11151      * @param rotationY The degrees of Y rotation.
   11152      *
   11153      * @see #getRotationY()
   11154      * @see #getPivotX()
   11155      * @see #getPivotY()
   11156      * @see #setRotation(float)
   11157      * @see #setRotationX(float)
   11158      * @see #setCameraDistance(float)
   11159      *
   11160      * @attr ref android.R.styleable#View_rotationY
   11161      */
   11162     public void setRotationY(float rotationY) {
   11163         if (rotationY != getRotationY()) {
   11164             invalidateViewProperty(true, false);
   11165             mRenderNode.setRotationY(rotationY);
   11166             invalidateViewProperty(false, true);
   11167 
   11168             invalidateParentIfNeededAndWasQuickRejected();
   11169             notifySubtreeAccessibilityStateChangedIfNeeded();
   11170         }
   11171     }
   11172 
   11173     /**
   11174      * The degrees that the view is rotated around the horizontal axis through the pivot point.
   11175      *
   11176      * @see #getPivotX()
   11177      * @see #getPivotY()
   11178      * @see #setRotationX(float)
   11179      *
   11180      * @return The degrees of X rotation.
   11181      */
   11182     @ViewDebug.ExportedProperty(category = "drawing")
   11183     public float getRotationX() {
   11184         return mRenderNode.getRotationX();
   11185     }
   11186 
   11187     /**
   11188      * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
   11189      * Increasing values result in clockwise rotation from the viewpoint of looking down the
   11190      * x axis.
   11191      *
   11192      * When rotating large views, it is recommended to adjust the camera distance
   11193      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
   11194      *
   11195      * @param rotationX The degrees of X rotation.
   11196      *
   11197      * @see #getRotationX()
   11198      * @see #getPivotX()
   11199      * @see #getPivotY()
   11200      * @see #setRotation(float)
   11201      * @see #setRotationY(float)
   11202      * @see #setCameraDistance(float)
   11203      *
   11204      * @attr ref android.R.styleable#View_rotationX
   11205      */
   11206     public void setRotationX(float rotationX) {
   11207         if (rotationX != getRotationX()) {
   11208             invalidateViewProperty(true, false);
   11209             mRenderNode.setRotationX(rotationX);
   11210             invalidateViewProperty(false, true);
   11211 
   11212             invalidateParentIfNeededAndWasQuickRejected();
   11213             notifySubtreeAccessibilityStateChangedIfNeeded();
   11214         }
   11215     }
   11216 
   11217     /**
   11218      * The amount that the view is scaled in x around the pivot point, as a proportion of
   11219      * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
   11220      *
   11221      * <p>By default, this is 1.0f.
   11222      *
   11223      * @see #getPivotX()
   11224      * @see #getPivotY()
   11225      * @return The scaling factor.
   11226      */
   11227     @ViewDebug.ExportedProperty(category = "drawing")
   11228     public float getScaleX() {
   11229         return mRenderNode.getScaleX();
   11230     }
   11231 
   11232     /**
   11233      * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
   11234      * the view's unscaled width. A value of 1 means that no scaling is applied.
   11235      *
   11236      * @param scaleX The scaling factor.
   11237      * @see #getPivotX()
   11238      * @see #getPivotY()
   11239      *
   11240      * @attr ref android.R.styleable#View_scaleX
   11241      */
   11242     public void setScaleX(float scaleX) {
   11243         if (scaleX != getScaleX()) {
   11244             invalidateViewProperty(true, false);
   11245             mRenderNode.setScaleX(scaleX);
   11246             invalidateViewProperty(false, true);
   11247 
   11248             invalidateParentIfNeededAndWasQuickRejected();
   11249             notifySubtreeAccessibilityStateChangedIfNeeded();
   11250         }
   11251     }
   11252 
   11253     /**
   11254      * The amount that the view is scaled in y around the pivot point, as a proportion of
   11255      * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
   11256      *
   11257      * <p>By default, this is 1.0f.
   11258      *
   11259      * @see #getPivotX()
   11260      * @see #getPivotY()
   11261      * @return The scaling factor.
   11262      */
   11263     @ViewDebug.ExportedProperty(category = "drawing")
   11264     public float getScaleY() {
   11265         return mRenderNode.getScaleY();
   11266     }
   11267 
   11268     /**
   11269      * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
   11270      * the view's unscaled width. A value of 1 means that no scaling is applied.
   11271      *
   11272      * @param scaleY The scaling factor.
   11273      * @see #getPivotX()
   11274      * @see #getPivotY()
   11275      *
   11276      * @attr ref android.R.styleable#View_scaleY
   11277      */
   11278     public void setScaleY(float scaleY) {
   11279         if (scaleY != getScaleY()) {
   11280             invalidateViewProperty(true, false);
   11281             mRenderNode.setScaleY(scaleY);
   11282             invalidateViewProperty(false, true);
   11283 
   11284             invalidateParentIfNeededAndWasQuickRejected();
   11285             notifySubtreeAccessibilityStateChangedIfNeeded();
   11286         }
   11287     }
   11288 
   11289     /**
   11290      * The x location of the point around which the view is {@link #setRotation(float) rotated}
   11291      * and {@link #setScaleX(float) scaled}.
   11292      *
   11293      * @see #getRotation()
   11294      * @see #getScaleX()
   11295      * @see #getScaleY()
   11296      * @see #getPivotY()
   11297      * @return The x location of the pivot point.
   11298      *
   11299      * @attr ref android.R.styleable#View_transformPivotX
   11300      */
   11301     @ViewDebug.ExportedProperty(category = "drawing")
   11302     public float getPivotX() {
   11303         return mRenderNode.getPivotX();
   11304     }
   11305 
   11306     /**
   11307      * Sets the x location of the point around which the view is
   11308      * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
   11309      * By default, the pivot point is centered on the object.
   11310      * Setting this property disables this behavior and causes the view to use only the
   11311      * explicitly set pivotX and pivotY values.
   11312      *
   11313      * @param pivotX The x location of the pivot point.
   11314      * @see #getRotation()
   11315      * @see #getScaleX()
   11316      * @see #getScaleY()
   11317      * @see #getPivotY()
   11318      *
   11319      * @attr ref android.R.styleable#View_transformPivotX
   11320      */
   11321     public void setPivotX(float pivotX) {
   11322         if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
   11323             invalidateViewProperty(true, false);
   11324             mRenderNode.setPivotX(pivotX);
   11325             invalidateViewProperty(false, true);
   11326 
   11327             invalidateParentIfNeededAndWasQuickRejected();
   11328         }
   11329     }
   11330 
   11331     /**
   11332      * The y location of the point around which the view is {@link #setRotation(float) rotated}
   11333      * and {@link #setScaleY(float) scaled}.
   11334      *
   11335      * @see #getRotation()
   11336      * @see #getScaleX()
   11337      * @see #getScaleY()
   11338      * @see #getPivotY()
   11339      * @return The y location of the pivot point.
   11340      *
   11341      * @attr ref android.R.styleable#View_transformPivotY
   11342      */
   11343     @ViewDebug.ExportedProperty(category = "drawing")
   11344     public float getPivotY() {
   11345         return mRenderNode.getPivotY();
   11346     }
   11347 
   11348     /**
   11349      * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
   11350      * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
   11351      * Setting this property disables this behavior and causes the view to use only the
   11352      * explicitly set pivotX and pivotY values.
   11353      *
   11354      * @param pivotY The y location of the pivot point.
   11355      * @see #getRotation()
   11356      * @see #getScaleX()
   11357      * @see #getScaleY()
   11358      * @see #getPivotY()
   11359      *
   11360      * @attr ref android.R.styleable#View_transformPivotY
   11361      */
   11362     public void setPivotY(float pivotY) {
   11363         if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
   11364             invalidateViewProperty(true, false);
   11365             mRenderNode.setPivotY(pivotY);
   11366             invalidateViewProperty(false, true);
   11367 
   11368             invalidateParentIfNeededAndWasQuickRejected();
   11369         }
   11370     }
   11371 
   11372     /**
   11373      * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
   11374      * completely transparent and 1 means the view is completely opaque.
   11375      *
   11376      * <p>By default this is 1.0f.
   11377      * @return The opacity of the view.
   11378      */
   11379     @ViewDebug.ExportedProperty(category = "drawing")
   11380     public float getAlpha() {
   11381         return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
   11382     }
   11383 
   11384     /**
   11385      * Returns whether this View has content which overlaps.
   11386      *
   11387      * <p>This function, intended to be overridden by specific View types, is an optimization when
   11388      * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
   11389      * an offscreen buffer and then composited into place, which can be expensive. If the view has
   11390      * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
   11391      * directly. An example of overlapping rendering is a TextView with a background image, such as
   11392      * a Button. An example of non-overlapping rendering is a TextView with no background, or an
   11393      * ImageView with only the foreground image. The default implementation returns true; subclasses
   11394      * should override if they have cases which can be optimized.</p>
   11395      *
   11396      * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
   11397      * necessitates that a View return true if it uses the methods internally without passing the
   11398      * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
   11399      *
   11400      * @return true if the content in this view might overlap, false otherwise.
   11401      */
   11402     @ViewDebug.ExportedProperty(category = "drawing")
   11403     public boolean hasOverlappingRendering() {
   11404         return true;
   11405     }
   11406 
   11407     /**
   11408      * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
   11409      * completely transparent and 1 means the view is completely opaque.
   11410      *
   11411      * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
   11412      * can have significant performance implications, especially for large views. It is best to use
   11413      * the alpha property sparingly and transiently, as in the case of fading animations.</p>
   11414      *
   11415      * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
   11416      * strongly recommended for performance reasons to either override
   11417      * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
   11418      * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
   11419      * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
   11420      * the default path for rendering an unlayered View with alpha could add multiple milliseconds
   11421      * of rendering cost, even for simple or small views. Starting with
   11422      * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
   11423      * applied to the view at the rendering level.</p>
   11424      *
   11425      * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
   11426      * responsible for applying the opacity itself.</p>
   11427      *
   11428      * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
   11429      * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
   11430      * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
   11431      * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
   11432      *
   11433      * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
   11434      * value will clip a View to its bounds, unless the View returns <code>false</code> from
   11435      * {@link #hasOverlappingRendering}.</p>
   11436      *
   11437      * @param alpha The opacity of the view.
   11438      *
   11439      * @see #hasOverlappingRendering()
   11440      * @see #setLayerType(int, android.graphics.Paint)
   11441      *
   11442      * @attr ref android.R.styleable#View_alpha
   11443      */
   11444     public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
   11445         ensureTransformationInfo();
   11446         if (mTransformationInfo.mAlpha != alpha) {
   11447             mTransformationInfo.mAlpha = alpha;
   11448             if (onSetAlpha((int) (alpha * 255))) {
   11449                 mPrivateFlags |= PFLAG_ALPHA_SET;
   11450                 // subclass is handling alpha - don't optimize rendering cache invalidation
   11451                 invalidateParentCaches();
   11452                 invalidate(true);
   11453             } else {
   11454                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
   11455                 invalidateViewProperty(true, false);
   11456                 mRenderNode.setAlpha(getFinalAlpha());
   11457                 notifyViewAccessibilityStateChangedIfNeeded(
   11458                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   11459             }
   11460         }
   11461     }
   11462 
   11463     /**
   11464      * Faster version of setAlpha() which performs the same steps except there are
   11465      * no calls to invalidate(). The caller of this function should perform proper invalidation
   11466      * on the parent and this object. The return value indicates whether the subclass handles
   11467      * alpha (the return value for onSetAlpha()).
   11468      *
   11469      * @param alpha The new value for the alpha property
   11470      * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
   11471      *         the new value for the alpha property is different from the old value
   11472      */
   11473     boolean setAlphaNoInvalidation(float alpha) {
   11474         ensureTransformationInfo();
   11475         if (mTransformationInfo.mAlpha != alpha) {
   11476             mTransformationInfo.mAlpha = alpha;
   11477             boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
   11478             if (subclassHandlesAlpha) {
   11479                 mPrivateFlags |= PFLAG_ALPHA_SET;
   11480                 return true;
   11481             } else {
   11482                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
   11483                 mRenderNode.setAlpha(getFinalAlpha());
   11484             }
   11485         }
   11486         return false;
   11487     }
   11488 
   11489     /**
   11490      * This property is hidden and intended only for use by the Fade transition, which
   11491      * animates it to produce a visual translucency that does not side-effect (or get
   11492      * affected by) the real alpha property. This value is composited with the other
   11493      * alpha value (and the AlphaAnimation value, when that is present) to produce
   11494      * a final visual translucency result, which is what is passed into the DisplayList.
   11495      *
   11496      * @hide
   11497      */
   11498     public void setTransitionAlpha(float alpha) {
   11499         ensureTransformationInfo();
   11500         if (mTransformationInfo.mTransitionAlpha != alpha) {
   11501             mTransformationInfo.mTransitionAlpha = alpha;
   11502             mPrivateFlags &= ~PFLAG_ALPHA_SET;
   11503             invalidateViewProperty(true, false);
   11504             mRenderNode.setAlpha(getFinalAlpha());
   11505         }
   11506     }
   11507 
   11508     /**
   11509      * Calculates the visual alpha of this view, which is a combination of the actual
   11510      * alpha value and the transitionAlpha value (if set).
   11511      */
   11512     private float getFinalAlpha() {
   11513         if (mTransformationInfo != null) {
   11514             return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
   11515         }
   11516         return 1;
   11517     }
   11518 
   11519     /**
   11520      * This property is hidden and intended only for use by the Fade transition, which
   11521      * animates it to produce a visual translucency that does not side-effect (or get
   11522      * affected by) the real alpha property. This value is composited with the other
   11523      * alpha value (and the AlphaAnimation value, when that is present) to produce
   11524      * a final visual translucency result, which is what is passed into the DisplayList.
   11525      *
   11526      * @hide
   11527      */
   11528     @ViewDebug.ExportedProperty(category = "drawing")
   11529     public float getTransitionAlpha() {
   11530         return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
   11531     }
   11532 
   11533     /**
   11534      * Top position of this view relative to its parent.
   11535      *
   11536      * @return The top of this view, in pixels.
   11537      */
   11538     @ViewDebug.CapturedViewProperty
   11539     public final int getTop() {
   11540         return mTop;
   11541     }
   11542 
   11543     /**
   11544      * Sets the top position of this view relative to its parent. This method is meant to be called
   11545      * by the layout system and should not generally be called otherwise, because the property
   11546      * may be changed at any time by the layout.
   11547      *
   11548      * @param top The top of this view, in pixels.
   11549      */
   11550     public final void setTop(int top) {
   11551         if (top != mTop) {
   11552             final boolean matrixIsIdentity = hasIdentityMatrix();
   11553             if (matrixIsIdentity) {
   11554                 if (mAttachInfo != null) {
   11555                     int minTop;
   11556                     int yLoc;
   11557                     if (top < mTop) {
   11558                         minTop = top;
   11559                         yLoc = top - mTop;
   11560                     } else {
   11561                         minTop = mTop;
   11562                         yLoc = 0;
   11563                     }
   11564                     invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
   11565                 }
   11566             } else {
   11567                 // Double-invalidation is necessary to capture view's old and new areas
   11568                 invalidate(true);
   11569             }
   11570 
   11571             int width = mRight - mLeft;
   11572             int oldHeight = mBottom - mTop;
   11573 
   11574             mTop = top;
   11575             mRenderNode.setTop(mTop);
   11576 
   11577             sizeChange(width, mBottom - mTop, width, oldHeight);
   11578 
   11579             if (!matrixIsIdentity) {
   11580                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
   11581                 invalidate(true);
   11582             }
   11583             mBackgroundSizeChanged = true;
   11584             if (mForegroundInfo != null) {
   11585                 mForegroundInfo.mBoundsChanged = true;
   11586             }
   11587             invalidateParentIfNeeded();
   11588             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
   11589                 // View was rejected last time it was drawn by its parent; this may have changed
   11590                 invalidateParentIfNeeded();
   11591             }
   11592         }
   11593     }
   11594 
   11595     /**
   11596      * Bottom position of this view relative to its parent.
   11597      *
   11598      * @return The bottom of this view, in pixels.
   11599      */
   11600     @ViewDebug.CapturedViewProperty
   11601     public final int getBottom() {
   11602         return mBottom;
   11603     }
   11604 
   11605     /**
   11606      * True if this view has changed since the last time being drawn.
   11607      *
   11608      * @return The dirty state of this view.
   11609      */
   11610     public boolean isDirty() {
   11611         return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
   11612     }
   11613 
   11614     /**
   11615      * Sets the bottom position of this view relative to its parent. This method is meant to be
   11616      * called by the layout system and should not generally be called otherwise, because the
   11617      * property may be changed at any time by the layout.
   11618      *
   11619      * @param bottom The bottom of this view, in pixels.
   11620      */
   11621     public final void setBottom(int bottom) {
   11622         if (bottom != mBottom) {
   11623             final boolean matrixIsIdentity = hasIdentityMatrix();
   11624             if (matrixIsIdentity) {
   11625                 if (mAttachInfo != null) {
   11626                     int maxBottom;
   11627                     if (bottom < mBottom) {
   11628                         maxBottom = mBottom;
   11629                     } else {
   11630                         maxBottom = bottom;
   11631                     }
   11632                     invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
   11633                 }
   11634             } else {
   11635                 // Double-invalidation is necessary to capture view's old and new areas
   11636                 invalidate(true);
   11637             }
   11638 
   11639             int width = mRight - mLeft;
   11640             int oldHeight = mBottom - mTop;
   11641 
   11642             mBottom = bottom;
   11643             mRenderNode.setBottom(mBottom);
   11644 
   11645             sizeChange(width, mBottom - mTop, width, oldHeight);
   11646 
   11647             if (!matrixIsIdentity) {
   11648                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
   11649                 invalidate(true);
   11650             }
   11651             mBackgroundSizeChanged = true;
   11652             if (mForegroundInfo != null) {
   11653                 mForegroundInfo.mBoundsChanged = true;
   11654             }
   11655             invalidateParentIfNeeded();
   11656             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
   11657                 // View was rejected last time it was drawn by its parent; this may have changed
   11658                 invalidateParentIfNeeded();
   11659             }
   11660         }
   11661     }
   11662 
   11663     /**
   11664      * Left position of this view relative to its parent.
   11665      *
   11666      * @return The left edge of this view, in pixels.
   11667      */
   11668     @ViewDebug.CapturedViewProperty
   11669     public final int getLeft() {
   11670         return mLeft;
   11671     }
   11672 
   11673     /**
   11674      * Sets the left position of this view relative to its parent. This method is meant to be called
   11675      * by the layout system and should not generally be called otherwise, because the property
   11676      * may be changed at any time by the layout.
   11677      *
   11678      * @param left The left of this view, in pixels.
   11679      */
   11680     public final void setLeft(int left) {
   11681         if (left != mLeft) {
   11682             final boolean matrixIsIdentity = hasIdentityMatrix();
   11683             if (matrixIsIdentity) {
   11684                 if (mAttachInfo != null) {
   11685                     int minLeft;
   11686                     int xLoc;
   11687                     if (left < mLeft) {
   11688                         minLeft = left;
   11689                         xLoc = left - mLeft;
   11690                     } else {
   11691                         minLeft = mLeft;
   11692                         xLoc = 0;
   11693                     }
   11694                     invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
   11695                 }
   11696             } else {
   11697                 // Double-invalidation is necessary to capture view's old and new areas
   11698                 invalidate(true);
   11699             }
   11700 
   11701             int oldWidth = mRight - mLeft;
   11702             int height = mBottom - mTop;
   11703 
   11704             mLeft = left;
   11705             mRenderNode.setLeft(left);
   11706 
   11707             sizeChange(mRight - mLeft, height, oldWidth, height);
   11708 
   11709             if (!matrixIsIdentity) {
   11710                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
   11711                 invalidate(true);
   11712             }
   11713             mBackgroundSizeChanged = true;
   11714             if (mForegroundInfo != null) {
   11715                 mForegroundInfo.mBoundsChanged = true;
   11716             }
   11717             invalidateParentIfNeeded();
   11718             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
   11719                 // View was rejected last time it was drawn by its parent; this may have changed
   11720                 invalidateParentIfNeeded();
   11721             }
   11722         }
   11723     }
   11724 
   11725     /**
   11726      * Right position of this view relative to its parent.
   11727      *
   11728      * @return The right edge of this view, in pixels.
   11729      */
   11730     @ViewDebug.CapturedViewProperty
   11731     public final int getRight() {
   11732         return mRight;
   11733     }
   11734 
   11735     /**
   11736      * Sets the right position of this view relative to its parent. This method is meant to be called
   11737      * by the layout system and should not generally be called otherwise, because the property
   11738      * may be changed at any time by the layout.
   11739      *
   11740      * @param right The right of this view, in pixels.
   11741      */
   11742     public final void setRight(int right) {
   11743         if (right != mRight) {
   11744             final boolean matrixIsIdentity = hasIdentityMatrix();
   11745             if (matrixIsIdentity) {
   11746                 if (mAttachInfo != null) {
   11747                     int maxRight;
   11748                     if (right < mRight) {
   11749                         maxRight = mRight;
   11750                     } else {
   11751                         maxRight = right;
   11752                     }
   11753                     invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
   11754                 }
   11755             } else {
   11756                 // Double-invalidation is necessary to capture view's old and new areas
   11757                 invalidate(true);
   11758             }
   11759 
   11760             int oldWidth = mRight - mLeft;
   11761             int height = mBottom - mTop;
   11762 
   11763             mRight = right;
   11764             mRenderNode.setRight(mRight);
   11765 
   11766             sizeChange(mRight - mLeft, height, oldWidth, height);
   11767 
   11768             if (!matrixIsIdentity) {
   11769                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
   11770                 invalidate(true);
   11771             }
   11772             mBackgroundSizeChanged = true;
   11773             if (mForegroundInfo != null) {
   11774                 mForegroundInfo.mBoundsChanged = true;
   11775             }
   11776             invalidateParentIfNeeded();
   11777             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
   11778                 // View was rejected last time it was drawn by its parent; this may have changed
   11779                 invalidateParentIfNeeded();
   11780             }
   11781         }
   11782     }
   11783 
   11784     /**
   11785      * The visual x position of this view, in pixels. This is equivalent to the
   11786      * {@link #setTranslationX(float) translationX} property plus the current
   11787      * {@link #getLeft() left} property.
   11788      *
   11789      * @return The visual x position of this view, in pixels.
   11790      */
   11791     @ViewDebug.ExportedProperty(category = "drawing")
   11792     public float getX() {
   11793         return mLeft + getTranslationX();
   11794     }
   11795 
   11796     /**
   11797      * Sets the visual x position of this view, in pixels. This is equivalent to setting the
   11798      * {@link #setTranslationX(float) translationX} property to be the difference between
   11799      * the x value passed in and the current {@link #getLeft() left} property.
   11800      *
   11801      * @param x The visual x position of this view, in pixels.
   11802      */
   11803     public void setX(float x) {
   11804         setTranslationX(x - mLeft);
   11805     }
   11806 
   11807     /**
   11808      * The visual y position of this view, in pixels. This is equivalent to the
   11809      * {@link #setTranslationY(float) translationY} property plus the current
   11810      * {@link #getTop() top} property.
   11811      *
   11812      * @return The visual y position of this view, in pixels.
   11813      */
   11814     @ViewDebug.ExportedProperty(category = "drawing")
   11815     public float getY() {
   11816         return mTop + getTranslationY();
   11817     }
   11818 
   11819     /**
   11820      * Sets the visual y position of this view, in pixels. This is equivalent to setting the
   11821      * {@link #setTranslationY(float) translationY} property to be the difference between
   11822      * the y value passed in and the current {@link #getTop() top} property.
   11823      *
   11824      * @param y The visual y position of this view, in pixels.
   11825      */
   11826     public void setY(float y) {
   11827         setTranslationY(y - mTop);
   11828     }
   11829 
   11830     /**
   11831      * The visual z position of this view, in pixels. This is equivalent to the
   11832      * {@link #setTranslationZ(float) translationZ} property plus the current
   11833      * {@link #getElevation() elevation} property.
   11834      *
   11835      * @return The visual z position of this view, in pixels.
   11836      */
   11837     @ViewDebug.ExportedProperty(category = "drawing")
   11838     public float getZ() {
   11839         return getElevation() + getTranslationZ();
   11840     }
   11841 
   11842     /**
   11843      * Sets the visual z position of this view, in pixels. This is equivalent to setting the
   11844      * {@link #setTranslationZ(float) translationZ} property to be the difference between
   11845      * the x value passed in and the current {@link #getElevation() elevation} property.
   11846      *
   11847      * @param z The visual z position of this view, in pixels.
   11848      */
   11849     public void setZ(float z) {
   11850         setTranslationZ(z - getElevation());
   11851     }
   11852 
   11853     /**
   11854      * The base elevation of this view relative to its parent, in pixels.
   11855      *
   11856      * @return The base depth position of the view, in pixels.
   11857      */
   11858     @ViewDebug.ExportedProperty(category = "drawing")
   11859     public float getElevation() {
   11860         return mRenderNode.getElevation();
   11861     }
   11862 
   11863     /**
   11864      * Sets the base elevation of this view, in pixels.
   11865      *
   11866      * @attr ref android.R.styleable#View_elevation
   11867      */
   11868     public void setElevation(float elevation) {
   11869         if (elevation != getElevation()) {
   11870             invalidateViewProperty(true, false);
   11871             mRenderNode.setElevation(elevation);
   11872             invalidateViewProperty(false, true);
   11873 
   11874             invalidateParentIfNeededAndWasQuickRejected();
   11875         }
   11876     }
   11877 
   11878     /**
   11879      * The horizontal location of this view relative to its {@link #getLeft() left} position.
   11880      * This position is post-layout, in addition to wherever the object's
   11881      * layout placed it.
   11882      *
   11883      * @return The horizontal position of this view relative to its left position, in pixels.
   11884      */
   11885     @ViewDebug.ExportedProperty(category = "drawing")
   11886     public float getTranslationX() {
   11887         return mRenderNode.getTranslationX();
   11888     }
   11889 
   11890     /**
   11891      * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
   11892      * This effectively positions the object post-layout, in addition to wherever the object's
   11893      * layout placed it.
   11894      *
   11895      * @param translationX The horizontal position of this view relative to its left position,
   11896      * in pixels.
   11897      *
   11898      * @attr ref android.R.styleable#View_translationX
   11899      */
   11900     public void setTranslationX(float translationX) {
   11901         if (translationX != getTranslationX()) {
   11902             invalidateViewProperty(true, false);
   11903             mRenderNode.setTranslationX(translationX);
   11904             invalidateViewProperty(false, true);
   11905 
   11906             invalidateParentIfNeededAndWasQuickRejected();
   11907             notifySubtreeAccessibilityStateChangedIfNeeded();
   11908         }
   11909     }
   11910 
   11911     /**
   11912      * The vertical location of this view relative to its {@link #getTop() top} position.
   11913      * This position is post-layout, in addition to wherever the object's
   11914      * layout placed it.
   11915      *
   11916      * @return The vertical position of this view relative to its top position,
   11917      * in pixels.
   11918      */
   11919     @ViewDebug.ExportedProperty(category = "drawing")
   11920     public float getTranslationY() {
   11921         return mRenderNode.getTranslationY();
   11922     }
   11923 
   11924     /**
   11925      * Sets the vertical location of this view relative to its {@link #getTop() top} position.
   11926      * This effectively positions the object post-layout, in addition to wherever the object's
   11927      * layout placed it.
   11928      *
   11929      * @param translationY The vertical position of this view relative to its top position,
   11930      * in pixels.
   11931      *
   11932      * @attr ref android.R.styleable#View_translationY
   11933      */
   11934     public void setTranslationY(float translationY) {
   11935         if (translationY != getTranslationY()) {
   11936             invalidateViewProperty(true, false);
   11937             mRenderNode.setTranslationY(translationY);
   11938             invalidateViewProperty(false, true);
   11939 
   11940             invalidateParentIfNeededAndWasQuickRejected();
   11941             notifySubtreeAccessibilityStateChangedIfNeeded();
   11942         }
   11943     }
   11944 
   11945     /**
   11946      * The depth location of this view relative to its {@link #getElevation() elevation}.
   11947      *
   11948      * @return The depth of this view relative to its elevation.
   11949      */
   11950     @ViewDebug.ExportedProperty(category = "drawing")
   11951     public float getTranslationZ() {
   11952         return mRenderNode.getTranslationZ();
   11953     }
   11954 
   11955     /**
   11956      * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
   11957      *
   11958      * @attr ref android.R.styleable#View_translationZ
   11959      */
   11960     public void setTranslationZ(float translationZ) {
   11961         if (translationZ != getTranslationZ()) {
   11962             invalidateViewProperty(true, false);
   11963             mRenderNode.setTranslationZ(translationZ);
   11964             invalidateViewProperty(false, true);
   11965 
   11966             invalidateParentIfNeededAndWasQuickRejected();
   11967         }
   11968     }
   11969 
   11970     /** @hide */
   11971     public void setAnimationMatrix(Matrix matrix) {
   11972         invalidateViewProperty(true, false);
   11973         mRenderNode.setAnimationMatrix(matrix);
   11974         invalidateViewProperty(false, true);
   11975 
   11976         invalidateParentIfNeededAndWasQuickRejected();
   11977     }
   11978 
   11979     /**
   11980      * Returns the current StateListAnimator if exists.
   11981      *
   11982      * @return StateListAnimator or null if it does not exists
   11983      * @see    #setStateListAnimator(android.animation.StateListAnimator)
   11984      */
   11985     public StateListAnimator getStateListAnimator() {
   11986         return mStateListAnimator;
   11987     }
   11988 
   11989     /**
   11990      * Attaches the provided StateListAnimator to this View.
   11991      * <p>
   11992      * Any previously attached StateListAnimator will be detached.
   11993      *
   11994      * @param stateListAnimator The StateListAnimator to update the view
   11995      * @see {@link android.animation.StateListAnimator}
   11996      */
   11997     public void setStateListAnimator(StateListAnimator stateListAnimator) {
   11998         if (mStateListAnimator == stateListAnimator) {
   11999             return;
   12000         }
   12001         if (mStateListAnimator != null) {
   12002             mStateListAnimator.setTarget(null);
   12003         }
   12004         mStateListAnimator = stateListAnimator;
   12005         if (stateListAnimator != null) {
   12006             stateListAnimator.setTarget(this);
   12007             if (isAttachedToWindow()) {
   12008                 stateListAnimator.setState(getDrawableState());
   12009             }
   12010         }
   12011     }
   12012 
   12013     /**
   12014      * Returns whether the Outline should be used to clip the contents of the View.
   12015      * <p>
   12016      * Note that this flag will only be respected if the View's Outline returns true from
   12017      * {@link Outline#canClip()}.
   12018      *
   12019      * @see #setOutlineProvider(ViewOutlineProvider)
   12020      * @see #setClipToOutline(boolean)
   12021      */
   12022     public final boolean getClipToOutline() {
   12023         return mRenderNode.getClipToOutline();
   12024     }
   12025 
   12026     /**
   12027      * Sets whether the View's Outline should be used to clip the contents of the View.
   12028      * <p>
   12029      * Only a single non-rectangular clip can be applied on a View at any time.
   12030      * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
   12031      * circular reveal} animation take priority over Outline clipping, and
   12032      * child Outline clipping takes priority over Outline clipping done by a
   12033      * parent.
   12034      * <p>
   12035      * Note that this flag will only be respected if the View's Outline returns true from
   12036      * {@link Outline#canClip()}.
   12037      *
   12038      * @see #setOutlineProvider(ViewOutlineProvider)
   12039      * @see #getClipToOutline()
   12040      */
   12041     public void setClipToOutline(boolean clipToOutline) {
   12042         damageInParent();
   12043         if (getClipToOutline() != clipToOutline) {
   12044             mRenderNode.setClipToOutline(clipToOutline);
   12045         }
   12046     }
   12047 
   12048     // correspond to the enum values of View_outlineProvider
   12049     private static final int PROVIDER_BACKGROUND = 0;
   12050     private static final int PROVIDER_NONE = 1;
   12051     private static final int PROVIDER_BOUNDS = 2;
   12052     private static final int PROVIDER_PADDED_BOUNDS = 3;
   12053     private void setOutlineProviderFromAttribute(int providerInt) {
   12054         switch (providerInt) {
   12055             case PROVIDER_BACKGROUND:
   12056                 setOutlineProvider(ViewOutlineProvider.BACKGROUND);
   12057                 break;
   12058             case PROVIDER_NONE:
   12059                 setOutlineProvider(null);
   12060                 break;
   12061             case PROVIDER_BOUNDS:
   12062                 setOutlineProvider(ViewOutlineProvider.BOUNDS);
   12063                 break;
   12064             case PROVIDER_PADDED_BOUNDS:
   12065                 setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
   12066                 break;
   12067         }
   12068     }
   12069 
   12070     /**
   12071      * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
   12072      * the shape of the shadow it casts, and enables outline clipping.
   12073      * <p>
   12074      * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
   12075      * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
   12076      * outline provider with this method allows this behavior to be overridden.
   12077      * <p>
   12078      * If the ViewOutlineProvider is null, if querying it for an outline returns false,
   12079      * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
   12080      * <p>
   12081      * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
   12082      *
   12083      * @see #setClipToOutline(boolean)
   12084      * @see #getClipToOutline()
   12085      * @see #getOutlineProvider()
   12086      */
   12087     public void setOutlineProvider(ViewOutlineProvider provider) {
   12088         mOutlineProvider = provider;
   12089         invalidateOutline();
   12090     }
   12091 
   12092     /**
   12093      * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
   12094      * that defines the shape of the shadow it casts, and enables outline clipping.
   12095      *
   12096      * @see #setOutlineProvider(ViewOutlineProvider)
   12097      */
   12098     public ViewOutlineProvider getOutlineProvider() {
   12099         return mOutlineProvider;
   12100     }
   12101 
   12102     /**
   12103      * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
   12104      *
   12105      * @see #setOutlineProvider(ViewOutlineProvider)
   12106      */
   12107     public void invalidateOutline() {
   12108         rebuildOutline();
   12109 
   12110         notifySubtreeAccessibilityStateChangedIfNeeded();
   12111         invalidateViewProperty(false, false);
   12112     }
   12113 
   12114     /**
   12115      * Internal version of {@link #invalidateOutline()} which invalidates the
   12116      * outline without invalidating the view itself. This is intended to be called from
   12117      * within methods in the View class itself which are the result of the view being
   12118      * invalidated already. For example, when we are drawing the background of a View,
   12119      * we invalidate the outline in case it changed in the meantime, but we do not
   12120      * need to invalidate the view because we're already drawing the background as part
   12121      * of drawing the view in response to an earlier invalidation of the view.
   12122      */
   12123     private void rebuildOutline() {
   12124         // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
   12125         if (mAttachInfo == null) return;
   12126 
   12127         if (mOutlineProvider == null) {
   12128             // no provider, remove outline
   12129             mRenderNode.setOutline(null);
   12130         } else {
   12131             final Outline outline = mAttachInfo.mTmpOutline;
   12132             outline.setEmpty();
   12133             outline.setAlpha(1.0f);
   12134 
   12135             mOutlineProvider.getOutline(this, outline);
   12136             mRenderNode.setOutline(outline);
   12137         }
   12138     }
   12139 
   12140     /**
   12141      * HierarchyViewer only
   12142      *
   12143      * @hide
   12144      */
   12145     @ViewDebug.ExportedProperty(category = "drawing")
   12146     public boolean hasShadow() {
   12147         return mRenderNode.hasShadow();
   12148     }
   12149 
   12150 
   12151     /** @hide */
   12152     public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
   12153         mRenderNode.setRevealClip(shouldClip, x, y, radius);
   12154         invalidateViewProperty(false, false);
   12155     }
   12156 
   12157     /**
   12158      * Hit rectangle in parent's coordinates
   12159      *
   12160      * @param outRect The hit rectangle of the view.
   12161      */
   12162     public void getHitRect(Rect outRect) {
   12163         if (hasIdentityMatrix() || mAttachInfo == null) {
   12164             outRect.set(mLeft, mTop, mRight, mBottom);
   12165         } else {
   12166             final RectF tmpRect = mAttachInfo.mTmpTransformRect;
   12167             tmpRect.set(0, 0, getWidth(), getHeight());
   12168             getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
   12169             outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
   12170                     (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
   12171         }
   12172     }
   12173 
   12174     /**
   12175      * Determines whether the given point, in local coordinates is inside the view.
   12176      */
   12177     /*package*/ final boolean pointInView(float localX, float localY) {
   12178         return localX >= 0 && localX < (mRight - mLeft)
   12179                 && localY >= 0 && localY < (mBottom - mTop);
   12180     }
   12181 
   12182     /**
   12183      * Utility method to determine whether the given point, in local coordinates,
   12184      * is inside the view, where the area of the view is expanded by the slop factor.
   12185      * This method is called while processing touch-move events to determine if the event
   12186      * is still within the view.
   12187      *
   12188      * @hide
   12189      */
   12190     public boolean pointInView(float localX, float localY, float slop) {
   12191         return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
   12192                 localY < ((mBottom - mTop) + slop);
   12193     }
   12194 
   12195     /**
   12196      * When a view has focus and the user navigates away from it, the next view is searched for
   12197      * starting from the rectangle filled in by this method.
   12198      *
   12199      * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
   12200      * of the view.  However, if your view maintains some idea of internal selection,
   12201      * such as a cursor, or a selected row or column, you should override this method and
   12202      * fill in a more specific rectangle.
   12203      *
   12204      * @param r The rectangle to fill in, in this view's coordinates.
   12205      */
   12206     public void getFocusedRect(Rect r) {
   12207         getDrawingRect(r);
   12208     }
   12209 
   12210     /**
   12211      * If some part of this view is not clipped by any of its parents, then
   12212      * return that area in r in global (root) coordinates. To convert r to local
   12213      * coordinates (without taking possible View rotations into account), offset
   12214      * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
   12215      * If the view is completely clipped or translated out, return false.
   12216      *
   12217      * @param r If true is returned, r holds the global coordinates of the
   12218      *        visible portion of this view.
   12219      * @param globalOffset If true is returned, globalOffset holds the dx,dy
   12220      *        between this view and its root. globalOffet may be null.
   12221      * @return true if r is non-empty (i.e. part of the view is visible at the
   12222      *         root level.
   12223      */
   12224     public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
   12225         int width = mRight - mLeft;
   12226         int height = mBottom - mTop;
   12227         if (width > 0 && height > 0) {
   12228             r.set(0, 0, width, height);
   12229             if (globalOffset != null) {
   12230                 globalOffset.set(-mScrollX, -mScrollY);
   12231             }
   12232             return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
   12233         }
   12234         return false;
   12235     }
   12236 
   12237     public final boolean getGlobalVisibleRect(Rect r) {
   12238         return getGlobalVisibleRect(r, null);
   12239     }
   12240 
   12241     public final boolean getLocalVisibleRect(Rect r) {
   12242         final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
   12243         if (getGlobalVisibleRect(r, offset)) {
   12244             r.offset(-offset.x, -offset.y); // make r local
   12245             return true;
   12246         }
   12247         return false;
   12248     }
   12249 
   12250     /**
   12251      * Offset this view's vertical location by the specified number of pixels.
   12252      *
   12253      * @param offset the number of pixels to offset the view by
   12254      */
   12255     public void offsetTopAndBottom(int offset) {
   12256         if (offset != 0) {
   12257             final boolean matrixIsIdentity = hasIdentityMatrix();
   12258             if (matrixIsIdentity) {
   12259                 if (isHardwareAccelerated()) {
   12260                     invalidateViewProperty(false, false);
   12261                 } else {
   12262                     final ViewParent p = mParent;
   12263                     if (p != null && mAttachInfo != null) {
   12264                         final Rect r = mAttachInfo.mTmpInvalRect;
   12265                         int minTop;
   12266                         int maxBottom;
   12267                         int yLoc;
   12268                         if (offset < 0) {
   12269                             minTop = mTop + offset;
   12270                             maxBottom = mBottom;
   12271                             yLoc = offset;
   12272                         } else {
   12273                             minTop = mTop;
   12274                             maxBottom = mBottom + offset;
   12275                             yLoc = 0;
   12276                         }
   12277                         r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
   12278                         p.invalidateChild(this, r);
   12279                     }
   12280                 }
   12281             } else {
   12282                 invalidateViewProperty(false, false);
   12283             }
   12284 
   12285             mTop += offset;
   12286             mBottom += offset;
   12287             mRenderNode.offsetTopAndBottom(offset);
   12288             if (isHardwareAccelerated()) {
   12289                 invalidateViewProperty(false, false);
   12290                 invalidateParentIfNeededAndWasQuickRejected();
   12291             } else {
   12292                 if (!matrixIsIdentity) {
   12293                     invalidateViewProperty(false, true);
   12294                 }
   12295                 invalidateParentIfNeeded();
   12296             }
   12297             notifySubtreeAccessibilityStateChangedIfNeeded();
   12298         }
   12299     }
   12300 
   12301     /**
   12302      * Offset this view's horizontal location by the specified amount of pixels.
   12303      *
   12304      * @param offset the number of pixels to offset the view by
   12305      */
   12306     public void offsetLeftAndRight(int offset) {
   12307         if (offset != 0) {
   12308             final boolean matrixIsIdentity = hasIdentityMatrix();
   12309             if (matrixIsIdentity) {
   12310                 if (isHardwareAccelerated()) {
   12311                     invalidateViewProperty(false, false);
   12312                 } else {
   12313                     final ViewParent p = mParent;
   12314                     if (p != null && mAttachInfo != null) {
   12315                         final Rect r = mAttachInfo.mTmpInvalRect;
   12316                         int minLeft;
   12317                         int maxRight;
   12318                         if (offset < 0) {
   12319                             minLeft = mLeft + offset;
   12320                             maxRight = mRight;
   12321                         } else {
   12322                             minLeft = mLeft;
   12323                             maxRight = mRight + offset;
   12324                         }
   12325                         r.set(0, 0, maxRight - minLeft, mBottom - mTop);
   12326                         p.invalidateChild(this, r);
   12327                     }
   12328                 }
   12329             } else {
   12330                 invalidateViewProperty(false, false);
   12331             }
   12332 
   12333             mLeft += offset;
   12334             mRight += offset;
   12335             mRenderNode.offsetLeftAndRight(offset);
   12336             if (isHardwareAccelerated()) {
   12337                 invalidateViewProperty(false, false);
   12338                 invalidateParentIfNeededAndWasQuickRejected();
   12339             } else {
   12340                 if (!matrixIsIdentity) {
   12341                     invalidateViewProperty(false, true);
   12342                 }
   12343                 invalidateParentIfNeeded();
   12344             }
   12345             notifySubtreeAccessibilityStateChangedIfNeeded();
   12346         }
   12347     }
   12348 
   12349     /**
   12350      * Get the LayoutParams associated with this view. All views should have
   12351      * layout parameters. These supply parameters to the <i>parent</i> of this
   12352      * view specifying how it should be arranged. There are many subclasses of
   12353      * ViewGroup.LayoutParams, and these correspond to the different subclasses
   12354      * of ViewGroup that are responsible for arranging their children.
   12355      *
   12356      * This method may return null if this View is not attached to a parent
   12357      * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
   12358      * was not invoked successfully. When a View is attached to a parent
   12359      * ViewGroup, this method must not return null.
   12360      *
   12361      * @return The LayoutParams associated with this view, or null if no
   12362      *         parameters have been set yet
   12363      */
   12364     @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
   12365     public ViewGroup.LayoutParams getLayoutParams() {
   12366         return mLayoutParams;
   12367     }
   12368 
   12369     /**
   12370      * Set the layout parameters associated with this view. These supply
   12371      * parameters to the <i>parent</i> of this view specifying how it should be
   12372      * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
   12373      * correspond to the different subclasses of ViewGroup that are responsible
   12374      * for arranging their children.
   12375      *
   12376      * @param params The layout parameters for this view, cannot be null
   12377      */
   12378     public void setLayoutParams(ViewGroup.LayoutParams params) {
   12379         if (params == null) {
   12380             throw new NullPointerException("Layout parameters cannot be null");
   12381         }
   12382         mLayoutParams = params;
   12383         resolveLayoutParams();
   12384         if (mParent instanceof ViewGroup) {
   12385             ((ViewGroup) mParent).onSetLayoutParams(this, params);
   12386         }
   12387         requestLayout();
   12388     }
   12389 
   12390     /**
   12391      * Resolve the layout parameters depending on the resolved layout direction
   12392      *
   12393      * @hide
   12394      */
   12395     public void resolveLayoutParams() {
   12396         if (mLayoutParams != null) {
   12397             mLayoutParams.resolveLayoutDirection(getLayoutDirection());
   12398         }
   12399     }
   12400 
   12401     /**
   12402      * Set the scrolled position of your view. This will cause a call to
   12403      * {@link #onScrollChanged(int, int, int, int)} and the view will be
   12404      * invalidated.
   12405      * @param x the x position to scroll to
   12406      * @param y the y position to scroll to
   12407      */
   12408     public void scrollTo(int x, int y) {
   12409         if (mScrollX != x || mScrollY != y) {
   12410             int oldX = mScrollX;
   12411             int oldY = mScrollY;
   12412             mScrollX = x;
   12413             mScrollY = y;
   12414             invalidateParentCaches();
   12415             onScrollChanged(mScrollX, mScrollY, oldX, oldY);
   12416             if (!awakenScrollBars()) {
   12417                 postInvalidateOnAnimation();
   12418             }
   12419         }
   12420     }
   12421 
   12422     /**
   12423      * Move the scrolled position of your view. This will cause a call to
   12424      * {@link #onScrollChanged(int, int, int, int)} and the view will be
   12425      * invalidated.
   12426      * @param x the amount of pixels to scroll by horizontally
   12427      * @param y the amount of pixels to scroll by vertically
   12428      */
   12429     public void scrollBy(int x, int y) {
   12430         scrollTo(mScrollX + x, mScrollY + y);
   12431     }
   12432 
   12433     /**
   12434      * <p>Trigger the scrollbars to draw. When invoked this method starts an
   12435      * animation to fade the scrollbars out after a default delay. If a subclass
   12436      * provides animated scrolling, the start delay should equal the duration
   12437      * of the scrolling animation.</p>
   12438      *
   12439      * <p>The animation starts only if at least one of the scrollbars is
   12440      * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
   12441      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
   12442      * this method returns true, and false otherwise. If the animation is
   12443      * started, this method calls {@link #invalidate()}; in that case the
   12444      * caller should not call {@link #invalidate()}.</p>
   12445      *
   12446      * <p>This method should be invoked every time a subclass directly updates
   12447      * the scroll parameters.</p>
   12448      *
   12449      * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
   12450      * and {@link #scrollTo(int, int)}.</p>
   12451      *
   12452      * @return true if the animation is played, false otherwise
   12453      *
   12454      * @see #awakenScrollBars(int)
   12455      * @see #scrollBy(int, int)
   12456      * @see #scrollTo(int, int)
   12457      * @see #isHorizontalScrollBarEnabled()
   12458      * @see #isVerticalScrollBarEnabled()
   12459      * @see #setHorizontalScrollBarEnabled(boolean)
   12460      * @see #setVerticalScrollBarEnabled(boolean)
   12461      */
   12462     protected boolean awakenScrollBars() {
   12463         return mScrollCache != null &&
   12464                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
   12465     }
   12466 
   12467     /**
   12468      * Trigger the scrollbars to draw.
   12469      * This method differs from awakenScrollBars() only in its default duration.
   12470      * initialAwakenScrollBars() will show the scroll bars for longer than
   12471      * usual to give the user more of a chance to notice them.
   12472      *
   12473      * @return true if the animation is played, false otherwise.
   12474      */
   12475     private boolean initialAwakenScrollBars() {
   12476         return mScrollCache != null &&
   12477                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
   12478     }
   12479 
   12480     /**
   12481      * <p>
   12482      * Trigger the scrollbars to draw. When invoked this method starts an
   12483      * animation to fade the scrollbars out after a fixed delay. If a subclass
   12484      * provides animated scrolling, the start delay should equal the duration of
   12485      * the scrolling animation.
   12486      * </p>
   12487      *
   12488      * <p>
   12489      * The animation starts only if at least one of the scrollbars is enabled,
   12490      * as specified by {@link #isHorizontalScrollBarEnabled()} and
   12491      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
   12492      * this method returns true, and false otherwise. If the animation is
   12493      * started, this method calls {@link #invalidate()}; in that case the caller
   12494      * should not call {@link #invalidate()}.
   12495      * </p>
   12496      *
   12497      * <p>
   12498      * This method should be invoked every time a subclass directly updates the
   12499      * scroll parameters.
   12500      * </p>
   12501      *
   12502      * @param startDelay the delay, in milliseconds, after which the animation
   12503      *        should start; when the delay is 0, the animation starts
   12504      *        immediately
   12505      * @return true if the animation is played, false otherwise
   12506      *
   12507      * @see #scrollBy(int, int)
   12508      * @see #scrollTo(int, int)
   12509      * @see #isHorizontalScrollBarEnabled()
   12510      * @see #isVerticalScrollBarEnabled()
   12511      * @see #setHorizontalScrollBarEnabled(boolean)
   12512      * @see #setVerticalScrollBarEnabled(boolean)
   12513      */
   12514     protected boolean awakenScrollBars(int startDelay) {
   12515         return awakenScrollBars(startDelay, true);
   12516     }
   12517 
   12518     /**
   12519      * <p>
   12520      * Trigger the scrollbars to draw. When invoked this method starts an
   12521      * animation to fade the scrollbars out after a fixed delay. If a subclass
   12522      * provides animated scrolling, the start delay should equal the duration of
   12523      * the scrolling animation.
   12524      * </p>
   12525      *
   12526      * <p>
   12527      * The animation starts only if at least one of the scrollbars is enabled,
   12528      * as specified by {@link #isHorizontalScrollBarEnabled()} and
   12529      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
   12530      * this method returns true, and false otherwise. If the animation is
   12531      * started, this method calls {@link #invalidate()} if the invalidate parameter
   12532      * is set to true; in that case the caller
   12533      * should not call {@link #invalidate()}.
   12534      * </p>
   12535      *
   12536      * <p>
   12537      * This method should be invoked every time a subclass directly updates the
   12538      * scroll parameters.
   12539      * </p>
   12540      *
   12541      * @param startDelay the delay, in milliseconds, after which the animation
   12542      *        should start; when the delay is 0, the animation starts
   12543      *        immediately
   12544      *
   12545      * @param invalidate Whether this method should call invalidate
   12546      *
   12547      * @return true if the animation is played, false otherwise
   12548      *
   12549      * @see #scrollBy(int, int)
   12550      * @see #scrollTo(int, int)
   12551      * @see #isHorizontalScrollBarEnabled()
   12552      * @see #isVerticalScrollBarEnabled()
   12553      * @see #setHorizontalScrollBarEnabled(boolean)
   12554      * @see #setVerticalScrollBarEnabled(boolean)
   12555      */
   12556     protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
   12557         final ScrollabilityCache scrollCache = mScrollCache;
   12558 
   12559         if (scrollCache == null || !scrollCache.fadeScrollBars) {
   12560             return false;
   12561         }
   12562 
   12563         if (scrollCache.scrollBar == null) {
   12564             scrollCache.scrollBar = new ScrollBarDrawable();
   12565             scrollCache.scrollBar.setCallback(this);
   12566             scrollCache.scrollBar.setState(getDrawableState());
   12567         }
   12568 
   12569         if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
   12570 
   12571             if (invalidate) {
   12572                 // Invalidate to show the scrollbars
   12573                 postInvalidateOnAnimation();
   12574             }
   12575 
   12576             if (scrollCache.state == ScrollabilityCache.OFF) {
   12577                 // FIXME: this is copied from WindowManagerService.
   12578                 // We should get this value from the system when it
   12579                 // is possible to do so.
   12580                 final int KEY_REPEAT_FIRST_DELAY = 750;
   12581                 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
   12582             }
   12583 
   12584             // Tell mScrollCache when we should start fading. This may
   12585             // extend the fade start time if one was already scheduled
   12586             long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
   12587             scrollCache.fadeStartTime = fadeStartTime;
   12588             scrollCache.state = ScrollabilityCache.ON;
   12589 
   12590             // Schedule our fader to run, unscheduling any old ones first
   12591             if (mAttachInfo != null) {
   12592                 mAttachInfo.mHandler.removeCallbacks(scrollCache);
   12593                 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
   12594             }
   12595 
   12596             return true;
   12597         }
   12598 
   12599         return false;
   12600     }
   12601 
   12602     /**
   12603      * Do not invalidate views which are not visible and which are not running an animation. They
   12604      * will not get drawn and they should not set dirty flags as if they will be drawn
   12605      */
   12606     private boolean skipInvalidate() {
   12607         return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
   12608                 (!(mParent instanceof ViewGroup) ||
   12609                         !((ViewGroup) mParent).isViewTransitioning(this));
   12610     }
   12611 
   12612     /**
   12613      * Mark the area defined by dirty as needing to be drawn. If the view is
   12614      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
   12615      * point in the future.
   12616      * <p>
   12617      * This must be called from a UI thread. To call from a non-UI thread, call
   12618      * {@link #postInvalidate()}.
   12619      * <p>
   12620      * <b>WARNING:</b> In API 19 and below, this method may be destructive to
   12621      * {@code dirty}.
   12622      *
   12623      * @param dirty the rectangle representing the bounds of the dirty region
   12624      */
   12625     public void invalidate(Rect dirty) {
   12626         final int scrollX = mScrollX;
   12627         final int scrollY = mScrollY;
   12628         invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
   12629                 dirty.right - scrollX, dirty.bottom - scrollY, true, false);
   12630     }
   12631 
   12632     /**
   12633      * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
   12634      * coordinates of the dirty rect are relative to the view. If the view is
   12635      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
   12636      * point in the future.
   12637      * <p>
   12638      * This must be called from a UI thread. To call from a non-UI thread, call
   12639      * {@link #postInvalidate()}.
   12640      *
   12641      * @param l the left position of the dirty region
   12642      * @param t the top position of the dirty region
   12643      * @param r the right position of the dirty region
   12644      * @param b the bottom position of the dirty region
   12645      */
   12646     public void invalidate(int l, int t, int r, int b) {
   12647         final int scrollX = mScrollX;
   12648         final int scrollY = mScrollY;
   12649         invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
   12650     }
   12651 
   12652     /**
   12653      * Invalidate the whole view. If the view is visible,
   12654      * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
   12655      * the future.
   12656      * <p>
   12657      * This must be called from a UI thread. To call from a non-UI thread, call
   12658      * {@link #postInvalidate()}.
   12659      */
   12660     public void invalidate() {
   12661         invalidate(true);
   12662     }
   12663 
   12664     /**
   12665      * This is where the invalidate() work actually happens. A full invalidate()
   12666      * causes the drawing cache to be invalidated, but this function can be
   12667      * called with invalidateCache set to false to skip that invalidation step
   12668      * for cases that do not need it (for example, a component that remains at
   12669      * the same dimensions with the same content).
   12670      *
   12671      * @param invalidateCache Whether the drawing cache for this view should be
   12672      *            invalidated as well. This is usually true for a full
   12673      *            invalidate, but may be set to false if the View's contents or
   12674      *            dimensions have not changed.
   12675      */
   12676     void invalidate(boolean invalidateCache) {
   12677         invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
   12678     }
   12679 
   12680     void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
   12681             boolean fullInvalidate) {
   12682         if (mGhostView != null) {
   12683             mGhostView.invalidate(true);
   12684             return;
   12685         }
   12686 
   12687         if (skipInvalidate()) {
   12688             return;
   12689         }
   12690 
   12691         if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
   12692                 || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
   12693                 || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
   12694                 || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
   12695             if (fullInvalidate) {
   12696                 mLastIsOpaque = isOpaque();
   12697                 mPrivateFlags &= ~PFLAG_DRAWN;
   12698             }
   12699 
   12700             mPrivateFlags |= PFLAG_DIRTY;
   12701 
   12702             if (invalidateCache) {
   12703                 mPrivateFlags |= PFLAG_INVALIDATED;
   12704                 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
   12705             }
   12706 
   12707             // Propagate the damage rectangle to the parent view.
   12708             final AttachInfo ai = mAttachInfo;
   12709             final ViewParent p = mParent;
   12710             if (p != null && ai != null && l < r && t < b) {
   12711                 final Rect damage = ai.mTmpInvalRect;
   12712                 damage.set(l, t, r, b);
   12713                 p.invalidateChild(this, damage);
   12714             }
   12715 
   12716             // Damage the entire projection receiver, if necessary.
   12717             if (mBackground != null && mBackground.isProjected()) {
   12718                 final View receiver = getProjectionReceiver();
   12719                 if (receiver != null) {
   12720                     receiver.damageInParent();
   12721                 }
   12722             }
   12723 
   12724             // Damage the entire IsolatedZVolume receiving this view's shadow.
   12725             if (isHardwareAccelerated() && getZ() != 0) {
   12726                 damageShadowReceiver();
   12727             }
   12728         }
   12729     }
   12730 
   12731     /**
   12732      * @return this view's projection receiver, or {@code null} if none exists
   12733      */
   12734     private View getProjectionReceiver() {
   12735         ViewParent p = getParent();
   12736         while (p != null && p instanceof View) {
   12737             final View v = (View) p;
   12738             if (v.isProjectionReceiver()) {
   12739                 return v;
   12740             }
   12741             p = p.getParent();
   12742         }
   12743 
   12744         return null;
   12745     }
   12746 
   12747     /**
   12748      * @return whether the view is a projection receiver
   12749      */
   12750     private boolean isProjectionReceiver() {
   12751         return mBackground != null;
   12752     }
   12753 
   12754     /**
   12755      * Damage area of the screen that can be covered by this View's shadow.
   12756      *
   12757      * This method will guarantee that any changes to shadows cast by a View
   12758      * are damaged on the screen for future redraw.
   12759      */
   12760     private void damageShadowReceiver() {
   12761         final AttachInfo ai = mAttachInfo;
   12762         if (ai != null) {
   12763             ViewParent p = getParent();
   12764             if (p != null && p instanceof ViewGroup) {
   12765                 final ViewGroup vg = (ViewGroup) p;
   12766                 vg.damageInParent();
   12767             }
   12768         }
   12769     }
   12770 
   12771     /**
   12772      * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
   12773      * set any flags or handle all of the cases handled by the default invalidation methods.
   12774      * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
   12775      * dirty rect. This method calls into fast invalidation methods in ViewGroup that
   12776      * walk up the hierarchy, transforming the dirty rect as necessary.
   12777      *
   12778      * The method also handles normal invalidation logic if display list properties are not
   12779      * being used in this view. The invalidateParent and forceRedraw flags are used by that
   12780      * backup approach, to handle these cases used in the various property-setting methods.
   12781      *
   12782      * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
   12783      * are not being used in this view
   12784      * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
   12785      * list properties are not being used in this view
   12786      */
   12787     void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
   12788         if (!isHardwareAccelerated()
   12789                 || !mRenderNode.isValid()
   12790                 || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
   12791             if (invalidateParent) {
   12792                 invalidateParentCaches();
   12793             }
   12794             if (forceRedraw) {
   12795                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
   12796             }
   12797             invalidate(false);
   12798         } else {
   12799             damageInParent();
   12800         }
   12801         if (isHardwareAccelerated() && invalidateParent && getZ() != 0) {
   12802             damageShadowReceiver();
   12803         }
   12804     }
   12805 
   12806     /**
   12807      * Tells the parent view to damage this view's bounds.
   12808      *
   12809      * @hide
   12810      */
   12811     protected void damageInParent() {
   12812         final AttachInfo ai = mAttachInfo;
   12813         final ViewParent p = mParent;
   12814         if (p != null && ai != null) {
   12815             final Rect r = ai.mTmpInvalRect;
   12816             r.set(0, 0, mRight - mLeft, mBottom - mTop);
   12817             if (mParent instanceof ViewGroup) {
   12818                 ((ViewGroup) mParent).damageChild(this, r);
   12819             } else {
   12820                 mParent.invalidateChild(this, r);
   12821             }
   12822         }
   12823     }
   12824 
   12825     /**
   12826      * Utility method to transform a given Rect by the current matrix of this view.
   12827      */
   12828     void transformRect(final Rect rect) {
   12829         if (!getMatrix().isIdentity()) {
   12830             RectF boundingRect = mAttachInfo.mTmpTransformRect;
   12831             boundingRect.set(rect);
   12832             getMatrix().mapRect(boundingRect);
   12833             rect.set((int) Math.floor(boundingRect.left),
   12834                     (int) Math.floor(boundingRect.top),
   12835                     (int) Math.ceil(boundingRect.right),
   12836                     (int) Math.ceil(boundingRect.bottom));
   12837         }
   12838     }
   12839 
   12840     /**
   12841      * Used to indicate that the parent of this view should clear its caches. This functionality
   12842      * is used to force the parent to rebuild its display list (when hardware-accelerated),
   12843      * which is necessary when various parent-managed properties of the view change, such as
   12844      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
   12845      * clears the parent caches and does not causes an invalidate event.
   12846      *
   12847      * @hide
   12848      */
   12849     protected void invalidateParentCaches() {
   12850         if (mParent instanceof View) {
   12851             ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
   12852         }
   12853     }
   12854 
   12855     /**
   12856      * Used to indicate that the parent of this view should be invalidated. This functionality
   12857      * is used to force the parent to rebuild its display list (when hardware-accelerated),
   12858      * which is necessary when various parent-managed properties of the view change, such as
   12859      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
   12860      * an invalidation event to the parent.
   12861      *
   12862      * @hide
   12863      */
   12864     protected void invalidateParentIfNeeded() {
   12865         if (isHardwareAccelerated() && mParent instanceof View) {
   12866             ((View) mParent).invalidate(true);
   12867         }
   12868     }
   12869 
   12870     /**
   12871      * @hide
   12872      */
   12873     protected void invalidateParentIfNeededAndWasQuickRejected() {
   12874         if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
   12875             // View was rejected last time it was drawn by its parent; this may have changed
   12876             invalidateParentIfNeeded();
   12877         }
   12878     }
   12879 
   12880     /**
   12881      * Indicates whether this View is opaque. An opaque View guarantees that it will
   12882      * draw all the pixels overlapping its bounds using a fully opaque color.
   12883      *
   12884      * Subclasses of View should override this method whenever possible to indicate
   12885      * whether an instance is opaque. Opaque Views are treated in a special way by
   12886      * the View hierarchy, possibly allowing it to perform optimizations during
   12887      * invalidate/draw passes.
   12888      *
   12889      * @return True if this View is guaranteed to be fully opaque, false otherwise.
   12890      */
   12891     @ViewDebug.ExportedProperty(category = "drawing")
   12892     public boolean isOpaque() {
   12893         return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
   12894                 getFinalAlpha() >= 1.0f;
   12895     }
   12896 
   12897     /**
   12898      * @hide
   12899      */
   12900     protected void computeOpaqueFlags() {
   12901         // Opaque if:
   12902         //   - Has a background
   12903         //   - Background is opaque
   12904         //   - Doesn't have scrollbars or scrollbars overlay
   12905 
   12906         if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
   12907             mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
   12908         } else {
   12909             mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
   12910         }
   12911 
   12912         final int flags = mViewFlags;
   12913         if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
   12914                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
   12915                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
   12916             mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
   12917         } else {
   12918             mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
   12919         }
   12920     }
   12921 
   12922     /**
   12923      * @hide
   12924      */
   12925     protected boolean hasOpaqueScrollbars() {
   12926         return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
   12927     }
   12928 
   12929     /**
   12930      * @return A handler associated with the thread running the View. This
   12931      * handler can be used to pump events in the UI events queue.
   12932      */
   12933     public Handler getHandler() {
   12934         final AttachInfo attachInfo = mAttachInfo;
   12935         if (attachInfo != null) {
   12936             return attachInfo.mHandler;
   12937         }
   12938         return null;
   12939     }
   12940 
   12941     /**
   12942      * Gets the view root associated with the View.
   12943      * @return The view root, or null if none.
   12944      * @hide
   12945      */
   12946     public ViewRootImpl getViewRootImpl() {
   12947         if (mAttachInfo != null) {
   12948             return mAttachInfo.mViewRootImpl;
   12949         }
   12950         return null;
   12951     }
   12952 
   12953     /**
   12954      * @hide
   12955      */
   12956     public HardwareRenderer getHardwareRenderer() {
   12957         return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null;
   12958     }
   12959 
   12960     /**
   12961      * <p>Causes the Runnable to be added to the message queue.
   12962      * The runnable will be run on the user interface thread.</p>
   12963      *
   12964      * @param action The Runnable that will be executed.
   12965      *
   12966      * @return Returns true if the Runnable was successfully placed in to the
   12967      *         message queue.  Returns false on failure, usually because the
   12968      *         looper processing the message queue is exiting.
   12969      *
   12970      * @see #postDelayed
   12971      * @see #removeCallbacks
   12972      */
   12973     public boolean post(Runnable action) {
   12974         final AttachInfo attachInfo = mAttachInfo;
   12975         if (attachInfo != null) {
   12976             return attachInfo.mHandler.post(action);
   12977         }
   12978         // Assume that post will succeed later
   12979         ViewRootImpl.getRunQueue().post(action);
   12980         return true;
   12981     }
   12982 
   12983     /**
   12984      * <p>Causes the Runnable to be added to the message queue, to be run
   12985      * after the specified amount of time elapses.
   12986      * The runnable will be run on the user interface thread.</p>
   12987      *
   12988      * @param action The Runnable that will be executed.
   12989      * @param delayMillis The delay (in milliseconds) until the Runnable
   12990      *        will be executed.
   12991      *
   12992      * @return true if the Runnable was successfully placed in to the
   12993      *         message queue.  Returns false on failure, usually because the
   12994      *         looper processing the message queue is exiting.  Note that a
   12995      *         result of true does not mean the Runnable will be processed --
   12996      *         if the looper is quit before the delivery time of the message
   12997      *         occurs then the message will be dropped.
   12998      *
   12999      * @see #post
   13000      * @see #removeCallbacks
   13001      */
   13002     public boolean postDelayed(Runnable action, long delayMillis) {
   13003         final AttachInfo attachInfo = mAttachInfo;
   13004         if (attachInfo != null) {
   13005             return attachInfo.mHandler.postDelayed(action, delayMillis);
   13006         }
   13007         // Assume that post will succeed later
   13008         ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
   13009         return true;
   13010     }
   13011 
   13012     /**
   13013      * <p>Causes the Runnable to execute on the next animation time step.
   13014      * The runnable will be run on the user interface thread.</p>
   13015      *
   13016      * @param action The Runnable that will be executed.
   13017      *
   13018      * @see #postOnAnimationDelayed
   13019      * @see #removeCallbacks
   13020      */
   13021     public void postOnAnimation(Runnable action) {
   13022         final AttachInfo attachInfo = mAttachInfo;
   13023         if (attachInfo != null) {
   13024             attachInfo.mViewRootImpl.mChoreographer.postCallback(
   13025                     Choreographer.CALLBACK_ANIMATION, action, null);
   13026         } else {
   13027             // Assume that post will succeed later
   13028             ViewRootImpl.getRunQueue().post(action);
   13029         }
   13030     }
   13031 
   13032     /**
   13033      * <p>Causes the Runnable to execute on the next animation time step,
   13034      * after the specified amount of time elapses.
   13035      * The runnable will be run on the user interface thread.</p>
   13036      *
   13037      * @param action The Runnable that will be executed.
   13038      * @param delayMillis The delay (in milliseconds) until the Runnable
   13039      *        will be executed.
   13040      *
   13041      * @see #postOnAnimation
   13042      * @see #removeCallbacks
   13043      */
   13044     public void postOnAnimationDelayed(Runnable action, long delayMillis) {
   13045         final AttachInfo attachInfo = mAttachInfo;
   13046         if (attachInfo != null) {
   13047             attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
   13048                     Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
   13049         } else {
   13050             // Assume that post will succeed later
   13051             ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
   13052         }
   13053     }
   13054 
   13055     /**
   13056      * <p>Removes the specified Runnable from the message queue.</p>
   13057      *
   13058      * @param action The Runnable to remove from the message handling queue
   13059      *
   13060      * @return true if this view could ask the Handler to remove the Runnable,
   13061      *         false otherwise. When the returned value is true, the Runnable
   13062      *         may or may not have been actually removed from the message queue
   13063      *         (for instance, if the Runnable was not in the queue already.)
   13064      *
   13065      * @see #post
   13066      * @see #postDelayed
   13067      * @see #postOnAnimation
   13068      * @see #postOnAnimationDelayed
   13069      */
   13070     public boolean removeCallbacks(Runnable action) {
   13071         if (action != null) {
   13072             final AttachInfo attachInfo = mAttachInfo;
   13073             if (attachInfo != null) {
   13074                 attachInfo.mHandler.removeCallbacks(action);
   13075                 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
   13076                         Choreographer.CALLBACK_ANIMATION, action, null);
   13077             }
   13078             // Assume that post will succeed later
   13079             ViewRootImpl.getRunQueue().removeCallbacks(action);
   13080         }
   13081         return true;
   13082     }
   13083 
   13084     /**
   13085      * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
   13086      * Use this to invalidate the View from a non-UI thread.</p>
   13087      *
   13088      * <p>This method can be invoked from outside of the UI thread
   13089      * only when this View is attached to a window.</p>
   13090      *
   13091      * @see #invalidate()
   13092      * @see #postInvalidateDelayed(long)
   13093      */
   13094     public void postInvalidate() {
   13095         postInvalidateDelayed(0);
   13096     }
   13097 
   13098     /**
   13099      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
   13100      * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
   13101      *
   13102      * <p>This method can be invoked from outside of the UI thread
   13103      * only when this View is attached to a window.</p>
   13104      *
   13105      * @param left The left coordinate of the rectangle to invalidate.
   13106      * @param top The top coordinate of the rectangle to invalidate.
   13107      * @param right The right coordinate of the rectangle to invalidate.
   13108      * @param bottom The bottom coordinate of the rectangle to invalidate.
   13109      *
   13110      * @see #invalidate(int, int, int, int)
   13111      * @see #invalidate(Rect)
   13112      * @see #postInvalidateDelayed(long, int, int, int, int)
   13113      */
   13114     public void postInvalidate(int left, int top, int right, int bottom) {
   13115         postInvalidateDelayed(0, left, top, right, bottom);
   13116     }
   13117 
   13118     /**
   13119      * <p>Cause an invalidate to happen on a subsequent cycle through the event
   13120      * loop. Waits for the specified amount of time.</p>
   13121      *
   13122      * <p>This method can be invoked from outside of the UI thread
   13123      * only when this View is attached to a window.</p>
   13124      *
   13125      * @param delayMilliseconds the duration in milliseconds to delay the
   13126      *         invalidation by
   13127      *
   13128      * @see #invalidate()
   13129      * @see #postInvalidate()
   13130      */
   13131     public void postInvalidateDelayed(long delayMilliseconds) {
   13132         // We try only with the AttachInfo because there's no point in invalidating
   13133         // if we are not attached to our window
   13134         final AttachInfo attachInfo = mAttachInfo;
   13135         if (attachInfo != null) {
   13136             attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
   13137         }
   13138     }
   13139 
   13140     /**
   13141      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
   13142      * through the event loop. Waits for the specified amount of time.</p>
   13143      *
   13144      * <p>This method can be invoked from outside of the UI thread
   13145      * only when this View is attached to a window.</p>
   13146      *
   13147      * @param delayMilliseconds the duration in milliseconds to delay the
   13148      *         invalidation by
   13149      * @param left The left coordinate of the rectangle to invalidate.
   13150      * @param top The top coordinate of the rectangle to invalidate.
   13151      * @param right The right coordinate of the rectangle to invalidate.
   13152      * @param bottom The bottom coordinate of the rectangle to invalidate.
   13153      *
   13154      * @see #invalidate(int, int, int, int)
   13155      * @see #invalidate(Rect)
   13156      * @see #postInvalidate(int, int, int, int)
   13157      */
   13158     public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
   13159             int right, int bottom) {
   13160 
   13161         // We try only with the AttachInfo because there's no point in invalidating
   13162         // if we are not attached to our window
   13163         final AttachInfo attachInfo = mAttachInfo;
   13164         if (attachInfo != null) {
   13165             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
   13166             info.target = this;
   13167             info.left = left;
   13168             info.top = top;
   13169             info.right = right;
   13170             info.bottom = bottom;
   13171 
   13172             attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
   13173         }
   13174     }
   13175 
   13176     /**
   13177      * <p>Cause an invalidate to happen on the next animation time step, typically the
   13178      * next display frame.</p>
   13179      *
   13180      * <p>This method can be invoked from outside of the UI thread
   13181      * only when this View is attached to a window.</p>
   13182      *
   13183      * @see #invalidate()
   13184      */
   13185     public void postInvalidateOnAnimation() {
   13186         // We try only with the AttachInfo because there's no point in invalidating
   13187         // if we are not attached to our window
   13188         final AttachInfo attachInfo = mAttachInfo;
   13189         if (attachInfo != null) {
   13190             attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
   13191         }
   13192     }
   13193 
   13194     /**
   13195      * <p>Cause an invalidate of the specified area to happen on the next animation
   13196      * time step, typically the next display frame.</p>
   13197      *
   13198      * <p>This method can be invoked from outside of the UI thread
   13199      * only when this View is attached to a window.</p>
   13200      *
   13201      * @param left The left coordinate of the rectangle to invalidate.
   13202      * @param top The top coordinate of the rectangle to invalidate.
   13203      * @param right The right coordinate of the rectangle to invalidate.
   13204      * @param bottom The bottom coordinate of the rectangle to invalidate.
   13205      *
   13206      * @see #invalidate(int, int, int, int)
   13207      * @see #invalidate(Rect)
   13208      */
   13209     public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
   13210         // We try only with the AttachInfo because there's no point in invalidating
   13211         // if we are not attached to our window
   13212         final AttachInfo attachInfo = mAttachInfo;
   13213         if (attachInfo != null) {
   13214             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
   13215             info.target = this;
   13216             info.left = left;
   13217             info.top = top;
   13218             info.right = right;
   13219             info.bottom = bottom;
   13220 
   13221             attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
   13222         }
   13223     }
   13224 
   13225     /**
   13226      * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
   13227      * This event is sent at most once every
   13228      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
   13229      */
   13230     private void postSendViewScrolledAccessibilityEventCallback() {
   13231         if (mSendViewScrolledAccessibilityEvent == null) {
   13232             mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
   13233         }
   13234         if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
   13235             mSendViewScrolledAccessibilityEvent.mIsPending = true;
   13236             postDelayed(mSendViewScrolledAccessibilityEvent,
   13237                     ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
   13238         }
   13239     }
   13240 
   13241     /**
   13242      * Called by a parent to request that a child update its values for mScrollX
   13243      * and mScrollY if necessary. This will typically be done if the child is
   13244      * animating a scroll using a {@link android.widget.Scroller Scroller}
   13245      * object.
   13246      */
   13247     public void computeScroll() {
   13248     }
   13249 
   13250     /**
   13251      * <p>Indicate whether the horizontal edges are faded when the view is
   13252      * scrolled horizontally.</p>
   13253      *
   13254      * @return true if the horizontal edges should are faded on scroll, false
   13255      *         otherwise
   13256      *
   13257      * @see #setHorizontalFadingEdgeEnabled(boolean)
   13258      *
   13259      * @attr ref android.R.styleable#View_requiresFadingEdge
   13260      */
   13261     public boolean isHorizontalFadingEdgeEnabled() {
   13262         return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
   13263     }
   13264 
   13265     /**
   13266      * <p>Define whether the horizontal edges should be faded when this view
   13267      * is scrolled horizontally.</p>
   13268      *
   13269      * @param horizontalFadingEdgeEnabled true if the horizontal edges should
   13270      *                                    be faded when the view is scrolled
   13271      *                                    horizontally
   13272      *
   13273      * @see #isHorizontalFadingEdgeEnabled()
   13274      *
   13275      * @attr ref android.R.styleable#View_requiresFadingEdge
   13276      */
   13277     public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
   13278         if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
   13279             if (horizontalFadingEdgeEnabled) {
   13280                 initScrollCache();
   13281             }
   13282 
   13283             mViewFlags ^= FADING_EDGE_HORIZONTAL;
   13284         }
   13285     }
   13286 
   13287     /**
   13288      * <p>Indicate whether the vertical edges are faded when the view is
   13289      * scrolled horizontally.</p>
   13290      *
   13291      * @return true if the vertical edges should are faded on scroll, false
   13292      *         otherwise
   13293      *
   13294      * @see #setVerticalFadingEdgeEnabled(boolean)
   13295      *
   13296      * @attr ref android.R.styleable#View_requiresFadingEdge
   13297      */
   13298     public boolean isVerticalFadingEdgeEnabled() {
   13299         return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
   13300     }
   13301 
   13302     /**
   13303      * <p>Define whether the vertical edges should be faded when this view
   13304      * is scrolled vertically.</p>
   13305      *
   13306      * @param verticalFadingEdgeEnabled true if the vertical edges should
   13307      *                                  be faded when the view is scrolled
   13308      *                                  vertically
   13309      *
   13310      * @see #isVerticalFadingEdgeEnabled()
   13311      *
   13312      * @attr ref android.R.styleable#View_requiresFadingEdge
   13313      */
   13314     public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
   13315         if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
   13316             if (verticalFadingEdgeEnabled) {
   13317                 initScrollCache();
   13318             }
   13319 
   13320             mViewFlags ^= FADING_EDGE_VERTICAL;
   13321         }
   13322     }
   13323 
   13324     /**
   13325      * Returns the strength, or intensity, of the top faded edge. The strength is
   13326      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
   13327      * returns 0.0 or 1.0 but no value in between.
   13328      *
   13329      * Subclasses should override this method to provide a smoother fade transition
   13330      * when scrolling occurs.
   13331      *
   13332      * @return the intensity of the top fade as a float between 0.0f and 1.0f
   13333      */
   13334     protected float getTopFadingEdgeStrength() {
   13335         return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
   13336     }
   13337 
   13338     /**
   13339      * Returns the strength, or intensity, of the bottom faded edge. The strength is
   13340      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
   13341      * returns 0.0 or 1.0 but no value in between.
   13342      *
   13343      * Subclasses should override this method to provide a smoother fade transition
   13344      * when scrolling occurs.
   13345      *
   13346      * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
   13347      */
   13348     protected float getBottomFadingEdgeStrength() {
   13349         return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
   13350                 computeVerticalScrollRange() ? 1.0f : 0.0f;
   13351     }
   13352 
   13353     /**
   13354      * Returns the strength, or intensity, of the left faded edge. The strength is
   13355      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
   13356      * returns 0.0 or 1.0 but no value in between.
   13357      *
   13358      * Subclasses should override this method to provide a smoother fade transition
   13359      * when scrolling occurs.
   13360      *
   13361      * @return the intensity of the left fade as a float between 0.0f and 1.0f
   13362      */
   13363     protected float getLeftFadingEdgeStrength() {
   13364         return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
   13365     }
   13366 
   13367     /**
   13368      * Returns the strength, or intensity, of the right faded edge. The strength is
   13369      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
   13370      * returns 0.0 or 1.0 but no value in between.
   13371      *
   13372      * Subclasses should override this method to provide a smoother fade transition
   13373      * when scrolling occurs.
   13374      *
   13375      * @return the intensity of the right fade as a float between 0.0f and 1.0f
   13376      */
   13377     protected float getRightFadingEdgeStrength() {
   13378         return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
   13379                 computeHorizontalScrollRange() ? 1.0f : 0.0f;
   13380     }
   13381 
   13382     /**
   13383      * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
   13384      * scrollbar is not drawn by default.</p>
   13385      *
   13386      * @return true if the horizontal scrollbar should be painted, false
   13387      *         otherwise
   13388      *
   13389      * @see #setHorizontalScrollBarEnabled(boolean)
   13390      */
   13391     public boolean isHorizontalScrollBarEnabled() {
   13392         return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
   13393     }
   13394 
   13395     /**
   13396      * <p>Define whether the horizontal scrollbar should be drawn or not. The
   13397      * scrollbar is not drawn by default.</p>
   13398      *
   13399      * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
   13400      *                                   be painted
   13401      *
   13402      * @see #isHorizontalScrollBarEnabled()
   13403      */
   13404     public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
   13405         if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
   13406             mViewFlags ^= SCROLLBARS_HORIZONTAL;
   13407             computeOpaqueFlags();
   13408             resolvePadding();
   13409         }
   13410     }
   13411 
   13412     /**
   13413      * <p>Indicate whether the vertical scrollbar should be drawn or not. The
   13414      * scrollbar is not drawn by default.</p>
   13415      *
   13416      * @return true if the vertical scrollbar should be painted, false
   13417      *         otherwise
   13418      *
   13419      * @see #setVerticalScrollBarEnabled(boolean)
   13420      */
   13421     public boolean isVerticalScrollBarEnabled() {
   13422         return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
   13423     }
   13424 
   13425     /**
   13426      * <p>Define whether the vertical scrollbar should be drawn or not. The
   13427      * scrollbar is not drawn by default.</p>
   13428      *
   13429      * @param verticalScrollBarEnabled true if the vertical scrollbar should
   13430      *                                 be painted
   13431      *
   13432      * @see #isVerticalScrollBarEnabled()
   13433      */
   13434     public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
   13435         if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
   13436             mViewFlags ^= SCROLLBARS_VERTICAL;
   13437             computeOpaqueFlags();
   13438             resolvePadding();
   13439         }
   13440     }
   13441 
   13442     /**
   13443      * @hide
   13444      */
   13445     protected void recomputePadding() {
   13446         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
   13447     }
   13448 
   13449     /**
   13450      * Define whether scrollbars will fade when the view is not scrolling.
   13451      *
   13452      * @param fadeScrollbars whether to enable fading
   13453      *
   13454      * @attr ref android.R.styleable#View_fadeScrollbars
   13455      */
   13456     public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
   13457         initScrollCache();
   13458         final ScrollabilityCache scrollabilityCache = mScrollCache;
   13459         scrollabilityCache.fadeScrollBars = fadeScrollbars;
   13460         if (fadeScrollbars) {
   13461             scrollabilityCache.state = ScrollabilityCache.OFF;
   13462         } else {
   13463             scrollabilityCache.state = ScrollabilityCache.ON;
   13464         }
   13465     }
   13466 
   13467     /**
   13468      *
   13469      * Returns true if scrollbars will fade when this view is not scrolling
   13470      *
   13471      * @return true if scrollbar fading is enabled
   13472      *
   13473      * @attr ref android.R.styleable#View_fadeScrollbars
   13474      */
   13475     public boolean isScrollbarFadingEnabled() {
   13476         return mScrollCache != null && mScrollCache.fadeScrollBars;
   13477     }
   13478 
   13479     /**
   13480      *
   13481      * Returns the delay before scrollbars fade.
   13482      *
   13483      * @return the delay before scrollbars fade
   13484      *
   13485      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
   13486      */
   13487     public int getScrollBarDefaultDelayBeforeFade() {
   13488         return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
   13489                 mScrollCache.scrollBarDefaultDelayBeforeFade;
   13490     }
   13491 
   13492     /**
   13493      * Define the delay before scrollbars fade.
   13494      *
   13495      * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
   13496      *
   13497      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
   13498      */
   13499     public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
   13500         getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
   13501     }
   13502 
   13503     /**
   13504      *
   13505      * Returns the scrollbar fade duration.
   13506      *
   13507      * @return the scrollbar fade duration
   13508      *
   13509      * @attr ref android.R.styleable#View_scrollbarFadeDuration
   13510      */
   13511     public int getScrollBarFadeDuration() {
   13512         return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
   13513                 mScrollCache.scrollBarFadeDuration;
   13514     }
   13515 
   13516     /**
   13517      * Define the scrollbar fade duration.
   13518      *
   13519      * @param scrollBarFadeDuration - the scrollbar fade duration
   13520      *
   13521      * @attr ref android.R.styleable#View_scrollbarFadeDuration
   13522      */
   13523     public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
   13524         getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
   13525     }
   13526 
   13527     /**
   13528      *
   13529      * Returns the scrollbar size.
   13530      *
   13531      * @return the scrollbar size
   13532      *
   13533      * @attr ref android.R.styleable#View_scrollbarSize
   13534      */
   13535     public int getScrollBarSize() {
   13536         return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
   13537                 mScrollCache.scrollBarSize;
   13538     }
   13539 
   13540     /**
   13541      * Define the scrollbar size.
   13542      *
   13543      * @param scrollBarSize - the scrollbar size
   13544      *
   13545      * @attr ref android.R.styleable#View_scrollbarSize
   13546      */
   13547     public void setScrollBarSize(int scrollBarSize) {
   13548         getScrollCache().scrollBarSize = scrollBarSize;
   13549     }
   13550 
   13551     /**
   13552      * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
   13553      * inset. When inset, they add to the padding of the view. And the scrollbars
   13554      * can be drawn inside the padding area or on the edge of the view. For example,
   13555      * if a view has a background drawable and you want to draw the scrollbars
   13556      * inside the padding specified by the drawable, you can use
   13557      * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
   13558      * appear at the edge of the view, ignoring the padding, then you can use
   13559      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
   13560      * @param style the style of the scrollbars. Should be one of
   13561      * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
   13562      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
   13563      * @see #SCROLLBARS_INSIDE_OVERLAY
   13564      * @see #SCROLLBARS_INSIDE_INSET
   13565      * @see #SCROLLBARS_OUTSIDE_OVERLAY
   13566      * @see #SCROLLBARS_OUTSIDE_INSET
   13567      *
   13568      * @attr ref android.R.styleable#View_scrollbarStyle
   13569      */
   13570     public void setScrollBarStyle(@ScrollBarStyle int style) {
   13571         if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
   13572             mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
   13573             computeOpaqueFlags();
   13574             resolvePadding();
   13575         }
   13576     }
   13577 
   13578     /**
   13579      * <p>Returns the current scrollbar style.</p>
   13580      * @return the current scrollbar style
   13581      * @see #SCROLLBARS_INSIDE_OVERLAY
   13582      * @see #SCROLLBARS_INSIDE_INSET
   13583      * @see #SCROLLBARS_OUTSIDE_OVERLAY
   13584      * @see #SCROLLBARS_OUTSIDE_INSET
   13585      *
   13586      * @attr ref android.R.styleable#View_scrollbarStyle
   13587      */
   13588     @ViewDebug.ExportedProperty(mapping = {
   13589             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
   13590             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
   13591             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
   13592             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
   13593     })
   13594     @ScrollBarStyle
   13595     public int getScrollBarStyle() {
   13596         return mViewFlags & SCROLLBARS_STYLE_MASK;
   13597     }
   13598 
   13599     /**
   13600      * <p>Compute the horizontal range that the horizontal scrollbar
   13601      * represents.</p>
   13602      *
   13603      * <p>The range is expressed in arbitrary units that must be the same as the
   13604      * units used by {@link #computeHorizontalScrollExtent()} and
   13605      * {@link #computeHorizontalScrollOffset()}.</p>
   13606      *
   13607      * <p>The default range is the drawing width of this view.</p>
   13608      *
   13609      * @return the total horizontal range represented by the horizontal
   13610      *         scrollbar
   13611      *
   13612      * @see #computeHorizontalScrollExtent()
   13613      * @see #computeHorizontalScrollOffset()
   13614      * @see android.widget.ScrollBarDrawable
   13615      */
   13616     protected int computeHorizontalScrollRange() {
   13617         return getWidth();
   13618     }
   13619 
   13620     /**
   13621      * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
   13622      * within the horizontal range. This value is used to compute the position
   13623      * of the thumb within the scrollbar's track.</p>
   13624      *
   13625      * <p>The range is expressed in arbitrary units that must be the same as the
   13626      * units used by {@link #computeHorizontalScrollRange()} and
   13627      * {@link #computeHorizontalScrollExtent()}.</p>
   13628      *
   13629      * <p>The default offset is the scroll offset of this view.</p>
   13630      *
   13631      * @return the horizontal offset of the scrollbar's thumb
   13632      *
   13633      * @see #computeHorizontalScrollRange()
   13634      * @see #computeHorizontalScrollExtent()
   13635      * @see android.widget.ScrollBarDrawable
   13636      */
   13637     protected int computeHorizontalScrollOffset() {
   13638         return mScrollX;
   13639     }
   13640 
   13641     /**
   13642      * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
   13643      * within the horizontal range. This value is used to compute the length
   13644      * of the thumb within the scrollbar's track.</p>
   13645      *
   13646      * <p>The range is expressed in arbitrary units that must be the same as the
   13647      * units used by {@link #computeHorizontalScrollRange()} and
   13648      * {@link #computeHorizontalScrollOffset()}.</p>
   13649      *
   13650      * <p>The default extent is the drawing width of this view.</p>
   13651      *
   13652      * @return the horizontal extent of the scrollbar's thumb
   13653      *
   13654      * @see #computeHorizontalScrollRange()
   13655      * @see #computeHorizontalScrollOffset()
   13656      * @see android.widget.ScrollBarDrawable
   13657      */
   13658     protected int computeHorizontalScrollExtent() {
   13659         return getWidth();
   13660     }
   13661 
   13662     /**
   13663      * <p>Compute the vertical range that the vertical scrollbar represents.</p>
   13664      *
   13665      * <p>The range is expressed in arbitrary units that must be the same as the
   13666      * units used by {@link #computeVerticalScrollExtent()} and
   13667      * {@link #computeVerticalScrollOffset()}.</p>
   13668      *
   13669      * @return the total vertical range represented by the vertical scrollbar
   13670      *
   13671      * <p>The default range is the drawing height of this view.</p>
   13672      *
   13673      * @see #computeVerticalScrollExtent()
   13674      * @see #computeVerticalScrollOffset()
   13675      * @see android.widget.ScrollBarDrawable
   13676      */
   13677     protected int computeVerticalScrollRange() {
   13678         return getHeight();
   13679     }
   13680 
   13681     /**
   13682      * <p>Compute the vertical offset of the vertical scrollbar's thumb
   13683      * within the horizontal range. This value is used to compute the position
   13684      * of the thumb within the scrollbar's track.</p>
   13685      *
   13686      * <p>The range is expressed in arbitrary units that must be the same as the
   13687      * units used by {@link #computeVerticalScrollRange()} and
   13688      * {@link #computeVerticalScrollExtent()}.</p>
   13689      *
   13690      * <p>The default offset is the scroll offset of this view.</p>
   13691      *
   13692      * @return the vertical offset of the scrollbar's thumb
   13693      *
   13694      * @see #computeVerticalScrollRange()
   13695      * @see #computeVerticalScrollExtent()
   13696      * @see android.widget.ScrollBarDrawable
   13697      */
   13698     protected int computeVerticalScrollOffset() {
   13699         return mScrollY;
   13700     }
   13701 
   13702     /**
   13703      * <p>Compute the vertical extent of the vertical scrollbar's thumb
   13704      * within the vertical range. This value is used to compute the length
   13705      * of the thumb within the scrollbar's track.</p>
   13706      *
   13707      * <p>The range is expressed in arbitrary units that must be the same as the
   13708      * units used by {@link #computeVerticalScrollRange()} and
   13709      * {@link #computeVerticalScrollOffset()}.</p>
   13710      *
   13711      * <p>The default extent is the drawing height of this view.</p>
   13712      *
   13713      * @return the vertical extent of the scrollbar's thumb
   13714      *
   13715      * @see #computeVerticalScrollRange()
   13716      * @see #computeVerticalScrollOffset()
   13717      * @see android.widget.ScrollBarDrawable
   13718      */
   13719     protected int computeVerticalScrollExtent() {
   13720         return getHeight();
   13721     }
   13722 
   13723     /**
   13724      * Check if this view can be scrolled horizontally in a certain direction.
   13725      *
   13726      * @param direction Negative to check scrolling left, positive to check scrolling right.
   13727      * @return true if this view can be scrolled in the specified direction, false otherwise.
   13728      */
   13729     public boolean canScrollHorizontally(int direction) {
   13730         final int offset = computeHorizontalScrollOffset();
   13731         final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
   13732         if (range == 0) return false;
   13733         if (direction < 0) {
   13734             return offset > 0;
   13735         } else {
   13736             return offset < range - 1;
   13737         }
   13738     }
   13739 
   13740     /**
   13741      * Check if this view can be scrolled vertically in a certain direction.
   13742      *
   13743      * @param direction Negative to check scrolling up, positive to check scrolling down.
   13744      * @return true if this view can be scrolled in the specified direction, false otherwise.
   13745      */
   13746     public boolean canScrollVertically(int direction) {
   13747         final int offset = computeVerticalScrollOffset();
   13748         final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
   13749         if (range == 0) return false;
   13750         if (direction < 0) {
   13751             return offset > 0;
   13752         } else {
   13753             return offset < range - 1;
   13754         }
   13755     }
   13756 
   13757     void getScrollIndicatorBounds(@NonNull Rect out) {
   13758         out.left = mScrollX;
   13759         out.right = mScrollX + mRight - mLeft;
   13760         out.top = mScrollY;
   13761         out.bottom = mScrollY + mBottom - mTop;
   13762     }
   13763 
   13764     private void onDrawScrollIndicators(Canvas c) {
   13765         if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
   13766             // No scroll indicators enabled.
   13767             return;
   13768         }
   13769 
   13770         final Drawable dr = mScrollIndicatorDrawable;
   13771         if (dr == null) {
   13772             // Scroll indicators aren't supported here.
   13773             return;
   13774         }
   13775 
   13776         final int h = dr.getIntrinsicHeight();
   13777         final int w = dr.getIntrinsicWidth();
   13778         final Rect rect = mAttachInfo.mTmpInvalRect;
   13779         getScrollIndicatorBounds(rect);
   13780 
   13781         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
   13782             final boolean canScrollUp = canScrollVertically(-1);
   13783             if (canScrollUp) {
   13784                 dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
   13785                 dr.draw(c);
   13786             }
   13787         }
   13788 
   13789         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
   13790             final boolean canScrollDown = canScrollVertically(1);
   13791             if (canScrollDown) {
   13792                 dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
   13793                 dr.draw(c);
   13794             }
   13795         }
   13796 
   13797         final int leftRtl;
   13798         final int rightRtl;
   13799         if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
   13800             leftRtl = PFLAG3_SCROLL_INDICATOR_END;
   13801             rightRtl = PFLAG3_SCROLL_INDICATOR_START;
   13802         } else {
   13803             leftRtl = PFLAG3_SCROLL_INDICATOR_START;
   13804             rightRtl = PFLAG3_SCROLL_INDICATOR_END;
   13805         }
   13806 
   13807         final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
   13808         if ((mPrivateFlags3 & leftMask) != 0) {
   13809             final boolean canScrollLeft = canScrollHorizontally(-1);
   13810             if (canScrollLeft) {
   13811                 dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
   13812                 dr.draw(c);
   13813             }
   13814         }
   13815 
   13816         final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
   13817         if ((mPrivateFlags3 & rightMask) != 0) {
   13818             final boolean canScrollRight = canScrollHorizontally(1);
   13819             if (canScrollRight) {
   13820                 dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
   13821                 dr.draw(c);
   13822             }
   13823         }
   13824     }
   13825 
   13826     /**
   13827      * <p>Request the drawing of the horizontal and the vertical scrollbar. The
   13828      * scrollbars are painted only if they have been awakened first.</p>
   13829      *
   13830      * @param canvas the canvas on which to draw the scrollbars
   13831      *
   13832      * @see #awakenScrollBars(int)
   13833      */
   13834     protected final void onDrawScrollBars(Canvas canvas) {
   13835         // scrollbars are drawn only when the animation is running
   13836         final ScrollabilityCache cache = mScrollCache;
   13837         if (cache != null) {
   13838 
   13839             int state = cache.state;
   13840 
   13841             if (state == ScrollabilityCache.OFF) {
   13842                 return;
   13843             }
   13844 
   13845             boolean invalidate = false;
   13846 
   13847             if (state == ScrollabilityCache.FADING) {
   13848                 // We're fading -- get our fade interpolation
   13849                 if (cache.interpolatorValues == null) {
   13850                     cache.interpolatorValues = new float[1];
   13851                 }
   13852 
   13853                 float[] values = cache.interpolatorValues;
   13854 
   13855                 // Stops the animation if we're done
   13856                 if (cache.scrollBarInterpolator.timeToValues(values) ==
   13857                         Interpolator.Result.FREEZE_END) {
   13858                     cache.state = ScrollabilityCache.OFF;
   13859                 } else {
   13860                     cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
   13861                 }
   13862 
   13863                 // This will make the scroll bars inval themselves after
   13864                 // drawing. We only want this when we're fading so that
   13865                 // we prevent excessive redraws
   13866                 invalidate = true;
   13867             } else {
   13868                 // We're just on -- but we may have been fading before so
   13869                 // reset alpha
   13870                 cache.scrollBar.mutate().setAlpha(255);
   13871             }
   13872 
   13873 
   13874             final int viewFlags = mViewFlags;
   13875 
   13876             final boolean drawHorizontalScrollBar =
   13877                 (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
   13878             final boolean drawVerticalScrollBar =
   13879                 (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
   13880                 && !isVerticalScrollBarHidden();
   13881 
   13882             if (drawVerticalScrollBar || drawHorizontalScrollBar) {
   13883                 final int width = mRight - mLeft;
   13884                 final int height = mBottom - mTop;
   13885 
   13886                 final ScrollBarDrawable scrollBar = cache.scrollBar;
   13887 
   13888                 final int scrollX = mScrollX;
   13889                 final int scrollY = mScrollY;
   13890                 final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
   13891 
   13892                 int left;
   13893                 int top;
   13894                 int right;
   13895                 int bottom;
   13896 
   13897                 if (drawHorizontalScrollBar) {
   13898                     int size = scrollBar.getSize(false);
   13899                     if (size <= 0) {
   13900                         size = cache.scrollBarSize;
   13901                     }
   13902 
   13903                     scrollBar.setParameters(computeHorizontalScrollRange(),
   13904                                             computeHorizontalScrollOffset(),
   13905                                             computeHorizontalScrollExtent(), false);
   13906                     final int verticalScrollBarGap = drawVerticalScrollBar ?
   13907                             getVerticalScrollbarWidth() : 0;
   13908                     top = scrollY + height - size - (mUserPaddingBottom & inside);
   13909                     left = scrollX + (mPaddingLeft & inside);
   13910                     right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
   13911                     bottom = top + size;
   13912                     onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
   13913                     if (invalidate) {
   13914                         invalidate(left, top, right, bottom);
   13915                     }
   13916                 }
   13917 
   13918                 if (drawVerticalScrollBar) {
   13919                     int size = scrollBar.getSize(true);
   13920                     if (size <= 0) {
   13921                         size = cache.scrollBarSize;
   13922                     }
   13923 
   13924                     scrollBar.setParameters(computeVerticalScrollRange(),
   13925                                             computeVerticalScrollOffset(),
   13926                                             computeVerticalScrollExtent(), true);
   13927                     int verticalScrollbarPosition = mVerticalScrollbarPosition;
   13928                     if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
   13929                         verticalScrollbarPosition = isLayoutRtl() ?
   13930                                 SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
   13931                     }
   13932                     switch (verticalScrollbarPosition) {
   13933                         default:
   13934                         case SCROLLBAR_POSITION_RIGHT:
   13935                             left = scrollX + width - size - (mUserPaddingRight & inside);
   13936                             break;
   13937                         case SCROLLBAR_POSITION_LEFT:
   13938                             left = scrollX + (mUserPaddingLeft & inside);
   13939                             break;
   13940                     }
   13941                     top = scrollY + (mPaddingTop & inside);
   13942                     right = left + size;
   13943                     bottom = scrollY + height - (mUserPaddingBottom & inside);
   13944                     onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
   13945                     if (invalidate) {
   13946                         invalidate(left, top, right, bottom);
   13947                     }
   13948                 }
   13949             }
   13950         }
   13951     }
   13952 
   13953     /**
   13954      * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
   13955      * FastScroller is visible.
   13956      * @return whether to temporarily hide the vertical scrollbar
   13957      * @hide
   13958      */
   13959     protected boolean isVerticalScrollBarHidden() {
   13960         return false;
   13961     }
   13962 
   13963     /**
   13964      * <p>Draw the horizontal scrollbar if
   13965      * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
   13966      *
   13967      * @param canvas the canvas on which to draw the scrollbar
   13968      * @param scrollBar the scrollbar's drawable
   13969      *
   13970      * @see #isHorizontalScrollBarEnabled()
   13971      * @see #computeHorizontalScrollRange()
   13972      * @see #computeHorizontalScrollExtent()
   13973      * @see #computeHorizontalScrollOffset()
   13974      * @see android.widget.ScrollBarDrawable
   13975      * @hide
   13976      */
   13977     protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
   13978             int l, int t, int r, int b) {
   13979         scrollBar.setBounds(l, t, r, b);
   13980         scrollBar.draw(canvas);
   13981     }
   13982 
   13983     /**
   13984      * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
   13985      * returns true.</p>
   13986      *
   13987      * @param canvas the canvas on which to draw the scrollbar
   13988      * @param scrollBar the scrollbar's drawable
   13989      *
   13990      * @see #isVerticalScrollBarEnabled()
   13991      * @see #computeVerticalScrollRange()
   13992      * @see #computeVerticalScrollExtent()
   13993      * @see #computeVerticalScrollOffset()
   13994      * @see android.widget.ScrollBarDrawable
   13995      * @hide
   13996      */
   13997     protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
   13998             int l, int t, int r, int b) {
   13999         scrollBar.setBounds(l, t, r, b);
   14000         scrollBar.draw(canvas);
   14001     }
   14002 
   14003     /**
   14004      * Implement this to do your drawing.
   14005      *
   14006      * @param canvas the canvas on which the background will be drawn
   14007      */
   14008     protected void onDraw(Canvas canvas) {
   14009     }
   14010 
   14011     /*
   14012      * Caller is responsible for calling requestLayout if necessary.
   14013      * (This allows addViewInLayout to not request a new layout.)
   14014      */
   14015     void assignParent(ViewParent parent) {
   14016         if (mParent == null) {
   14017             mParent = parent;
   14018         } else if (parent == null) {
   14019             mParent = null;
   14020         } else {
   14021             throw new RuntimeException("view " + this + " being added, but"
   14022                     + " it already has a parent");
   14023         }
   14024     }
   14025 
   14026     /**
   14027      * This is called when the view is attached to a window.  At this point it
   14028      * has a Surface and will start drawing.  Note that this function is
   14029      * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
   14030      * however it may be called any time before the first onDraw -- including
   14031      * before or after {@link #onMeasure(int, int)}.
   14032      *
   14033      * @see #onDetachedFromWindow()
   14034      */
   14035     @CallSuper
   14036     protected void onAttachedToWindow() {
   14037         if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
   14038             mParent.requestTransparentRegion(this);
   14039         }
   14040 
   14041         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
   14042 
   14043         jumpDrawablesToCurrentState();
   14044 
   14045         resetSubtreeAccessibilityStateChanged();
   14046 
   14047         // rebuild, since Outline not maintained while View is detached
   14048         rebuildOutline();
   14049 
   14050         if (isFocused()) {
   14051             InputMethodManager imm = InputMethodManager.peekInstance();
   14052             if (imm != null) {
   14053                 imm.focusIn(this);
   14054             }
   14055         }
   14056     }
   14057 
   14058     /**
   14059      * Resolve all RTL related properties.
   14060      *
   14061      * @return true if resolution of RTL properties has been done
   14062      *
   14063      * @hide
   14064      */
   14065     public boolean resolveRtlPropertiesIfNeeded() {
   14066         if (!needRtlPropertiesResolution()) return false;
   14067 
   14068         // Order is important here: LayoutDirection MUST be resolved first
   14069         if (!isLayoutDirectionResolved()) {
   14070             resolveLayoutDirection();
   14071             resolveLayoutParams();
   14072         }
   14073         // ... then we can resolve the others properties depending on the resolved LayoutDirection.
   14074         if (!isTextDirectionResolved()) {
   14075             resolveTextDirection();
   14076         }
   14077         if (!isTextAlignmentResolved()) {
   14078             resolveTextAlignment();
   14079         }
   14080         // Should resolve Drawables before Padding because we need the layout direction of the
   14081         // Drawable to correctly resolve Padding.
   14082         if (!areDrawablesResolved()) {
   14083             resolveDrawables();
   14084         }
   14085         if (!isPaddingResolved()) {
   14086             resolvePadding();
   14087         }
   14088         onRtlPropertiesChanged(getLayoutDirection());
   14089         return true;
   14090     }
   14091 
   14092     /**
   14093      * Reset resolution of all RTL related properties.
   14094      *
   14095      * @hide
   14096      */
   14097     public void resetRtlProperties() {
   14098         resetResolvedLayoutDirection();
   14099         resetResolvedTextDirection();
   14100         resetResolvedTextAlignment();
   14101         resetResolvedPadding();
   14102         resetResolvedDrawables();
   14103     }
   14104 
   14105     /**
   14106      * @see #onScreenStateChanged(int)
   14107      */
   14108     void dispatchScreenStateChanged(int screenState) {
   14109         onScreenStateChanged(screenState);
   14110     }
   14111 
   14112     /**
   14113      * This method is called whenever the state of the screen this view is
   14114      * attached to changes. A state change will usually occurs when the screen
   14115      * turns on or off (whether it happens automatically or the user does it
   14116      * manually.)
   14117      *
   14118      * @param screenState The new state of the screen. Can be either
   14119      *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
   14120      */
   14121     public void onScreenStateChanged(int screenState) {
   14122     }
   14123 
   14124     /**
   14125      * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
   14126      */
   14127     private boolean hasRtlSupport() {
   14128         return mContext.getApplicationInfo().hasRtlSupport();
   14129     }
   14130 
   14131     /**
   14132      * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
   14133      * RTL not supported)
   14134      */
   14135     private boolean isRtlCompatibilityMode() {
   14136         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
   14137         return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
   14138     }
   14139 
   14140     /**
   14141      * @return true if RTL properties need resolution.
   14142      *
   14143      */
   14144     private boolean needRtlPropertiesResolution() {
   14145         return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
   14146     }
   14147 
   14148     /**
   14149      * Called when any RTL property (layout direction or text direction or text alignment) has
   14150      * been changed.
   14151      *
   14152      * Subclasses need to override this method to take care of cached information that depends on the
   14153      * resolved layout direction, or to inform child views that inherit their layout direction.
   14154      *
   14155      * The default implementation does nothing.
   14156      *
   14157      * @param layoutDirection the direction of the layout
   14158      *
   14159      * @see #LAYOUT_DIRECTION_LTR
   14160      * @see #LAYOUT_DIRECTION_RTL
   14161      */
   14162     public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
   14163     }
   14164 
   14165     /**
   14166      * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
   14167      * that the parent directionality can and will be resolved before its children.
   14168      *
   14169      * @return true if resolution has been done, false otherwise.
   14170      *
   14171      * @hide
   14172      */
   14173     public boolean resolveLayoutDirection() {
   14174         // Clear any previous layout direction resolution
   14175         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
   14176 
   14177         if (hasRtlSupport()) {
   14178             // Set resolved depending on layout direction
   14179             switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
   14180                     PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
   14181                 case LAYOUT_DIRECTION_INHERIT:
   14182                     // We cannot resolve yet. LTR is by default and let the resolution happen again
   14183                     // later to get the correct resolved value
   14184                     if (!canResolveLayoutDirection()) return false;
   14185 
   14186                     // Parent has not yet resolved, LTR is still the default
   14187                     try {
   14188                         if (!mParent.isLayoutDirectionResolved()) return false;
   14189 
   14190                         if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
   14191                             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
   14192                         }
   14193                     } catch (AbstractMethodError e) {
   14194                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   14195                                 " does not fully implement ViewParent", e);
   14196                     }
   14197                     break;
   14198                 case LAYOUT_DIRECTION_RTL:
   14199                     mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
   14200                     break;
   14201                 case LAYOUT_DIRECTION_LOCALE:
   14202                     if((LAYOUT_DIRECTION_RTL ==
   14203                             TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
   14204                         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
   14205                     }
   14206                     break;
   14207                 default:
   14208                     // Nothing to do, LTR by default
   14209             }
   14210         }
   14211 
   14212         // Set to resolved
   14213         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
   14214         return true;
   14215     }
   14216 
   14217     /**
   14218      * Check if layout direction resolution can be done.
   14219      *
   14220      * @return true if layout direction resolution can be done otherwise return false.
   14221      */
   14222     public boolean canResolveLayoutDirection() {
   14223         switch (getRawLayoutDirection()) {
   14224             case LAYOUT_DIRECTION_INHERIT:
   14225                 if (mParent != null) {
   14226                     try {
   14227                         return mParent.canResolveLayoutDirection();
   14228                     } catch (AbstractMethodError e) {
   14229                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   14230                                 " does not fully implement ViewParent", e);
   14231                     }
   14232                 }
   14233                 return false;
   14234 
   14235             default:
   14236                 return true;
   14237         }
   14238     }
   14239 
   14240     /**
   14241      * Reset the resolved layout direction. Layout direction will be resolved during a call to
   14242      * {@link #onMeasure(int, int)}.
   14243      *
   14244      * @hide
   14245      */
   14246     public void resetResolvedLayoutDirection() {
   14247         // Reset the current resolved bits
   14248         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
   14249     }
   14250 
   14251     /**
   14252      * @return true if the layout direction is inherited.
   14253      *
   14254      * @hide
   14255      */
   14256     public boolean isLayoutDirectionInherited() {
   14257         return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
   14258     }
   14259 
   14260     /**
   14261      * @return true if layout direction has been resolved.
   14262      */
   14263     public boolean isLayoutDirectionResolved() {
   14264         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
   14265     }
   14266 
   14267     /**
   14268      * Return if padding has been resolved
   14269      *
   14270      * @hide
   14271      */
   14272     boolean isPaddingResolved() {
   14273         return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
   14274     }
   14275 
   14276     /**
   14277      * Resolves padding depending on layout direction, if applicable, and
   14278      * recomputes internal padding values to adjust for scroll bars.
   14279      *
   14280      * @hide
   14281      */
   14282     public void resolvePadding() {
   14283         final int resolvedLayoutDirection = getLayoutDirection();
   14284 
   14285         if (!isRtlCompatibilityMode()) {
   14286             // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
   14287             // If start / end padding are defined, they will be resolved (hence overriding) to
   14288             // left / right or right / left depending on the resolved layout direction.
   14289             // If start / end padding are not defined, use the left / right ones.
   14290             if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
   14291                 Rect padding = sThreadLocal.get();
   14292                 if (padding == null) {
   14293                     padding = new Rect();
   14294                     sThreadLocal.set(padding);
   14295                 }
   14296                 mBackground.getPadding(padding);
   14297                 if (!mLeftPaddingDefined) {
   14298                     mUserPaddingLeftInitial = padding.left;
   14299                 }
   14300                 if (!mRightPaddingDefined) {
   14301                     mUserPaddingRightInitial = padding.right;
   14302                 }
   14303             }
   14304             switch (resolvedLayoutDirection) {
   14305                 case LAYOUT_DIRECTION_RTL:
   14306                     if (mUserPaddingStart != UNDEFINED_PADDING) {
   14307                         mUserPaddingRight = mUserPaddingStart;
   14308                     } else {
   14309                         mUserPaddingRight = mUserPaddingRightInitial;
   14310                     }
   14311                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
   14312                         mUserPaddingLeft = mUserPaddingEnd;
   14313                     } else {
   14314                         mUserPaddingLeft = mUserPaddingLeftInitial;
   14315                     }
   14316                     break;
   14317                 case LAYOUT_DIRECTION_LTR:
   14318                 default:
   14319                     if (mUserPaddingStart != UNDEFINED_PADDING) {
   14320                         mUserPaddingLeft = mUserPaddingStart;
   14321                     } else {
   14322                         mUserPaddingLeft = mUserPaddingLeftInitial;
   14323                     }
   14324                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
   14325                         mUserPaddingRight = mUserPaddingEnd;
   14326                     } else {
   14327                         mUserPaddingRight = mUserPaddingRightInitial;
   14328                     }
   14329             }
   14330 
   14331             mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
   14332         }
   14333 
   14334         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
   14335         onRtlPropertiesChanged(resolvedLayoutDirection);
   14336 
   14337         mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
   14338     }
   14339 
   14340     /**
   14341      * Reset the resolved layout direction.
   14342      *
   14343      * @hide
   14344      */
   14345     public void resetResolvedPadding() {
   14346         resetResolvedPaddingInternal();
   14347     }
   14348 
   14349     /**
   14350      * Used when we only want to reset *this* view's padding and not trigger overrides
   14351      * in ViewGroup that reset children too.
   14352      */
   14353     void resetResolvedPaddingInternal() {
   14354         mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
   14355     }
   14356 
   14357     /**
   14358      * This is called when the view is detached from a window.  At this point it
   14359      * no longer has a surface for drawing.
   14360      *
   14361      * @see #onAttachedToWindow()
   14362      */
   14363     @CallSuper
   14364     protected void onDetachedFromWindow() {
   14365     }
   14366 
   14367     /**
   14368      * This is a framework-internal mirror of onDetachedFromWindow() that's called
   14369      * after onDetachedFromWindow().
   14370      *
   14371      * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
   14372      * The super method should be called at the end of the overridden method to ensure
   14373      * subclasses are destroyed first
   14374      *
   14375      * @hide
   14376      */
   14377     @CallSuper
   14378     protected void onDetachedFromWindowInternal() {
   14379         mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
   14380         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
   14381 
   14382         removeUnsetPressCallback();
   14383         removeLongPressCallback();
   14384         removePerformClickCallback();
   14385         removeSendViewScrolledAccessibilityEventCallback();
   14386         stopNestedScroll();
   14387 
   14388         // Anything that started animating right before detach should already
   14389         // be in its final state when re-attached.
   14390         jumpDrawablesToCurrentState();
   14391 
   14392         destroyDrawingCache();
   14393 
   14394         cleanupDraw();
   14395         mCurrentAnimation = null;
   14396     }
   14397 
   14398     private void cleanupDraw() {
   14399         resetDisplayList();
   14400         if (mAttachInfo != null) {
   14401             mAttachInfo.mViewRootImpl.cancelInvalidate(this);
   14402         }
   14403     }
   14404 
   14405     void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
   14406     }
   14407 
   14408     /**
   14409      * @return The number of times this view has been attached to a window
   14410      */
   14411     protected int getWindowAttachCount() {
   14412         return mWindowAttachCount;
   14413     }
   14414 
   14415     /**
   14416      * Retrieve a unique token identifying the window this view is attached to.
   14417      * @return Return the window's token for use in
   14418      * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
   14419      */
   14420     public IBinder getWindowToken() {
   14421         return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
   14422     }
   14423 
   14424     /**
   14425      * Retrieve the {@link WindowId} for the window this view is
   14426      * currently attached to.
   14427      */
   14428     public WindowId getWindowId() {
   14429         if (mAttachInfo == null) {
   14430             return null;
   14431         }
   14432         if (mAttachInfo.mWindowId == null) {
   14433             try {
   14434                 mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
   14435                         mAttachInfo.mWindowToken);
   14436                 mAttachInfo.mWindowId = new WindowId(
   14437                         mAttachInfo.mIWindowId);
   14438             } catch (RemoteException e) {
   14439             }
   14440         }
   14441         return mAttachInfo.mWindowId;
   14442     }
   14443 
   14444     /**
   14445      * Retrieve a unique token identifying the top-level "real" window of
   14446      * the window that this view is attached to.  That is, this is like
   14447      * {@link #getWindowToken}, except if the window this view in is a panel
   14448      * window (attached to another containing window), then the token of
   14449      * the containing window is returned instead.
   14450      *
   14451      * @return Returns the associated window token, either
   14452      * {@link #getWindowToken()} or the containing window's token.
   14453      */
   14454     public IBinder getApplicationWindowToken() {
   14455         AttachInfo ai = mAttachInfo;
   14456         if (ai != null) {
   14457             IBinder appWindowToken = ai.mPanelParentWindowToken;
   14458             if (appWindowToken == null) {
   14459                 appWindowToken = ai.mWindowToken;
   14460             }
   14461             return appWindowToken;
   14462         }
   14463         return null;
   14464     }
   14465 
   14466     /**
   14467      * Gets the logical display to which the view's window has been attached.
   14468      *
   14469      * @return The logical display, or null if the view is not currently attached to a window.
   14470      */
   14471     public Display getDisplay() {
   14472         return mAttachInfo != null ? mAttachInfo.mDisplay : null;
   14473     }
   14474 
   14475     /**
   14476      * Retrieve private session object this view hierarchy is using to
   14477      * communicate with the window manager.
   14478      * @return the session object to communicate with the window manager
   14479      */
   14480     /*package*/ IWindowSession getWindowSession() {
   14481         return mAttachInfo != null ? mAttachInfo.mSession : null;
   14482     }
   14483 
   14484     /**
   14485      * Return the visibility value of the least visible component passed.
   14486      */
   14487     int combineVisibility(int vis1, int vis2) {
   14488         // This works because VISIBLE < INVISIBLE < GONE.
   14489         return Math.max(vis1, vis2);
   14490     }
   14491 
   14492     /**
   14493      * @param info the {@link android.view.View.AttachInfo} to associated with
   14494      *        this view
   14495      */
   14496     void dispatchAttachedToWindow(AttachInfo info, int visibility) {
   14497         //System.out.println("Attached! " + this);
   14498         mAttachInfo = info;
   14499         if (mOverlay != null) {
   14500             mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
   14501         }
   14502         mWindowAttachCount++;
   14503         // We will need to evaluate the drawable state at least once.
   14504         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
   14505         if (mFloatingTreeObserver != null) {
   14506             info.mTreeObserver.merge(mFloatingTreeObserver);
   14507             mFloatingTreeObserver = null;
   14508         }
   14509         if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
   14510             mAttachInfo.mScrollContainers.add(this);
   14511             mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
   14512         }
   14513         performCollectViewAttributes(mAttachInfo, visibility);
   14514         onAttachedToWindow();
   14515 
   14516         ListenerInfo li = mListenerInfo;
   14517         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
   14518                 li != null ? li.mOnAttachStateChangeListeners : null;
   14519         if (listeners != null && listeners.size() > 0) {
   14520             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
   14521             // perform the dispatching. The iterator is a safe guard against listeners that
   14522             // could mutate the list by calling the various add/remove methods. This prevents
   14523             // the array from being modified while we iterate it.
   14524             for (OnAttachStateChangeListener listener : listeners) {
   14525                 listener.onViewAttachedToWindow(this);
   14526             }
   14527         }
   14528 
   14529         int vis = info.mWindowVisibility;
   14530         if (vis != GONE) {
   14531             onWindowVisibilityChanged(vis);
   14532         }
   14533 
   14534         // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
   14535         // As all views in the subtree will already receive dispatchAttachedToWindow
   14536         // traversing the subtree again here is not desired.
   14537         onVisibilityChanged(this, visibility);
   14538 
   14539         if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
   14540             // If nobody has evaluated the drawable state yet, then do it now.
   14541             refreshDrawableState();
   14542         }
   14543         needGlobalAttributesUpdate(false);
   14544     }
   14545 
   14546     void dispatchDetachedFromWindow() {
   14547         AttachInfo info = mAttachInfo;
   14548         if (info != null) {
   14549             int vis = info.mWindowVisibility;
   14550             if (vis != GONE) {
   14551                 onWindowVisibilityChanged(GONE);
   14552             }
   14553         }
   14554 
   14555         onDetachedFromWindow();
   14556         onDetachedFromWindowInternal();
   14557 
   14558         InputMethodManager imm = InputMethodManager.peekInstance();
   14559         if (imm != null) {
   14560             imm.onViewDetachedFromWindow(this);
   14561         }
   14562 
   14563         ListenerInfo li = mListenerInfo;
   14564         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
   14565                 li != null ? li.mOnAttachStateChangeListeners : null;
   14566         if (listeners != null && listeners.size() > 0) {
   14567             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
   14568             // perform the dispatching. The iterator is a safe guard against listeners that
   14569             // could mutate the list by calling the various add/remove methods. This prevents
   14570             // the array from being modified while we iterate it.
   14571             for (OnAttachStateChangeListener listener : listeners) {
   14572                 listener.onViewDetachedFromWindow(this);
   14573             }
   14574         }
   14575 
   14576         if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
   14577             mAttachInfo.mScrollContainers.remove(this);
   14578             mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
   14579         }
   14580 
   14581         mAttachInfo = null;
   14582         if (mOverlay != null) {
   14583             mOverlay.getOverlayView().dispatchDetachedFromWindow();
   14584         }
   14585     }
   14586 
   14587     /**
   14588      * Cancel any deferred high-level input events that were previously posted to the event queue.
   14589      *
   14590      * <p>Many views post high-level events such as click handlers to the event queue
   14591      * to run deferred in order to preserve a desired user experience - clearing visible
   14592      * pressed states before executing, etc. This method will abort any events of this nature
   14593      * that are currently in flight.</p>
   14594      *
   14595      * <p>Custom views that generate their own high-level deferred input events should override
   14596      * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
   14597      *
   14598      * <p>This will also cancel pending input events for any child views.</p>
   14599      *
   14600      * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
   14601      * This will not impact newer events posted after this call that may occur as a result of
   14602      * lower-level input events still waiting in the queue. If you are trying to prevent
   14603      * double-submitted  events for the duration of some sort of asynchronous transaction
   14604      * you should also take other steps to protect against unexpected double inputs e.g. calling
   14605      * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
   14606      * the transaction completes, tracking already submitted transaction IDs, etc.</p>
   14607      */
   14608     public final void cancelPendingInputEvents() {
   14609         dispatchCancelPendingInputEvents();
   14610     }
   14611 
   14612     /**
   14613      * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
   14614      * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
   14615      */
   14616     void dispatchCancelPendingInputEvents() {
   14617         mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
   14618         onCancelPendingInputEvents();
   14619         if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
   14620             throw new SuperNotCalledException("View " + getClass().getSimpleName() +
   14621                     " did not call through to super.onCancelPendingInputEvents()");
   14622         }
   14623     }
   14624 
   14625     /**
   14626      * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
   14627      * a parent view.
   14628      *
   14629      * <p>This method is responsible for removing any pending high-level input events that were
   14630      * posted to the event queue to run later. Custom view classes that post their own deferred
   14631      * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
   14632      * {@link android.os.Handler} should override this method, call
   14633      * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
   14634      * </p>
   14635      */
   14636     public void onCancelPendingInputEvents() {
   14637         removePerformClickCallback();
   14638         cancelLongPress();
   14639         mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
   14640     }
   14641 
   14642     /**
   14643      * Store this view hierarchy's frozen state into the given container.
   14644      *
   14645      * @param container The SparseArray in which to save the view's state.
   14646      *
   14647      * @see #restoreHierarchyState(android.util.SparseArray)
   14648      * @see #dispatchSaveInstanceState(android.util.SparseArray)
   14649      * @see #onSaveInstanceState()
   14650      */
   14651     public void saveHierarchyState(SparseArray<Parcelable> container) {
   14652         dispatchSaveInstanceState(container);
   14653     }
   14654 
   14655     /**
   14656      * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
   14657      * this view and its children. May be overridden to modify how freezing happens to a
   14658      * view's children; for example, some views may want to not store state for their children.
   14659      *
   14660      * @param container The SparseArray in which to save the view's state.
   14661      *
   14662      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
   14663      * @see #saveHierarchyState(android.util.SparseArray)
   14664      * @see #onSaveInstanceState()
   14665      */
   14666     protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
   14667         if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
   14668             mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
   14669             Parcelable state = onSaveInstanceState();
   14670             if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
   14671                 throw new IllegalStateException(
   14672                         "Derived class did not call super.onSaveInstanceState()");
   14673             }
   14674             if (state != null) {
   14675                 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
   14676                 // + ": " + state);
   14677                 container.put(mID, state);
   14678             }
   14679         }
   14680     }
   14681 
   14682     /**
   14683      * Hook allowing a view to generate a representation of its internal state
   14684      * that can later be used to create a new instance with that same state.
   14685      * This state should only contain information that is not persistent or can
   14686      * not be reconstructed later. For example, you will never store your
   14687      * current position on screen because that will be computed again when a
   14688      * new instance of the view is placed in its view hierarchy.
   14689      * <p>
   14690      * Some examples of things you may store here: the current cursor position
   14691      * in a text view (but usually not the text itself since that is stored in a
   14692      * content provider or other persistent storage), the currently selected
   14693      * item in a list view.
   14694      *
   14695      * @return Returns a Parcelable object containing the view's current dynamic
   14696      *         state, or null if there is nothing interesting to save. The
   14697      *         default implementation returns null.
   14698      * @see #onRestoreInstanceState(android.os.Parcelable)
   14699      * @see #saveHierarchyState(android.util.SparseArray)
   14700      * @see #dispatchSaveInstanceState(android.util.SparseArray)
   14701      * @see #setSaveEnabled(boolean)
   14702      */
   14703     @CallSuper
   14704     protected Parcelable onSaveInstanceState() {
   14705         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
   14706         if (mStartActivityRequestWho != null) {
   14707             BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
   14708             state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
   14709             return state;
   14710         }
   14711         return BaseSavedState.EMPTY_STATE;
   14712     }
   14713 
   14714     /**
   14715      * Restore this view hierarchy's frozen state from the given container.
   14716      *
   14717      * @param container The SparseArray which holds previously frozen states.
   14718      *
   14719      * @see #saveHierarchyState(android.util.SparseArray)
   14720      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
   14721      * @see #onRestoreInstanceState(android.os.Parcelable)
   14722      */
   14723     public void restoreHierarchyState(SparseArray<Parcelable> container) {
   14724         dispatchRestoreInstanceState(container);
   14725     }
   14726 
   14727     /**
   14728      * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
   14729      * state for this view and its children. May be overridden to modify how restoring
   14730      * happens to a view's children; for example, some views may want to not store state
   14731      * for their children.
   14732      *
   14733      * @param container The SparseArray which holds previously saved state.
   14734      *
   14735      * @see #dispatchSaveInstanceState(android.util.SparseArray)
   14736      * @see #restoreHierarchyState(android.util.SparseArray)
   14737      * @see #onRestoreInstanceState(android.os.Parcelable)
   14738      */
   14739     protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
   14740         if (mID != NO_ID) {
   14741             Parcelable state = container.get(mID);
   14742             if (state != null) {
   14743                 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
   14744                 // + ": " + state);
   14745                 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
   14746                 onRestoreInstanceState(state);
   14747                 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
   14748                     throw new IllegalStateException(
   14749                             "Derived class did not call super.onRestoreInstanceState()");
   14750                 }
   14751             }
   14752         }
   14753     }
   14754 
   14755     /**
   14756      * Hook allowing a view to re-apply a representation of its internal state that had previously
   14757      * been generated by {@link #onSaveInstanceState}. This function will never be called with a
   14758      * null state.
   14759      *
   14760      * @param state The frozen state that had previously been returned by
   14761      *        {@link #onSaveInstanceState}.
   14762      *
   14763      * @see #onSaveInstanceState()
   14764      * @see #restoreHierarchyState(android.util.SparseArray)
   14765      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
   14766      */
   14767     @CallSuper
   14768     protected void onRestoreInstanceState(Parcelable state) {
   14769         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
   14770         if (state != null && !(state instanceof AbsSavedState)) {
   14771             throw new IllegalArgumentException("Wrong state class, expecting View State but "
   14772                     + "received " + state.getClass().toString() + " instead. This usually happens "
   14773                     + "when two views of different type have the same id in the same hierarchy. "
   14774                     + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
   14775                     + "other views do not use the same id.");
   14776         }
   14777         if (state != null && state instanceof BaseSavedState) {
   14778             mStartActivityRequestWho = ((BaseSavedState) state).mStartActivityRequestWhoSaved;
   14779         }
   14780     }
   14781 
   14782     /**
   14783      * <p>Return the time at which the drawing of the view hierarchy started.</p>
   14784      *
   14785      * @return the drawing start time in milliseconds
   14786      */
   14787     public long getDrawingTime() {
   14788         return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
   14789     }
   14790 
   14791     /**
   14792      * <p>Enables or disables the duplication of the parent's state into this view. When
   14793      * duplication is enabled, this view gets its drawable state from its parent rather
   14794      * than from its own internal properties.</p>
   14795      *
   14796      * <p>Note: in the current implementation, setting this property to true after the
   14797      * view was added to a ViewGroup might have no effect at all. This property should
   14798      * always be used from XML or set to true before adding this view to a ViewGroup.</p>
   14799      *
   14800      * <p>Note: if this view's parent addStateFromChildren property is enabled and this
   14801      * property is enabled, an exception will be thrown.</p>
   14802      *
   14803      * <p>Note: if the child view uses and updates additional states which are unknown to the
   14804      * parent, these states should not be affected by this method.</p>
   14805      *
   14806      * @param enabled True to enable duplication of the parent's drawable state, false
   14807      *                to disable it.
   14808      *
   14809      * @see #getDrawableState()
   14810      * @see #isDuplicateParentStateEnabled()
   14811      */
   14812     public void setDuplicateParentStateEnabled(boolean enabled) {
   14813         setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
   14814     }
   14815 
   14816     /**
   14817      * <p>Indicates whether this duplicates its drawable state from its parent.</p>
   14818      *
   14819      * @return True if this view's drawable state is duplicated from the parent,
   14820      *         false otherwise
   14821      *
   14822      * @see #getDrawableState()
   14823      * @see #setDuplicateParentStateEnabled(boolean)
   14824      */
   14825     public boolean isDuplicateParentStateEnabled() {
   14826         return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
   14827     }
   14828 
   14829     /**
   14830      * <p>Specifies the type of layer backing this view. The layer can be
   14831      * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
   14832      * {@link #LAYER_TYPE_HARDWARE}.</p>
   14833      *
   14834      * <p>A layer is associated with an optional {@link android.graphics.Paint}
   14835      * instance that controls how the layer is composed on screen. The following
   14836      * properties of the paint are taken into account when composing the layer:</p>
   14837      * <ul>
   14838      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
   14839      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
   14840      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
   14841      * </ul>
   14842      *
   14843      * <p>If this view has an alpha value set to < 1.0 by calling
   14844      * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
   14845      * by this view's alpha value.</p>
   14846      *
   14847      * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
   14848      * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
   14849      * for more information on when and how to use layers.</p>
   14850      *
   14851      * @param layerType The type of layer to use with this view, must be one of
   14852      *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
   14853      *        {@link #LAYER_TYPE_HARDWARE}
   14854      * @param paint The paint used to compose the layer. This argument is optional
   14855      *        and can be null. It is ignored when the layer type is
   14856      *        {@link #LAYER_TYPE_NONE}
   14857      *
   14858      * @see #getLayerType()
   14859      * @see #LAYER_TYPE_NONE
   14860      * @see #LAYER_TYPE_SOFTWARE
   14861      * @see #LAYER_TYPE_HARDWARE
   14862      * @see #setAlpha(float)
   14863      *
   14864      * @attr ref android.R.styleable#View_layerType
   14865      */
   14866     public void setLayerType(int layerType, Paint paint) {
   14867         if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
   14868             throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
   14869                     + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
   14870         }
   14871 
   14872         boolean typeChanged = mRenderNode.setLayerType(layerType);
   14873 
   14874         if (!typeChanged) {
   14875             setLayerPaint(paint);
   14876             return;
   14877         }
   14878 
   14879         // Destroy any previous software drawing cache if needed
   14880         if (mLayerType == LAYER_TYPE_SOFTWARE) {
   14881             destroyDrawingCache();
   14882         }
   14883 
   14884         mLayerType = layerType;
   14885         final boolean layerDisabled = (mLayerType == LAYER_TYPE_NONE);
   14886         mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
   14887         mRenderNode.setLayerPaint(mLayerPaint);
   14888 
   14889         // draw() behaves differently if we are on a layer, so we need to
   14890         // invalidate() here
   14891         invalidateParentCaches();
   14892         invalidate(true);
   14893     }
   14894 
   14895     /**
   14896      * Updates the {@link Paint} object used with the current layer (used only if the current
   14897      * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
   14898      * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
   14899      * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
   14900      * ensure that the view gets redrawn immediately.
   14901      *
   14902      * <p>A layer is associated with an optional {@link android.graphics.Paint}
   14903      * instance that controls how the layer is composed on screen. The following
   14904      * properties of the paint are taken into account when composing the layer:</p>
   14905      * <ul>
   14906      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
   14907      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
   14908      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
   14909      * </ul>
   14910      *
   14911      * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
   14912      * alpha value of the layer's paint is superseded by this view's alpha value.</p>
   14913      *
   14914      * @param paint The paint used to compose the layer. This argument is optional
   14915      *        and can be null. It is ignored when the layer type is
   14916      *        {@link #LAYER_TYPE_NONE}
   14917      *
   14918      * @see #setLayerType(int, android.graphics.Paint)
   14919      */
   14920     public void setLayerPaint(Paint paint) {
   14921         int layerType = getLayerType();
   14922         if (layerType != LAYER_TYPE_NONE) {
   14923             mLayerPaint = paint == null ? new Paint() : paint;
   14924             if (layerType == LAYER_TYPE_HARDWARE) {
   14925                 if (mRenderNode.setLayerPaint(mLayerPaint)) {
   14926                     invalidateViewProperty(false, false);
   14927                 }
   14928             } else {
   14929                 invalidate();
   14930             }
   14931         }
   14932     }
   14933 
   14934     /**
   14935      * Indicates what type of layer is currently associated with this view. By default
   14936      * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
   14937      * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
   14938      * for more information on the different types of layers.
   14939      *
   14940      * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
   14941      *         {@link #LAYER_TYPE_HARDWARE}
   14942      *
   14943      * @see #setLayerType(int, android.graphics.Paint)
   14944      * @see #buildLayer()
   14945      * @see #LAYER_TYPE_NONE
   14946      * @see #LAYER_TYPE_SOFTWARE
   14947      * @see #LAYER_TYPE_HARDWARE
   14948      */
   14949     public int getLayerType() {
   14950         return mLayerType;
   14951     }
   14952 
   14953     /**
   14954      * Forces this view's layer to be created and this view to be rendered
   14955      * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
   14956      * invoking this method will have no effect.
   14957      *
   14958      * This method can for instance be used to render a view into its layer before
   14959      * starting an animation. If this view is complex, rendering into the layer
   14960      * before starting the animation will avoid skipping frames.
   14961      *
   14962      * @throws IllegalStateException If this view is not attached to a window
   14963      *
   14964      * @see #setLayerType(int, android.graphics.Paint)
   14965      */
   14966     public void buildLayer() {
   14967         if (mLayerType == LAYER_TYPE_NONE) return;
   14968 
   14969         final AttachInfo attachInfo = mAttachInfo;
   14970         if (attachInfo == null) {
   14971             throw new IllegalStateException("This view must be attached to a window first");
   14972         }
   14973 
   14974         if (getWidth() == 0 || getHeight() == 0) {
   14975             return;
   14976         }
   14977 
   14978         switch (mLayerType) {
   14979             case LAYER_TYPE_HARDWARE:
   14980                 updateDisplayListIfDirty();
   14981                 if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) {
   14982                     attachInfo.mHardwareRenderer.buildLayer(mRenderNode);
   14983                 }
   14984                 break;
   14985             case LAYER_TYPE_SOFTWARE:
   14986                 buildDrawingCache(true);
   14987                 break;
   14988         }
   14989     }
   14990 
   14991     /**
   14992      * If this View draws with a HardwareLayer, returns it.
   14993      * Otherwise returns null
   14994      *
   14995      * TODO: Only TextureView uses this, can we eliminate it?
   14996      */
   14997     HardwareLayer getHardwareLayer() {
   14998         return null;
   14999     }
   15000 
   15001     /**
   15002      * Destroys all hardware rendering resources. This method is invoked
   15003      * when the system needs to reclaim resources. Upon execution of this
   15004      * method, you should free any OpenGL resources created by the view.
   15005      *
   15006      * Note: you <strong>must</strong> call
   15007      * <code>super.destroyHardwareResources()</code> when overriding
   15008      * this method.
   15009      *
   15010      * @hide
   15011      */
   15012     @CallSuper
   15013     protected void destroyHardwareResources() {
   15014         // Although the Layer will be destroyed by RenderNode, we want to release
   15015         // the staging display list, which is also a signal to RenderNode that it's
   15016         // safe to free its copy of the display list as it knows that we will
   15017         // push an updated DisplayList if we try to draw again
   15018         resetDisplayList();
   15019     }
   15020 
   15021     /**
   15022      * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
   15023      * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
   15024      * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
   15025      * the cache is enabled. To benefit from the cache, you must request the drawing cache by
   15026      * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
   15027      * null.</p>
   15028      *
   15029      * <p>Enabling the drawing cache is similar to
   15030      * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
   15031      * acceleration is turned off. When hardware acceleration is turned on, enabling the
   15032      * drawing cache has no effect on rendering because the system uses a different mechanism
   15033      * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
   15034      * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
   15035      * for information on how to enable software and hardware layers.</p>
   15036      *
   15037      * <p>This API can be used to manually generate
   15038      * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
   15039      * {@link #getDrawingCache()}.</p>
   15040      *
   15041      * @param enabled true to enable the drawing cache, false otherwise
   15042      *
   15043      * @see #isDrawingCacheEnabled()
   15044      * @see #getDrawingCache()
   15045      * @see #buildDrawingCache()
   15046      * @see #setLayerType(int, android.graphics.Paint)
   15047      */
   15048     public void setDrawingCacheEnabled(boolean enabled) {
   15049         mCachingFailed = false;
   15050         setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
   15051     }
   15052 
   15053     /**
   15054      * <p>Indicates whether the drawing cache is enabled for this view.</p>
   15055      *
   15056      * @return true if the drawing cache is enabled
   15057      *
   15058      * @see #setDrawingCacheEnabled(boolean)
   15059      * @see #getDrawingCache()
   15060      */
   15061     @ViewDebug.ExportedProperty(category = "drawing")
   15062     public boolean isDrawingCacheEnabled() {
   15063         return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
   15064     }
   15065 
   15066     /**
   15067      * Debugging utility which recursively outputs the dirty state of a view and its
   15068      * descendants.
   15069      *
   15070      * @hide
   15071      */
   15072     @SuppressWarnings({"UnusedDeclaration"})
   15073     public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
   15074         Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
   15075                 ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
   15076                 (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
   15077                 ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
   15078         if (clear) {
   15079             mPrivateFlags &= clearMask;
   15080         }
   15081         if (this instanceof ViewGroup) {
   15082             ViewGroup parent = (ViewGroup) this;
   15083             final int count = parent.getChildCount();
   15084             for (int i = 0; i < count; i++) {
   15085                 final View child = parent.getChildAt(i);
   15086                 child.outputDirtyFlags(indent + "  ", clear, clearMask);
   15087             }
   15088         }
   15089     }
   15090 
   15091     /**
   15092      * This method is used by ViewGroup to cause its children to restore or recreate their
   15093      * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
   15094      * to recreate its own display list, which would happen if it went through the normal
   15095      * draw/dispatchDraw mechanisms.
   15096      *
   15097      * @hide
   15098      */
   15099     protected void dispatchGetDisplayList() {}
   15100 
   15101     /**
   15102      * A view that is not attached or hardware accelerated cannot create a display list.
   15103      * This method checks these conditions and returns the appropriate result.
   15104      *
   15105      * @return true if view has the ability to create a display list, false otherwise.
   15106      *
   15107      * @hide
   15108      */
   15109     public boolean canHaveDisplayList() {
   15110         return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
   15111     }
   15112 
   15113     /**
   15114      * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
   15115      * @hide
   15116      */
   15117     @NonNull
   15118     public RenderNode updateDisplayListIfDirty() {
   15119         final RenderNode renderNode = mRenderNode;
   15120         if (!canHaveDisplayList()) {
   15121             // can't populate RenderNode, don't try
   15122             return renderNode;
   15123         }
   15124 
   15125         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
   15126                 || !renderNode.isValid()
   15127                 || (mRecreateDisplayList)) {
   15128             // Don't need to recreate the display list, just need to tell our
   15129             // children to restore/recreate theirs
   15130             if (renderNode.isValid()
   15131                     && !mRecreateDisplayList) {
   15132                 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
   15133                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   15134                 dispatchGetDisplayList();
   15135 
   15136                 return renderNode; // no work needed
   15137             }
   15138 
   15139             // If we got here, we're recreating it. Mark it as such to ensure that
   15140             // we copy in child display lists into ours in drawChild()
   15141             mRecreateDisplayList = true;
   15142 
   15143             int width = mRight - mLeft;
   15144             int height = mBottom - mTop;
   15145             int layerType = getLayerType();
   15146 
   15147             final DisplayListCanvas canvas = renderNode.start(width, height);
   15148             canvas.setHighContrastText(mAttachInfo.mHighContrastText);
   15149 
   15150             try {
   15151                 final HardwareLayer layer = getHardwareLayer();
   15152                 if (layer != null && layer.isValid()) {
   15153                     canvas.drawHardwareLayer(layer, 0, 0, mLayerPaint);
   15154                 } else if (layerType == LAYER_TYPE_SOFTWARE) {
   15155                     buildDrawingCache(true);
   15156                     Bitmap cache = getDrawingCache(true);
   15157                     if (cache != null) {
   15158                         canvas.drawBitmap(cache, 0, 0, mLayerPaint);
   15159                     }
   15160                 } else {
   15161                     computeScroll();
   15162 
   15163                     canvas.translate(-mScrollX, -mScrollY);
   15164                     mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
   15165                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   15166 
   15167                     // Fast path for layouts with no backgrounds
   15168                     if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
   15169                         dispatchDraw(canvas);
   15170                         if (mOverlay != null && !mOverlay.isEmpty()) {
   15171                             mOverlay.getOverlayView().draw(canvas);
   15172                         }
   15173                     } else {
   15174                         draw(canvas);
   15175                     }
   15176                 }
   15177             } finally {
   15178                 renderNode.end(canvas);
   15179                 setDisplayListProperties(renderNode);
   15180             }
   15181         } else {
   15182             mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
   15183             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   15184         }
   15185         return renderNode;
   15186     }
   15187 
   15188     private void resetDisplayList() {
   15189         if (mRenderNode.isValid()) {
   15190             mRenderNode.destroyDisplayListData();
   15191         }
   15192 
   15193         if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
   15194             mBackgroundRenderNode.destroyDisplayListData();
   15195         }
   15196     }
   15197 
   15198     /**
   15199      * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
   15200      *
   15201      * @return A non-scaled bitmap representing this view or null if cache is disabled.
   15202      *
   15203      * @see #getDrawingCache(boolean)
   15204      */
   15205     public Bitmap getDrawingCache() {
   15206         return getDrawingCache(false);
   15207     }
   15208 
   15209     /**
   15210      * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
   15211      * is null when caching is disabled. If caching is enabled and the cache is not ready,
   15212      * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
   15213      * draw from the cache when the cache is enabled. To benefit from the cache, you must
   15214      * request the drawing cache by calling this method and draw it on screen if the
   15215      * returned bitmap is not null.</p>
   15216      *
   15217      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
   15218      * this method will create a bitmap of the same size as this view. Because this bitmap
   15219      * will be drawn scaled by the parent ViewGroup, the result on screen might show
   15220      * scaling artifacts. To avoid such artifacts, you should call this method by setting
   15221      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
   15222      * size than the view. This implies that your application must be able to handle this
   15223      * size.</p>
   15224      *
   15225      * @param autoScale Indicates whether the generated bitmap should be scaled based on
   15226      *        the current density of the screen when the application is in compatibility
   15227      *        mode.
   15228      *
   15229      * @return A bitmap representing this view or null if cache is disabled.
   15230      *
   15231      * @see #setDrawingCacheEnabled(boolean)
   15232      * @see #isDrawingCacheEnabled()
   15233      * @see #buildDrawingCache(boolean)
   15234      * @see #destroyDrawingCache()
   15235      */
   15236     public Bitmap getDrawingCache(boolean autoScale) {
   15237         if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
   15238             return null;
   15239         }
   15240         if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
   15241             buildDrawingCache(autoScale);
   15242         }
   15243         return autoScale ? mDrawingCache : mUnscaledDrawingCache;
   15244     }
   15245 
   15246     /**
   15247      * <p>Frees the resources used by the drawing cache. If you call
   15248      * {@link #buildDrawingCache()} manually without calling
   15249      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
   15250      * should cleanup the cache with this method afterwards.</p>
   15251      *
   15252      * @see #setDrawingCacheEnabled(boolean)
   15253      * @see #buildDrawingCache()
   15254      * @see #getDrawingCache()
   15255      */
   15256     public void destroyDrawingCache() {
   15257         if (mDrawingCache != null) {
   15258             mDrawingCache.recycle();
   15259             mDrawingCache = null;
   15260         }
   15261         if (mUnscaledDrawingCache != null) {
   15262             mUnscaledDrawingCache.recycle();
   15263             mUnscaledDrawingCache = null;
   15264         }
   15265     }
   15266 
   15267     /**
   15268      * Setting a solid background color for the drawing cache's bitmaps will improve
   15269      * performance and memory usage. Note, though that this should only be used if this
   15270      * view will always be drawn on top of a solid color.
   15271      *
   15272      * @param color The background color to use for the drawing cache's bitmap
   15273      *
   15274      * @see #setDrawingCacheEnabled(boolean)
   15275      * @see #buildDrawingCache()
   15276      * @see #getDrawingCache()
   15277      */
   15278     public void setDrawingCacheBackgroundColor(@ColorInt int color) {
   15279         if (color != mDrawingCacheBackgroundColor) {
   15280             mDrawingCacheBackgroundColor = color;
   15281             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
   15282         }
   15283     }
   15284 
   15285     /**
   15286      * @see #setDrawingCacheBackgroundColor(int)
   15287      *
   15288      * @return The background color to used for the drawing cache's bitmap
   15289      */
   15290     @ColorInt
   15291     public int getDrawingCacheBackgroundColor() {
   15292         return mDrawingCacheBackgroundColor;
   15293     }
   15294 
   15295     /**
   15296      * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
   15297      *
   15298      * @see #buildDrawingCache(boolean)
   15299      */
   15300     public void buildDrawingCache() {
   15301         buildDrawingCache(false);
   15302     }
   15303 
   15304     /**
   15305      * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
   15306      *
   15307      * <p>If you call {@link #buildDrawingCache()} manually without calling
   15308      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
   15309      * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
   15310      *
   15311      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
   15312      * this method will create a bitmap of the same size as this view. Because this bitmap
   15313      * will be drawn scaled by the parent ViewGroup, the result on screen might show
   15314      * scaling artifacts. To avoid such artifacts, you should call this method by setting
   15315      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
   15316      * size than the view. This implies that your application must be able to handle this
   15317      * size.</p>
   15318      *
   15319      * <p>You should avoid calling this method when hardware acceleration is enabled. If
   15320      * you do not need the drawing cache bitmap, calling this method will increase memory
   15321      * usage and cause the view to be rendered in software once, thus negatively impacting
   15322      * performance.</p>
   15323      *
   15324      * @see #getDrawingCache()
   15325      * @see #destroyDrawingCache()
   15326      */
   15327     public void buildDrawingCache(boolean autoScale) {
   15328         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
   15329                 mDrawingCache == null : mUnscaledDrawingCache == null)) {
   15330             if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
   15331                 Trace.traceBegin(Trace.TRACE_TAG_VIEW,
   15332                         "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
   15333             }
   15334             try {
   15335                 buildDrawingCacheImpl(autoScale);
   15336             } finally {
   15337                 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
   15338             }
   15339         }
   15340     }
   15341 
   15342     /**
   15343      * private, internal implementation of buildDrawingCache, used to enable tracing
   15344      */
   15345     private void buildDrawingCacheImpl(boolean autoScale) {
   15346         mCachingFailed = false;
   15347 
   15348         int width = mRight - mLeft;
   15349         int height = mBottom - mTop;
   15350 
   15351         final AttachInfo attachInfo = mAttachInfo;
   15352         final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
   15353 
   15354         if (autoScale && scalingRequired) {
   15355             width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
   15356             height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
   15357         }
   15358 
   15359         final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
   15360         final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
   15361         final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
   15362 
   15363         final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
   15364         final long drawingCacheSize =
   15365                 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
   15366         if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
   15367             if (width > 0 && height > 0) {
   15368                 Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
   15369                         + " too large to fit into a software layer (or drawing cache), needs "
   15370                         + projectedBitmapSize + " bytes, only "
   15371                         + drawingCacheSize + " available");
   15372             }
   15373             destroyDrawingCache();
   15374             mCachingFailed = true;
   15375             return;
   15376         }
   15377 
   15378         boolean clear = true;
   15379         Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
   15380 
   15381         if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
   15382             Bitmap.Config quality;
   15383             if (!opaque) {
   15384                 // Never pick ARGB_4444 because it looks awful
   15385                 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
   15386                 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
   15387                     case DRAWING_CACHE_QUALITY_AUTO:
   15388                     case DRAWING_CACHE_QUALITY_LOW:
   15389                     case DRAWING_CACHE_QUALITY_HIGH:
   15390                     default:
   15391                         quality = Bitmap.Config.ARGB_8888;
   15392                         break;
   15393                 }
   15394             } else {
   15395                 // Optimization for translucent windows
   15396                 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
   15397                 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
   15398             }
   15399 
   15400             // Try to cleanup memory
   15401             if (bitmap != null) bitmap.recycle();
   15402 
   15403             try {
   15404                 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
   15405                         width, height, quality);
   15406                 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
   15407                 if (autoScale) {
   15408                     mDrawingCache = bitmap;
   15409                 } else {
   15410                     mUnscaledDrawingCache = bitmap;
   15411                 }
   15412                 if (opaque && use32BitCache) bitmap.setHasAlpha(false);
   15413             } catch (OutOfMemoryError e) {
   15414                 // If there is not enough memory to create the bitmap cache, just
   15415                 // ignore the issue as bitmap caches are not required to draw the
   15416                 // view hierarchy
   15417                 if (autoScale) {
   15418                     mDrawingCache = null;
   15419                 } else {
   15420                     mUnscaledDrawingCache = null;
   15421                 }
   15422                 mCachingFailed = true;
   15423                 return;
   15424             }
   15425 
   15426             clear = drawingCacheBackgroundColor != 0;
   15427         }
   15428 
   15429         Canvas canvas;
   15430         if (attachInfo != null) {
   15431             canvas = attachInfo.mCanvas;
   15432             if (canvas == null) {
   15433                 canvas = new Canvas();
   15434             }
   15435             canvas.setBitmap(bitmap);
   15436             // Temporarily clobber the cached Canvas in case one of our children
   15437             // is also using a drawing cache. Without this, the children would
   15438             // steal the canvas by attaching their own bitmap to it and bad, bad
   15439             // thing would happen (invisible views, corrupted drawings, etc.)
   15440             attachInfo.mCanvas = null;
   15441         } else {
   15442             // This case should hopefully never or seldom happen
   15443             canvas = new Canvas(bitmap);
   15444         }
   15445 
   15446         if (clear) {
   15447             bitmap.eraseColor(drawingCacheBackgroundColor);
   15448         }
   15449 
   15450         computeScroll();
   15451         final int restoreCount = canvas.save();
   15452 
   15453         if (autoScale && scalingRequired) {
   15454             final float scale = attachInfo.mApplicationScale;
   15455             canvas.scale(scale, scale);
   15456         }
   15457 
   15458         canvas.translate(-mScrollX, -mScrollY);
   15459 
   15460         mPrivateFlags |= PFLAG_DRAWN;
   15461         if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
   15462                 mLayerType != LAYER_TYPE_NONE) {
   15463             mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
   15464         }
   15465 
   15466         // Fast path for layouts with no backgrounds
   15467         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
   15468             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   15469             dispatchDraw(canvas);
   15470             if (mOverlay != null && !mOverlay.isEmpty()) {
   15471                 mOverlay.getOverlayView().draw(canvas);
   15472             }
   15473         } else {
   15474             draw(canvas);
   15475         }
   15476 
   15477         canvas.restoreToCount(restoreCount);
   15478         canvas.setBitmap(null);
   15479 
   15480         if (attachInfo != null) {
   15481             // Restore the cached Canvas for our siblings
   15482             attachInfo.mCanvas = canvas;
   15483         }
   15484     }
   15485 
   15486     /**
   15487      * Create a snapshot of the view into a bitmap.  We should probably make
   15488      * some form of this public, but should think about the API.
   15489      */
   15490     Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
   15491         int width = mRight - mLeft;
   15492         int height = mBottom - mTop;
   15493 
   15494         final AttachInfo attachInfo = mAttachInfo;
   15495         final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
   15496         width = (int) ((width * scale) + 0.5f);
   15497         height = (int) ((height * scale) + 0.5f);
   15498 
   15499         Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
   15500                 width > 0 ? width : 1, height > 0 ? height : 1, quality);
   15501         if (bitmap == null) {
   15502             throw new OutOfMemoryError();
   15503         }
   15504 
   15505         Resources resources = getResources();
   15506         if (resources != null) {
   15507             bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
   15508         }
   15509 
   15510         Canvas canvas;
   15511         if (attachInfo != null) {
   15512             canvas = attachInfo.mCanvas;
   15513             if (canvas == null) {
   15514                 canvas = new Canvas();
   15515             }
   15516             canvas.setBitmap(bitmap);
   15517             // Temporarily clobber the cached Canvas in case one of our children
   15518             // is also using a drawing cache. Without this, the children would
   15519             // steal the canvas by attaching their own bitmap to it and bad, bad
   15520             // things would happen (invisible views, corrupted drawings, etc.)
   15521             attachInfo.mCanvas = null;
   15522         } else {
   15523             // This case should hopefully never or seldom happen
   15524             canvas = new Canvas(bitmap);
   15525         }
   15526 
   15527         if ((backgroundColor & 0xff000000) != 0) {
   15528             bitmap.eraseColor(backgroundColor);
   15529         }
   15530 
   15531         computeScroll();
   15532         final int restoreCount = canvas.save();
   15533         canvas.scale(scale, scale);
   15534         canvas.translate(-mScrollX, -mScrollY);
   15535 
   15536         // Temporarily remove the dirty mask
   15537         int flags = mPrivateFlags;
   15538         mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   15539 
   15540         // Fast path for layouts with no backgrounds
   15541         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
   15542             dispatchDraw(canvas);
   15543             if (mOverlay != null && !mOverlay.isEmpty()) {
   15544                 mOverlay.getOverlayView().draw(canvas);
   15545             }
   15546         } else {
   15547             draw(canvas);
   15548         }
   15549 
   15550         mPrivateFlags = flags;
   15551 
   15552         canvas.restoreToCount(restoreCount);
   15553         canvas.setBitmap(null);
   15554 
   15555         if (attachInfo != null) {
   15556             // Restore the cached Canvas for our siblings
   15557             attachInfo.mCanvas = canvas;
   15558         }
   15559 
   15560         return bitmap;
   15561     }
   15562 
   15563     /**
   15564      * Indicates whether this View is currently in edit mode. A View is usually
   15565      * in edit mode when displayed within a developer tool. For instance, if
   15566      * this View is being drawn by a visual user interface builder, this method
   15567      * should return true.
   15568      *
   15569      * Subclasses should check the return value of this method to provide
   15570      * different behaviors if their normal behavior might interfere with the
   15571      * host environment. For instance: the class spawns a thread in its
   15572      * constructor, the drawing code relies on device-specific features, etc.
   15573      *
   15574      * This method is usually checked in the drawing code of custom widgets.
   15575      *
   15576      * @return True if this View is in edit mode, false otherwise.
   15577      */
   15578     public boolean isInEditMode() {
   15579         return false;
   15580     }
   15581 
   15582     /**
   15583      * If the View draws content inside its padding and enables fading edges,
   15584      * it needs to support padding offsets. Padding offsets are added to the
   15585      * fading edges to extend the length of the fade so that it covers pixels
   15586      * drawn inside the padding.
   15587      *
   15588      * Subclasses of this class should override this method if they need
   15589      * to draw content inside the padding.
   15590      *
   15591      * @return True if padding offset must be applied, false otherwise.
   15592      *
   15593      * @see #getLeftPaddingOffset()
   15594      * @see #getRightPaddingOffset()
   15595      * @see #getTopPaddingOffset()
   15596      * @see #getBottomPaddingOffset()
   15597      *
   15598      * @since CURRENT
   15599      */
   15600     protected boolean isPaddingOffsetRequired() {
   15601         return false;
   15602     }
   15603 
   15604     /**
   15605      * Amount by which to extend the left fading region. Called only when
   15606      * {@link #isPaddingOffsetRequired()} returns true.
   15607      *
   15608      * @return The left padding offset in pixels.
   15609      *
   15610      * @see #isPaddingOffsetRequired()
   15611      *
   15612      * @since CURRENT
   15613      */
   15614     protected int getLeftPaddingOffset() {
   15615         return 0;
   15616     }
   15617 
   15618     /**
   15619      * Amount by which to extend the right fading region. Called only when
   15620      * {@link #isPaddingOffsetRequired()} returns true.
   15621      *
   15622      * @return The right padding offset in pixels.
   15623      *
   15624      * @see #isPaddingOffsetRequired()
   15625      *
   15626      * @since CURRENT
   15627      */
   15628     protected int getRightPaddingOffset() {
   15629         return 0;
   15630     }
   15631 
   15632     /**
   15633      * Amount by which to extend the top fading region. Called only when
   15634      * {@link #isPaddingOffsetRequired()} returns true.
   15635      *
   15636      * @return The top padding offset in pixels.
   15637      *
   15638      * @see #isPaddingOffsetRequired()
   15639      *
   15640      * @since CURRENT
   15641      */
   15642     protected int getTopPaddingOffset() {
   15643         return 0;
   15644     }
   15645 
   15646     /**
   15647      * Amount by which to extend the bottom fading region. Called only when
   15648      * {@link #isPaddingOffsetRequired()} returns true.
   15649      *
   15650      * @return The bottom padding offset in pixels.
   15651      *
   15652      * @see #isPaddingOffsetRequired()
   15653      *
   15654      * @since CURRENT
   15655      */
   15656     protected int getBottomPaddingOffset() {
   15657         return 0;
   15658     }
   15659 
   15660     /**
   15661      * @hide
   15662      * @param offsetRequired
   15663      */
   15664     protected int getFadeTop(boolean offsetRequired) {
   15665         int top = mPaddingTop;
   15666         if (offsetRequired) top += getTopPaddingOffset();
   15667         return top;
   15668     }
   15669 
   15670     /**
   15671      * @hide
   15672      * @param offsetRequired
   15673      */
   15674     protected int getFadeHeight(boolean offsetRequired) {
   15675         int padding = mPaddingTop;
   15676         if (offsetRequired) padding += getTopPaddingOffset();
   15677         return mBottom - mTop - mPaddingBottom - padding;
   15678     }
   15679 
   15680     /**
   15681      * <p>Indicates whether this view is attached to a hardware accelerated
   15682      * window or not.</p>
   15683      *
   15684      * <p>Even if this method returns true, it does not mean that every call
   15685      * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
   15686      * accelerated {@link android.graphics.Canvas}. For instance, if this view
   15687      * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
   15688      * window is hardware accelerated,
   15689      * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
   15690      * return false, and this method will return true.</p>
   15691      *
   15692      * @return True if the view is attached to a window and the window is
   15693      *         hardware accelerated; false in any other case.
   15694      */
   15695     @ViewDebug.ExportedProperty(category = "drawing")
   15696     public boolean isHardwareAccelerated() {
   15697         return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
   15698     }
   15699 
   15700     /**
   15701      * Sets a rectangular area on this view to which the view will be clipped
   15702      * when it is drawn. Setting the value to null will remove the clip bounds
   15703      * and the view will draw normally, using its full bounds.
   15704      *
   15705      * @param clipBounds The rectangular area, in the local coordinates of
   15706      * this view, to which future drawing operations will be clipped.
   15707      */
   15708     public void setClipBounds(Rect clipBounds) {
   15709         if (clipBounds == mClipBounds
   15710                 || (clipBounds != null && clipBounds.equals(mClipBounds))) {
   15711             return;
   15712         }
   15713         if (clipBounds != null) {
   15714             if (mClipBounds == null) {
   15715                 mClipBounds = new Rect(clipBounds);
   15716             } else {
   15717                 mClipBounds.set(clipBounds);
   15718             }
   15719         } else {
   15720             mClipBounds = null;
   15721         }
   15722         mRenderNode.setClipBounds(mClipBounds);
   15723         invalidateViewProperty(false, false);
   15724     }
   15725 
   15726     /**
   15727      * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
   15728      *
   15729      * @return A copy of the current clip bounds if clip bounds are set,
   15730      * otherwise null.
   15731      */
   15732     public Rect getClipBounds() {
   15733         return (mClipBounds != null) ? new Rect(mClipBounds) : null;
   15734     }
   15735 
   15736 
   15737     /**
   15738      * Populates an output rectangle with the clip bounds of the view,
   15739      * returning {@code true} if successful or {@code false} if the view's
   15740      * clip bounds are {@code null}.
   15741      *
   15742      * @param outRect rectangle in which to place the clip bounds of the view
   15743      * @return {@code true} if successful or {@code false} if the view's
   15744      *         clip bounds are {@code null}
   15745      */
   15746     public boolean getClipBounds(Rect outRect) {
   15747         if (mClipBounds != null) {
   15748             outRect.set(mClipBounds);
   15749             return true;
   15750         }
   15751         return false;
   15752     }
   15753 
   15754     /**
   15755      * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
   15756      * case of an active Animation being run on the view.
   15757      */
   15758     private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
   15759             Animation a, boolean scalingRequired) {
   15760         Transformation invalidationTransform;
   15761         final int flags = parent.mGroupFlags;
   15762         final boolean initialized = a.isInitialized();
   15763         if (!initialized) {
   15764             a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
   15765             a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
   15766             if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
   15767             onAnimationStart();
   15768         }
   15769 
   15770         final Transformation t = parent.getChildTransformation();
   15771         boolean more = a.getTransformation(drawingTime, t, 1f);
   15772         if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
   15773             if (parent.mInvalidationTransformation == null) {
   15774                 parent.mInvalidationTransformation = new Transformation();
   15775             }
   15776             invalidationTransform = parent.mInvalidationTransformation;
   15777             a.getTransformation(drawingTime, invalidationTransform, 1f);
   15778         } else {
   15779             invalidationTransform = t;
   15780         }
   15781 
   15782         if (more) {
   15783             if (!a.willChangeBounds()) {
   15784                 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
   15785                         ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
   15786                     parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
   15787                 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
   15788                     // The child need to draw an animation, potentially offscreen, so
   15789                     // make sure we do not cancel invalidate requests
   15790                     parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
   15791                     parent.invalidate(mLeft, mTop, mRight, mBottom);
   15792                 }
   15793             } else {
   15794                 if (parent.mInvalidateRegion == null) {
   15795                     parent.mInvalidateRegion = new RectF();
   15796                 }
   15797                 final RectF region = parent.mInvalidateRegion;
   15798                 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
   15799                         invalidationTransform);
   15800 
   15801                 // The child need to draw an animation, potentially offscreen, so
   15802                 // make sure we do not cancel invalidate requests
   15803                 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
   15804 
   15805                 final int left = mLeft + (int) region.left;
   15806                 final int top = mTop + (int) region.top;
   15807                 parent.invalidate(left, top, left + (int) (region.width() + .5f),
   15808                         top + (int) (region.height() + .5f));
   15809             }
   15810         }
   15811         return more;
   15812     }
   15813 
   15814     /**
   15815      * This method is called by getDisplayList() when a display list is recorded for a View.
   15816      * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
   15817      */
   15818     void setDisplayListProperties(RenderNode renderNode) {
   15819         if (renderNode != null) {
   15820             renderNode.setHasOverlappingRendering(hasOverlappingRendering());
   15821             renderNode.setClipToBounds(mParent instanceof ViewGroup
   15822                     && ((ViewGroup) mParent).getClipChildren());
   15823 
   15824             float alpha = 1;
   15825             if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
   15826                     ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
   15827                 ViewGroup parentVG = (ViewGroup) mParent;
   15828                 final Transformation t = parentVG.getChildTransformation();
   15829                 if (parentVG.getChildStaticTransformation(this, t)) {
   15830                     final int transformType = t.getTransformationType();
   15831                     if (transformType != Transformation.TYPE_IDENTITY) {
   15832                         if ((transformType & Transformation.TYPE_ALPHA) != 0) {
   15833                             alpha = t.getAlpha();
   15834                         }
   15835                         if ((transformType & Transformation.TYPE_MATRIX) != 0) {
   15836                             renderNode.setStaticMatrix(t.getMatrix());
   15837                         }
   15838                     }
   15839                 }
   15840             }
   15841             if (mTransformationInfo != null) {
   15842                 alpha *= getFinalAlpha();
   15843                 if (alpha < 1) {
   15844                     final int multipliedAlpha = (int) (255 * alpha);
   15845                     if (onSetAlpha(multipliedAlpha)) {
   15846                         alpha = 1;
   15847                     }
   15848                 }
   15849                 renderNode.setAlpha(alpha);
   15850             } else if (alpha < 1) {
   15851                 renderNode.setAlpha(alpha);
   15852             }
   15853         }
   15854     }
   15855 
   15856     /**
   15857      * This method is called by ViewGroup.drawChild() to have each child view draw itself.
   15858      *
   15859      * This is where the View specializes rendering behavior based on layer type,
   15860      * and hardware acceleration.
   15861      */
   15862     boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
   15863         final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
   15864         /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
   15865          *
   15866          * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
   15867          * HW accelerated, it can't handle drawing RenderNodes.
   15868          */
   15869         boolean drawingWithRenderNode = mAttachInfo != null
   15870                 && mAttachInfo.mHardwareAccelerated
   15871                 && hardwareAcceleratedCanvas;
   15872 
   15873         boolean more = false;
   15874         final boolean childHasIdentityMatrix = hasIdentityMatrix();
   15875         final int parentFlags = parent.mGroupFlags;
   15876 
   15877         if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
   15878             parent.getChildTransformation().clear();
   15879             parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
   15880         }
   15881 
   15882         Transformation transformToApply = null;
   15883         boolean concatMatrix = false;
   15884         final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
   15885         final Animation a = getAnimation();
   15886         if (a != null) {
   15887             more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
   15888             concatMatrix = a.willChangeTransformationMatrix();
   15889             if (concatMatrix) {
   15890                 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
   15891             }
   15892             transformToApply = parent.getChildTransformation();
   15893         } else {
   15894             if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
   15895                 // No longer animating: clear out old animation matrix
   15896                 mRenderNode.setAnimationMatrix(null);
   15897                 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
   15898             }
   15899             if (!drawingWithRenderNode
   15900                     && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
   15901                 final Transformation t = parent.getChildTransformation();
   15902                 final boolean hasTransform = parent.getChildStaticTransformation(this, t);
   15903                 if (hasTransform) {
   15904                     final int transformType = t.getTransformationType();
   15905                     transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
   15906                     concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
   15907                 }
   15908             }
   15909         }
   15910 
   15911         concatMatrix |= !childHasIdentityMatrix;
   15912 
   15913         // Sets the flag as early as possible to allow draw() implementations
   15914         // to call invalidate() successfully when doing animations
   15915         mPrivateFlags |= PFLAG_DRAWN;
   15916 
   15917         if (!concatMatrix &&
   15918                 (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
   15919                         ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
   15920                 canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
   15921                 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
   15922             mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
   15923             return more;
   15924         }
   15925         mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
   15926 
   15927         if (hardwareAcceleratedCanvas) {
   15928             // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
   15929             // retain the flag's value temporarily in the mRecreateDisplayList flag
   15930             mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
   15931             mPrivateFlags &= ~PFLAG_INVALIDATED;
   15932         }
   15933 
   15934         RenderNode renderNode = null;
   15935         Bitmap cache = null;
   15936         int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
   15937         if (layerType == LAYER_TYPE_SOFTWARE
   15938                 || (!drawingWithRenderNode && layerType != LAYER_TYPE_NONE)) {
   15939             // If not drawing with RenderNode, treat HW layers as SW
   15940             layerType = LAYER_TYPE_SOFTWARE;
   15941             buildDrawingCache(true);
   15942             cache = getDrawingCache(true);
   15943         }
   15944 
   15945         if (drawingWithRenderNode) {
   15946             // Delay getting the display list until animation-driven alpha values are
   15947             // set up and possibly passed on to the view
   15948             renderNode = updateDisplayListIfDirty();
   15949             if (!renderNode.isValid()) {
   15950                 // Uncommon, but possible. If a view is removed from the hierarchy during the call
   15951                 // to getDisplayList(), the display list will be marked invalid and we should not
   15952                 // try to use it again.
   15953                 renderNode = null;
   15954                 drawingWithRenderNode = false;
   15955             }
   15956         }
   15957 
   15958         int sx = 0;
   15959         int sy = 0;
   15960         if (!drawingWithRenderNode) {
   15961             computeScroll();
   15962             sx = mScrollX;
   15963             sy = mScrollY;
   15964         }
   15965 
   15966         final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
   15967         final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
   15968 
   15969         int restoreTo = -1;
   15970         if (!drawingWithRenderNode || transformToApply != null) {
   15971             restoreTo = canvas.save();
   15972         }
   15973         if (offsetForScroll) {
   15974             canvas.translate(mLeft - sx, mTop - sy);
   15975         } else {
   15976             if (!drawingWithRenderNode) {
   15977                 canvas.translate(mLeft, mTop);
   15978             }
   15979             if (scalingRequired) {
   15980                 if (drawingWithRenderNode) {
   15981                     // TODO: Might not need this if we put everything inside the DL
   15982                     restoreTo = canvas.save();
   15983                 }
   15984                 // mAttachInfo cannot be null, otherwise scalingRequired == false
   15985                 final float scale = 1.0f / mAttachInfo.mApplicationScale;
   15986                 canvas.scale(scale, scale);
   15987             }
   15988         }
   15989 
   15990         float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
   15991         if (transformToApply != null
   15992                 || alpha < 1
   15993                 || !hasIdentityMatrix()
   15994                 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
   15995             if (transformToApply != null || !childHasIdentityMatrix) {
   15996                 int transX = 0;
   15997                 int transY = 0;
   15998 
   15999                 if (offsetForScroll) {
   16000                     transX = -sx;
   16001                     transY = -sy;
   16002                 }
   16003 
   16004                 if (transformToApply != null) {
   16005                     if (concatMatrix) {
   16006                         if (drawingWithRenderNode) {
   16007                             renderNode.setAnimationMatrix(transformToApply.getMatrix());
   16008                         } else {
   16009                             // Undo the scroll translation, apply the transformation matrix,
   16010                             // then redo the scroll translate to get the correct result.
   16011                             canvas.translate(-transX, -transY);
   16012                             canvas.concat(transformToApply.getMatrix());
   16013                             canvas.translate(transX, transY);
   16014                         }
   16015                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
   16016                     }
   16017 
   16018                     float transformAlpha = transformToApply.getAlpha();
   16019                     if (transformAlpha < 1) {
   16020                         alpha *= transformAlpha;
   16021                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
   16022                     }
   16023                 }
   16024 
   16025                 if (!childHasIdentityMatrix && !drawingWithRenderNode) {
   16026                     canvas.translate(-transX, -transY);
   16027                     canvas.concat(getMatrix());
   16028                     canvas.translate(transX, transY);
   16029                 }
   16030             }
   16031 
   16032             // Deal with alpha if it is or used to be <1
   16033             if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
   16034                 if (alpha < 1) {
   16035                     mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
   16036                 } else {
   16037                     mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
   16038                 }
   16039                 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
   16040                 if (!drawingWithDrawingCache) {
   16041                     final int multipliedAlpha = (int) (255 * alpha);
   16042                     if (!onSetAlpha(multipliedAlpha)) {
   16043                         if (drawingWithRenderNode) {
   16044                             renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
   16045                         } else if (layerType == LAYER_TYPE_NONE) {
   16046                             canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
   16047                                     multipliedAlpha);
   16048                         }
   16049                     } else {
   16050                         // Alpha is handled by the child directly, clobber the layer's alpha
   16051                         mPrivateFlags |= PFLAG_ALPHA_SET;
   16052                     }
   16053                 }
   16054             }
   16055         } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
   16056             onSetAlpha(255);
   16057             mPrivateFlags &= ~PFLAG_ALPHA_SET;
   16058         }
   16059 
   16060         if (!drawingWithRenderNode) {
   16061             // apply clips directly, since RenderNode won't do it for this draw
   16062             if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
   16063                 if (offsetForScroll) {
   16064                     canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
   16065                 } else {
   16066                     if (!scalingRequired || cache == null) {
   16067                         canvas.clipRect(0, 0, getWidth(), getHeight());
   16068                     } else {
   16069                         canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
   16070                     }
   16071                 }
   16072             }
   16073 
   16074             if (mClipBounds != null) {
   16075                 // clip bounds ignore scroll
   16076                 canvas.clipRect(mClipBounds);
   16077             }
   16078         }
   16079 
   16080         if (!drawingWithDrawingCache) {
   16081             if (drawingWithRenderNode) {
   16082                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   16083                 ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
   16084             } else {
   16085                 // Fast path for layouts with no backgrounds
   16086                 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
   16087                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   16088                     dispatchDraw(canvas);
   16089                 } else {
   16090                     draw(canvas);
   16091                 }
   16092             }
   16093         } else if (cache != null) {
   16094             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
   16095             if (layerType == LAYER_TYPE_NONE) {
   16096                 // no layer paint, use temporary paint to draw bitmap
   16097                 Paint cachePaint = parent.mCachePaint;
   16098                 if (cachePaint == null) {
   16099                     cachePaint = new Paint();
   16100                     cachePaint.setDither(false);
   16101                     parent.mCachePaint = cachePaint;
   16102                 }
   16103                 cachePaint.setAlpha((int) (alpha * 255));
   16104                 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
   16105             } else {
   16106                 // use layer paint to draw the bitmap, merging the two alphas, but also restore
   16107                 int layerPaintAlpha = mLayerPaint.getAlpha();
   16108                 mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
   16109                 canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
   16110                 mLayerPaint.setAlpha(layerPaintAlpha);
   16111             }
   16112         }
   16113 
   16114         if (restoreTo >= 0) {
   16115             canvas.restoreToCount(restoreTo);
   16116         }
   16117 
   16118         if (a != null && !more) {
   16119             if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
   16120                 onSetAlpha(255);
   16121             }
   16122             parent.finishAnimatingView(this, a);
   16123         }
   16124 
   16125         if (more && hardwareAcceleratedCanvas) {
   16126             if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
   16127                 // alpha animations should cause the child to recreate its display list
   16128                 invalidate(true);
   16129             }
   16130         }
   16131 
   16132         mRecreateDisplayList = false;
   16133 
   16134         return more;
   16135     }
   16136 
   16137     /**
   16138      * Manually render this view (and all of its children) to the given Canvas.
   16139      * The view must have already done a full layout before this function is
   16140      * called.  When implementing a view, implement
   16141      * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
   16142      * If you do need to override this method, call the superclass version.
   16143      *
   16144      * @param canvas The Canvas to which the View is rendered.
   16145      */
   16146     @CallSuper
   16147     public void draw(Canvas canvas) {
   16148         final int privateFlags = mPrivateFlags;
   16149         final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
   16150                 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
   16151         mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
   16152 
   16153         /*
   16154          * Draw traversal performs several drawing steps which must be executed
   16155          * in the appropriate order:
   16156          *
   16157          *      1. Draw the background
   16158          *      2. If necessary, save the canvas' layers to prepare for fading
   16159          *      3. Draw view's content
   16160          *      4. Draw children
   16161          *      5. If necessary, draw the fading edges and restore layers
   16162          *      6. Draw decorations (scrollbars for instance)
   16163          */
   16164 
   16165         // Step 1, draw the background, if needed
   16166         int saveCount;
   16167 
   16168         if (!dirtyOpaque) {
   16169             drawBackground(canvas);
   16170         }
   16171 
   16172         // skip step 2 & 5 if possible (common case)
   16173         final int viewFlags = mViewFlags;
   16174         boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
   16175         boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
   16176         if (!verticalEdges && !horizontalEdges) {
   16177             // Step 3, draw the content
   16178             if (!dirtyOpaque) onDraw(canvas);
   16179 
   16180             // Step 4, draw the children
   16181             dispatchDraw(canvas);
   16182 
   16183             // Overlay is part of the content and draws beneath Foreground
   16184             if (mOverlay != null && !mOverlay.isEmpty()) {
   16185                 mOverlay.getOverlayView().dispatchDraw(canvas);
   16186             }
   16187 
   16188             // Step 6, draw decorations (foreground, scrollbars)
   16189             onDrawForeground(canvas);
   16190 
   16191             // we're done...
   16192             return;
   16193         }
   16194 
   16195         /*
   16196          * Here we do the full fledged routine...
   16197          * (this is an uncommon case where speed matters less,
   16198          * this is why we repeat some of the tests that have been
   16199          * done above)
   16200          */
   16201 
   16202         boolean drawTop = false;
   16203         boolean drawBottom = false;
   16204         boolean drawLeft = false;
   16205         boolean drawRight = false;
   16206 
   16207         float topFadeStrength = 0.0f;
   16208         float bottomFadeStrength = 0.0f;
   16209         float leftFadeStrength = 0.0f;
   16210         float rightFadeStrength = 0.0f;
   16211 
   16212         // Step 2, save the canvas' layers
   16213         int paddingLeft = mPaddingLeft;
   16214 
   16215         final boolean offsetRequired = isPaddingOffsetRequired();
   16216         if (offsetRequired) {
   16217             paddingLeft += getLeftPaddingOffset();
   16218         }
   16219 
   16220         int left = mScrollX + paddingLeft;
   16221         int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
   16222         int top = mScrollY + getFadeTop(offsetRequired);
   16223         int bottom = top + getFadeHeight(offsetRequired);
   16224 
   16225         if (offsetRequired) {
   16226             right += getRightPaddingOffset();
   16227             bottom += getBottomPaddingOffset();
   16228         }
   16229 
   16230         final ScrollabilityCache scrollabilityCache = mScrollCache;
   16231         final float fadeHeight = scrollabilityCache.fadingEdgeLength;
   16232         int length = (int) fadeHeight;
   16233 
   16234         // clip the fade length if top and bottom fades overlap
   16235         // overlapping fades produce odd-looking artifacts
   16236         if (verticalEdges && (top + length > bottom - length)) {
   16237             length = (bottom - top) / 2;
   16238         }
   16239 
   16240         // also clip horizontal fades if necessary
   16241         if (horizontalEdges && (left + length > right - length)) {
   16242             length = (right - left) / 2;
   16243         }
   16244 
   16245         if (verticalEdges) {
   16246             topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
   16247             drawTop = topFadeStrength * fadeHeight > 1.0f;
   16248             bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
   16249             drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
   16250         }
   16251 
   16252         if (horizontalEdges) {
   16253             leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
   16254             drawLeft = leftFadeStrength * fadeHeight > 1.0f;
   16255             rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
   16256             drawRight = rightFadeStrength * fadeHeight > 1.0f;
   16257         }
   16258 
   16259         saveCount = canvas.getSaveCount();
   16260 
   16261         int solidColor = getSolidColor();
   16262         if (solidColor == 0) {
   16263             final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
   16264 
   16265             if (drawTop) {
   16266                 canvas.saveLayer(left, top, right, top + length, null, flags);
   16267             }
   16268 
   16269             if (drawBottom) {
   16270                 canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
   16271             }
   16272 
   16273             if (drawLeft) {
   16274                 canvas.saveLayer(left, top, left + length, bottom, null, flags);
   16275             }
   16276 
   16277             if (drawRight) {
   16278                 canvas.saveLayer(right - length, top, right, bottom, null, flags);
   16279             }
   16280         } else {
   16281             scrollabilityCache.setFadeColor(solidColor);
   16282         }
   16283 
   16284         // Step 3, draw the content
   16285         if (!dirtyOpaque) onDraw(canvas);
   16286 
   16287         // Step 4, draw the children
   16288         dispatchDraw(canvas);
   16289 
   16290         // Step 5, draw the fade effect and restore layers
   16291         final Paint p = scrollabilityCache.paint;
   16292         final Matrix matrix = scrollabilityCache.matrix;
   16293         final Shader fade = scrollabilityCache.shader;
   16294 
   16295         if (drawTop) {
   16296             matrix.setScale(1, fadeHeight * topFadeStrength);
   16297             matrix.postTranslate(left, top);
   16298             fade.setLocalMatrix(matrix);
   16299             p.setShader(fade);
   16300             canvas.drawRect(left, top, right, top + length, p);
   16301         }
   16302 
   16303         if (drawBottom) {
   16304             matrix.setScale(1, fadeHeight * bottomFadeStrength);
   16305             matrix.postRotate(180);
   16306             matrix.postTranslate(left, bottom);
   16307             fade.setLocalMatrix(matrix);
   16308             p.setShader(fade);
   16309             canvas.drawRect(left, bottom - length, right, bottom, p);
   16310         }
   16311 
   16312         if (drawLeft) {
   16313             matrix.setScale(1, fadeHeight * leftFadeStrength);
   16314             matrix.postRotate(-90);
   16315             matrix.postTranslate(left, top);
   16316             fade.setLocalMatrix(matrix);
   16317             p.setShader(fade);
   16318             canvas.drawRect(left, top, left + length, bottom, p);
   16319         }
   16320 
   16321         if (drawRight) {
   16322             matrix.setScale(1, fadeHeight * rightFadeStrength);
   16323             matrix.postRotate(90);
   16324             matrix.postTranslate(right, top);
   16325             fade.setLocalMatrix(matrix);
   16326             p.setShader(fade);
   16327             canvas.drawRect(right - length, top, right, bottom, p);
   16328         }
   16329 
   16330         canvas.restoreToCount(saveCount);
   16331 
   16332         // Overlay is part of the content and draws beneath Foreground
   16333         if (mOverlay != null && !mOverlay.isEmpty()) {
   16334             mOverlay.getOverlayView().dispatchDraw(canvas);
   16335         }
   16336 
   16337         // Step 6, draw decorations (foreground, scrollbars)
   16338         onDrawForeground(canvas);
   16339     }
   16340 
   16341     /**
   16342      * Draws the background onto the specified canvas.
   16343      *
   16344      * @param canvas Canvas on which to draw the background
   16345      */
   16346     private void drawBackground(Canvas canvas) {
   16347         final Drawable background = mBackground;
   16348         if (background == null) {
   16349             return;
   16350         }
   16351 
   16352         setBackgroundBounds();
   16353 
   16354         // Attempt to use a display list if requested.
   16355         if (canvas.isHardwareAccelerated() && mAttachInfo != null
   16356                 && mAttachInfo.mHardwareRenderer != null) {
   16357             mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
   16358 
   16359             final RenderNode renderNode = mBackgroundRenderNode;
   16360             if (renderNode != null && renderNode.isValid()) {
   16361                 setBackgroundRenderNodeProperties(renderNode);
   16362                 ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
   16363                 return;
   16364             }
   16365         }
   16366 
   16367         final int scrollX = mScrollX;
   16368         final int scrollY = mScrollY;
   16369         if ((scrollX | scrollY) == 0) {
   16370             background.draw(canvas);
   16371         } else {
   16372             canvas.translate(scrollX, scrollY);
   16373             background.draw(canvas);
   16374             canvas.translate(-scrollX, -scrollY);
   16375         }
   16376     }
   16377 
   16378     /**
   16379      * Sets the correct background bounds and rebuilds the outline, if needed.
   16380      * <p/>
   16381      * This is called by LayoutLib.
   16382      */
   16383     void setBackgroundBounds() {
   16384         if (mBackgroundSizeChanged && mBackground != null) {
   16385             mBackground.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
   16386             mBackgroundSizeChanged = false;
   16387             rebuildOutline();
   16388         }
   16389     }
   16390 
   16391     private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
   16392         renderNode.setTranslationX(mScrollX);
   16393         renderNode.setTranslationY(mScrollY);
   16394     }
   16395 
   16396     /**
   16397      * Creates a new display list or updates the existing display list for the
   16398      * specified Drawable.
   16399      *
   16400      * @param drawable Drawable for which to create a display list
   16401      * @param renderNode Existing RenderNode, or {@code null}
   16402      * @return A valid display list for the specified drawable
   16403      */
   16404     private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
   16405         if (renderNode == null) {
   16406             renderNode = RenderNode.create(drawable.getClass().getName(), this);
   16407         }
   16408 
   16409         final Rect bounds = drawable.getBounds();
   16410         final int width = bounds.width();
   16411         final int height = bounds.height();
   16412         final DisplayListCanvas canvas = renderNode.start(width, height);
   16413 
   16414         // Reverse left/top translation done by drawable canvas, which will
   16415         // instead be applied by rendernode's LTRB bounds below. This way, the
   16416         // drawable's bounds match with its rendernode bounds and its content
   16417         // will lie within those bounds in the rendernode tree.
   16418         canvas.translate(-bounds.left, -bounds.top);
   16419 
   16420         try {
   16421             drawable.draw(canvas);
   16422         } finally {
   16423             renderNode.end(canvas);
   16424         }
   16425 
   16426         // Set up drawable properties that are view-independent.
   16427         renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
   16428         renderNode.setProjectBackwards(drawable.isProjected());
   16429         renderNode.setProjectionReceiver(true);
   16430         renderNode.setClipToBounds(false);
   16431         return renderNode;
   16432     }
   16433 
   16434     /**
   16435      * Returns the overlay for this view, creating it if it does not yet exist.
   16436      * Adding drawables to the overlay will cause them to be displayed whenever
   16437      * the view itself is redrawn. Objects in the overlay should be actively
   16438      * managed: remove them when they should not be displayed anymore. The
   16439      * overlay will always have the same size as its host view.
   16440      *
   16441      * <p>Note: Overlays do not currently work correctly with {@link
   16442      * SurfaceView} or {@link TextureView}; contents in overlays for these
   16443      * types of views may not display correctly.</p>
   16444      *
   16445      * @return The ViewOverlay object for this view.
   16446      * @see ViewOverlay
   16447      */
   16448     public ViewOverlay getOverlay() {
   16449         if (mOverlay == null) {
   16450             mOverlay = new ViewOverlay(mContext, this);
   16451         }
   16452         return mOverlay;
   16453     }
   16454 
   16455     /**
   16456      * Override this if your view is known to always be drawn on top of a solid color background,
   16457      * and needs to draw fading edges. Returning a non-zero color enables the view system to
   16458      * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
   16459      * should be set to 0xFF.
   16460      *
   16461      * @see #setVerticalFadingEdgeEnabled(boolean)
   16462      * @see #setHorizontalFadingEdgeEnabled(boolean)
   16463      *
   16464      * @return The known solid color background for this view, or 0 if the color may vary
   16465      */
   16466     @ViewDebug.ExportedProperty(category = "drawing")
   16467     @ColorInt
   16468     public int getSolidColor() {
   16469         return 0;
   16470     }
   16471 
   16472     /**
   16473      * Build a human readable string representation of the specified view flags.
   16474      *
   16475      * @param flags the view flags to convert to a string
   16476      * @return a String representing the supplied flags
   16477      */
   16478     private static String printFlags(int flags) {
   16479         String output = "";
   16480         int numFlags = 0;
   16481         if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
   16482             output += "TAKES_FOCUS";
   16483             numFlags++;
   16484         }
   16485 
   16486         switch (flags & VISIBILITY_MASK) {
   16487         case INVISIBLE:
   16488             if (numFlags > 0) {
   16489                 output += " ";
   16490             }
   16491             output += "INVISIBLE";
   16492             // USELESS HERE numFlags++;
   16493             break;
   16494         case GONE:
   16495             if (numFlags > 0) {
   16496                 output += " ";
   16497             }
   16498             output += "GONE";
   16499             // USELESS HERE numFlags++;
   16500             break;
   16501         default:
   16502             break;
   16503         }
   16504         return output;
   16505     }
   16506 
   16507     /**
   16508      * Build a human readable string representation of the specified private
   16509      * view flags.
   16510      *
   16511      * @param privateFlags the private view flags to convert to a string
   16512      * @return a String representing the supplied flags
   16513      */
   16514     private static String printPrivateFlags(int privateFlags) {
   16515         String output = "";
   16516         int numFlags = 0;
   16517 
   16518         if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
   16519             output += "WANTS_FOCUS";
   16520             numFlags++;
   16521         }
   16522 
   16523         if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
   16524             if (numFlags > 0) {
   16525                 output += " ";
   16526             }
   16527             output += "FOCUSED";
   16528             numFlags++;
   16529         }
   16530 
   16531         if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
   16532             if (numFlags > 0) {
   16533                 output += " ";
   16534             }
   16535             output += "SELECTED";
   16536             numFlags++;
   16537         }
   16538 
   16539         if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
   16540             if (numFlags > 0) {
   16541                 output += " ";
   16542             }
   16543             output += "IS_ROOT_NAMESPACE";
   16544             numFlags++;
   16545         }
   16546 
   16547         if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
   16548             if (numFlags > 0) {
   16549                 output += " ";
   16550             }
   16551             output += "HAS_BOUNDS";
   16552             numFlags++;
   16553         }
   16554 
   16555         if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
   16556             if (numFlags > 0) {
   16557                 output += " ";
   16558             }
   16559             output += "DRAWN";
   16560             // USELESS HERE numFlags++;
   16561         }
   16562         return output;
   16563     }
   16564 
   16565     /**
   16566      * <p>Indicates whether or not this view's layout will be requested during
   16567      * the next hierarchy layout pass.</p>
   16568      *
   16569      * @return true if the layout will be forced during next layout pass
   16570      */
   16571     public boolean isLayoutRequested() {
   16572         return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
   16573     }
   16574 
   16575     /**
   16576      * Return true if o is a ViewGroup that is laying out using optical bounds.
   16577      * @hide
   16578      */
   16579     public static boolean isLayoutModeOptical(Object o) {
   16580         return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
   16581     }
   16582 
   16583     private boolean setOpticalFrame(int left, int top, int right, int bottom) {
   16584         Insets parentInsets = mParent instanceof View ?
   16585                 ((View) mParent).getOpticalInsets() : Insets.NONE;
   16586         Insets childInsets = getOpticalInsets();
   16587         return setFrame(
   16588                 left   + parentInsets.left - childInsets.left,
   16589                 top    + parentInsets.top  - childInsets.top,
   16590                 right  + parentInsets.left + childInsets.right,
   16591                 bottom + parentInsets.top  + childInsets.bottom);
   16592     }
   16593 
   16594     /**
   16595      * Assign a size and position to a view and all of its
   16596      * descendants
   16597      *
   16598      * <p>This is the second phase of the layout mechanism.
   16599      * (The first is measuring). In this phase, each parent calls
   16600      * layout on all of its children to position them.
   16601      * This is typically done using the child measurements
   16602      * that were stored in the measure pass().</p>
   16603      *
   16604      * <p>Derived classes should not override this method.
   16605      * Derived classes with children should override
   16606      * onLayout. In that method, they should
   16607      * call layout on each of their children.</p>
   16608      *
   16609      * @param l Left position, relative to parent
   16610      * @param t Top position, relative to parent
   16611      * @param r Right position, relative to parent
   16612      * @param b Bottom position, relative to parent
   16613      */
   16614     @SuppressWarnings({"unchecked"})
   16615     public void layout(int l, int t, int r, int b) {
   16616         if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
   16617             onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
   16618             mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
   16619         }
   16620 
   16621         int oldL = mLeft;
   16622         int oldT = mTop;
   16623         int oldB = mBottom;
   16624         int oldR = mRight;
   16625 
   16626         boolean changed = isLayoutModeOptical(mParent) ?
   16627                 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
   16628 
   16629         if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
   16630             onLayout(changed, l, t, r, b);
   16631             mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
   16632 
   16633             ListenerInfo li = mListenerInfo;
   16634             if (li != null && li.mOnLayoutChangeListeners != null) {
   16635                 ArrayList<OnLayoutChangeListener> listenersCopy =
   16636                         (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
   16637                 int numListeners = listenersCopy.size();
   16638                 for (int i = 0; i < numListeners; ++i) {
   16639                     listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
   16640                 }
   16641             }
   16642         }
   16643 
   16644         mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
   16645         mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
   16646     }
   16647 
   16648     /**
   16649      * Called from layout when this view should
   16650      * assign a size and position to each of its children.
   16651      *
   16652      * Derived classes with children should override
   16653      * this method and call layout on each of
   16654      * their children.
   16655      * @param changed This is a new size or position for this view
   16656      * @param left Left position, relative to parent
   16657      * @param top Top position, relative to parent
   16658      * @param right Right position, relative to parent
   16659      * @param bottom Bottom position, relative to parent
   16660      */
   16661     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
   16662     }
   16663 
   16664     /**
   16665      * Assign a size and position to this view.
   16666      *
   16667      * This is called from layout.
   16668      *
   16669      * @param left Left position, relative to parent
   16670      * @param top Top position, relative to parent
   16671      * @param right Right position, relative to parent
   16672      * @param bottom Bottom position, relative to parent
   16673      * @return true if the new size and position are different than the
   16674      *         previous ones
   16675      * {@hide}
   16676      */
   16677     protected boolean setFrame(int left, int top, int right, int bottom) {
   16678         boolean changed = false;
   16679 
   16680         if (DBG) {
   16681             Log.d("View", this + " View.setFrame(" + left + "," + top + ","
   16682                     + right + "," + bottom + ")");
   16683         }
   16684 
   16685         if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
   16686             changed = true;
   16687 
   16688             // Remember our drawn bit
   16689             int drawn = mPrivateFlags & PFLAG_DRAWN;
   16690 
   16691             int oldWidth = mRight - mLeft;
   16692             int oldHeight = mBottom - mTop;
   16693             int newWidth = right - left;
   16694             int newHeight = bottom - top;
   16695             boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
   16696 
   16697             // Invalidate our old position
   16698             invalidate(sizeChanged);
   16699 
   16700             mLeft = left;
   16701             mTop = top;
   16702             mRight = right;
   16703             mBottom = bottom;
   16704             mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
   16705 
   16706             mPrivateFlags |= PFLAG_HAS_BOUNDS;
   16707 
   16708 
   16709             if (sizeChanged) {
   16710                 sizeChange(newWidth, newHeight, oldWidth, oldHeight);
   16711             }
   16712 
   16713             if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
   16714                 // If we are visible, force the DRAWN bit to on so that
   16715                 // this invalidate will go through (at least to our parent).
   16716                 // This is because someone may have invalidated this view
   16717                 // before this call to setFrame came in, thereby clearing
   16718                 // the DRAWN bit.
   16719                 mPrivateFlags |= PFLAG_DRAWN;
   16720                 invalidate(sizeChanged);
   16721                 // parent display list may need to be recreated based on a change in the bounds
   16722                 // of any child
   16723                 invalidateParentCaches();
   16724             }
   16725 
   16726             // Reset drawn bit to original value (invalidate turns it off)
   16727             mPrivateFlags |= drawn;
   16728 
   16729             mBackgroundSizeChanged = true;
   16730             if (mForegroundInfo != null) {
   16731                 mForegroundInfo.mBoundsChanged = true;
   16732             }
   16733 
   16734             notifySubtreeAccessibilityStateChangedIfNeeded();
   16735         }
   16736         return changed;
   16737     }
   16738 
   16739     /**
   16740      * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
   16741      * @hide
   16742      */
   16743     public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
   16744         setFrame(left, top, right, bottom);
   16745     }
   16746 
   16747     private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
   16748         onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
   16749         if (mOverlay != null) {
   16750             mOverlay.getOverlayView().setRight(newWidth);
   16751             mOverlay.getOverlayView().setBottom(newHeight);
   16752         }
   16753         rebuildOutline();
   16754     }
   16755 
   16756     /**
   16757      * Finalize inflating a view from XML.  This is called as the last phase
   16758      * of inflation, after all child views have been added.
   16759      *
   16760      * <p>Even if the subclass overrides onFinishInflate, they should always be
   16761      * sure to call the super method, so that we get called.
   16762      */
   16763     @CallSuper
   16764     protected void onFinishInflate() {
   16765     }
   16766 
   16767     /**
   16768      * Returns the resources associated with this view.
   16769      *
   16770      * @return Resources object.
   16771      */
   16772     public Resources getResources() {
   16773         return mResources;
   16774     }
   16775 
   16776     /**
   16777      * Invalidates the specified Drawable.
   16778      *
   16779      * @param drawable the drawable to invalidate
   16780      */
   16781     @Override
   16782     public void invalidateDrawable(@NonNull Drawable drawable) {
   16783         if (verifyDrawable(drawable)) {
   16784             final Rect dirty = drawable.getDirtyBounds();
   16785             final int scrollX = mScrollX;
   16786             final int scrollY = mScrollY;
   16787 
   16788             invalidate(dirty.left + scrollX, dirty.top + scrollY,
   16789                     dirty.right + scrollX, dirty.bottom + scrollY);
   16790             rebuildOutline();
   16791         }
   16792     }
   16793 
   16794     /**
   16795      * Schedules an action on a drawable to occur at a specified time.
   16796      *
   16797      * @param who the recipient of the action
   16798      * @param what the action to run on the drawable
   16799      * @param when the time at which the action must occur. Uses the
   16800      *        {@link SystemClock#uptimeMillis} timebase.
   16801      */
   16802     @Override
   16803     public void scheduleDrawable(Drawable who, Runnable what, long when) {
   16804         if (verifyDrawable(who) && what != null) {
   16805             final long delay = when - SystemClock.uptimeMillis();
   16806             if (mAttachInfo != null) {
   16807                 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
   16808                         Choreographer.CALLBACK_ANIMATION, what, who,
   16809                         Choreographer.subtractFrameDelay(delay));
   16810             } else {
   16811                 ViewRootImpl.getRunQueue().postDelayed(what, delay);
   16812             }
   16813         }
   16814     }
   16815 
   16816     /**
   16817      * Cancels a scheduled action on a drawable.
   16818      *
   16819      * @param who the recipient of the action
   16820      * @param what the action to cancel
   16821      */
   16822     @Override
   16823     public void unscheduleDrawable(Drawable who, Runnable what) {
   16824         if (verifyDrawable(who) && what != null) {
   16825             if (mAttachInfo != null) {
   16826                 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
   16827                         Choreographer.CALLBACK_ANIMATION, what, who);
   16828             }
   16829             ViewRootImpl.getRunQueue().removeCallbacks(what);
   16830         }
   16831     }
   16832 
   16833     /**
   16834      * Unschedule any events associated with the given Drawable.  This can be
   16835      * used when selecting a new Drawable into a view, so that the previous
   16836      * one is completely unscheduled.
   16837      *
   16838      * @param who The Drawable to unschedule.
   16839      *
   16840      * @see #drawableStateChanged
   16841      */
   16842     public void unscheduleDrawable(Drawable who) {
   16843         if (mAttachInfo != null && who != null) {
   16844             mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
   16845                     Choreographer.CALLBACK_ANIMATION, null, who);
   16846         }
   16847     }
   16848 
   16849     /**
   16850      * Resolve the Drawables depending on the layout direction. This is implicitly supposing
   16851      * that the View directionality can and will be resolved before its Drawables.
   16852      *
   16853      * Will call {@link View#onResolveDrawables} when resolution is done.
   16854      *
   16855      * @hide
   16856      */
   16857     protected void resolveDrawables() {
   16858         // Drawables resolution may need to happen before resolving the layout direction (which is
   16859         // done only during the measure() call).
   16860         // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
   16861         // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
   16862         // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
   16863         // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
   16864         // direction to be resolved as its resolved value will be the same as its raw value.
   16865         if (!isLayoutDirectionResolved() &&
   16866                 getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
   16867             return;
   16868         }
   16869 
   16870         final int layoutDirection = isLayoutDirectionResolved() ?
   16871                 getLayoutDirection() : getRawLayoutDirection();
   16872 
   16873         if (mBackground != null) {
   16874             mBackground.setLayoutDirection(layoutDirection);
   16875         }
   16876         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
   16877             mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
   16878         }
   16879         mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
   16880         onResolveDrawables(layoutDirection);
   16881     }
   16882 
   16883     boolean areDrawablesResolved() {
   16884         return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
   16885     }
   16886 
   16887     /**
   16888      * Called when layout direction has been resolved.
   16889      *
   16890      * The default implementation does nothing.
   16891      *
   16892      * @param layoutDirection The resolved layout direction.
   16893      *
   16894      * @see #LAYOUT_DIRECTION_LTR
   16895      * @see #LAYOUT_DIRECTION_RTL
   16896      *
   16897      * @hide
   16898      */
   16899     public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
   16900     }
   16901 
   16902     /**
   16903      * @hide
   16904      */
   16905     protected void resetResolvedDrawables() {
   16906         resetResolvedDrawablesInternal();
   16907     }
   16908 
   16909     void resetResolvedDrawablesInternal() {
   16910         mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
   16911     }
   16912 
   16913     /**
   16914      * If your view subclass is displaying its own Drawable objects, it should
   16915      * override this function and return true for any Drawable it is
   16916      * displaying.  This allows animations for those drawables to be
   16917      * scheduled.
   16918      *
   16919      * <p>Be sure to call through to the super class when overriding this
   16920      * function.
   16921      *
   16922      * @param who The Drawable to verify.  Return true if it is one you are
   16923      *            displaying, else return the result of calling through to the
   16924      *            super class.
   16925      *
   16926      * @return boolean If true than the Drawable is being displayed in the
   16927      *         view; else false and it is not allowed to animate.
   16928      *
   16929      * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
   16930      * @see #drawableStateChanged()
   16931      */
   16932     @CallSuper
   16933     protected boolean verifyDrawable(Drawable who) {
   16934         return who == mBackground || (mScrollCache != null && mScrollCache.scrollBar == who)
   16935                 || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
   16936     }
   16937 
   16938     /**
   16939      * This function is called whenever the state of the view changes in such
   16940      * a way that it impacts the state of drawables being shown.
   16941      * <p>
   16942      * If the View has a StateListAnimator, it will also be called to run necessary state
   16943      * change animations.
   16944      * <p>
   16945      * Be sure to call through to the superclass when overriding this function.
   16946      *
   16947      * @see Drawable#setState(int[])
   16948      */
   16949     @CallSuper
   16950     protected void drawableStateChanged() {
   16951         final int[] state = getDrawableState();
   16952 
   16953         final Drawable bg = mBackground;
   16954         if (bg != null && bg.isStateful()) {
   16955             bg.setState(state);
   16956         }
   16957 
   16958         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
   16959         if (fg != null && fg.isStateful()) {
   16960             fg.setState(state);
   16961         }
   16962 
   16963         if (mScrollCache != null) {
   16964             final Drawable scrollBar = mScrollCache.scrollBar;
   16965             if (scrollBar != null && scrollBar.isStateful()) {
   16966                 scrollBar.setState(state);
   16967             }
   16968         }
   16969 
   16970         if (mStateListAnimator != null) {
   16971             mStateListAnimator.setState(state);
   16972         }
   16973     }
   16974 
   16975     /**
   16976      * This function is called whenever the view hotspot changes and needs to
   16977      * be propagated to drawables or child views managed by the view.
   16978      * <p>
   16979      * Dispatching to child views is handled by
   16980      * {@link #dispatchDrawableHotspotChanged(float, float)}.
   16981      * <p>
   16982      * Be sure to call through to the superclass when overriding this function.
   16983      *
   16984      * @param x hotspot x coordinate
   16985      * @param y hotspot y coordinate
   16986      */
   16987     @CallSuper
   16988     public void drawableHotspotChanged(float x, float y) {
   16989         if (mBackground != null) {
   16990             mBackground.setHotspot(x, y);
   16991         }
   16992         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
   16993             mForegroundInfo.mDrawable.setHotspot(x, y);
   16994         }
   16995 
   16996         dispatchDrawableHotspotChanged(x, y);
   16997     }
   16998 
   16999     /**
   17000      * Dispatches drawableHotspotChanged to all of this View's children.
   17001      *
   17002      * @param x hotspot x coordinate
   17003      * @param y hotspot y coordinate
   17004      * @see #drawableHotspotChanged(float, float)
   17005      */
   17006     public void dispatchDrawableHotspotChanged(float x, float y) {
   17007     }
   17008 
   17009     /**
   17010      * Call this to force a view to update its drawable state. This will cause
   17011      * drawableStateChanged to be called on this view. Views that are interested
   17012      * in the new state should call getDrawableState.
   17013      *
   17014      * @see #drawableStateChanged
   17015      * @see #getDrawableState
   17016      */
   17017     public void refreshDrawableState() {
   17018         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
   17019         drawableStateChanged();
   17020 
   17021         ViewParent parent = mParent;
   17022         if (parent != null) {
   17023             parent.childDrawableStateChanged(this);
   17024         }
   17025     }
   17026 
   17027     /**
   17028      * Return an array of resource IDs of the drawable states representing the
   17029      * current state of the view.
   17030      *
   17031      * @return The current drawable state
   17032      *
   17033      * @see Drawable#setState(int[])
   17034      * @see #drawableStateChanged()
   17035      * @see #onCreateDrawableState(int)
   17036      */
   17037     public final int[] getDrawableState() {
   17038         if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
   17039             return mDrawableState;
   17040         } else {
   17041             mDrawableState = onCreateDrawableState(0);
   17042             mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
   17043             return mDrawableState;
   17044         }
   17045     }
   17046 
   17047     /**
   17048      * Generate the new {@link android.graphics.drawable.Drawable} state for
   17049      * this view. This is called by the view
   17050      * system when the cached Drawable state is determined to be invalid.  To
   17051      * retrieve the current state, you should use {@link #getDrawableState}.
   17052      *
   17053      * @param extraSpace if non-zero, this is the number of extra entries you
   17054      * would like in the returned array in which you can place your own
   17055      * states.
   17056      *
   17057      * @return Returns an array holding the current {@link Drawable} state of
   17058      * the view.
   17059      *
   17060      * @see #mergeDrawableStates(int[], int[])
   17061      */
   17062     protected int[] onCreateDrawableState(int extraSpace) {
   17063         if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
   17064                 mParent instanceof View) {
   17065             return ((View) mParent).onCreateDrawableState(extraSpace);
   17066         }
   17067 
   17068         int[] drawableState;
   17069 
   17070         int privateFlags = mPrivateFlags;
   17071 
   17072         int viewStateIndex = 0;
   17073         if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
   17074         if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
   17075         if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
   17076         if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
   17077         if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
   17078         if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
   17079         if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
   17080                 HardwareRenderer.isAvailable()) {
   17081             // This is set if HW acceleration is requested, even if the current
   17082             // process doesn't allow it.  This is just to allow app preview
   17083             // windows to better match their app.
   17084             viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
   17085         }
   17086         if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
   17087 
   17088         final int privateFlags2 = mPrivateFlags2;
   17089         if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
   17090             viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
   17091         }
   17092         if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
   17093             viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
   17094         }
   17095 
   17096         drawableState = StateSet.get(viewStateIndex);
   17097 
   17098         //noinspection ConstantIfStatement
   17099         if (false) {
   17100             Log.i("View", "drawableStateIndex=" + viewStateIndex);
   17101             Log.i("View", toString()
   17102                     + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
   17103                     + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
   17104                     + " fo=" + hasFocus()
   17105                     + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
   17106                     + " wf=" + hasWindowFocus()
   17107                     + ": " + Arrays.toString(drawableState));
   17108         }
   17109 
   17110         if (extraSpace == 0) {
   17111             return drawableState;
   17112         }
   17113 
   17114         final int[] fullState;
   17115         if (drawableState != null) {
   17116             fullState = new int[drawableState.length + extraSpace];
   17117             System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
   17118         } else {
   17119             fullState = new int[extraSpace];
   17120         }
   17121 
   17122         return fullState;
   17123     }
   17124 
   17125     /**
   17126      * Merge your own state values in <var>additionalState</var> into the base
   17127      * state values <var>baseState</var> that were returned by
   17128      * {@link #onCreateDrawableState(int)}.
   17129      *
   17130      * @param baseState The base state values returned by
   17131      * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
   17132      * own additional state values.
   17133      *
   17134      * @param additionalState The additional state values you would like
   17135      * added to <var>baseState</var>; this array is not modified.
   17136      *
   17137      * @return As a convenience, the <var>baseState</var> array you originally
   17138      * passed into the function is returned.
   17139      *
   17140      * @see #onCreateDrawableState(int)
   17141      */
   17142     protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
   17143         final int N = baseState.length;
   17144         int i = N - 1;
   17145         while (i >= 0 && baseState[i] == 0) {
   17146             i--;
   17147         }
   17148         System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
   17149         return baseState;
   17150     }
   17151 
   17152     /**
   17153      * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
   17154      * on all Drawable objects associated with this view.
   17155      * <p>
   17156      * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
   17157      * attached to this view.
   17158      */
   17159     @CallSuper
   17160     public void jumpDrawablesToCurrentState() {
   17161         if (mBackground != null) {
   17162             mBackground.jumpToCurrentState();
   17163         }
   17164         if (mStateListAnimator != null) {
   17165             mStateListAnimator.jumpToCurrentState();
   17166         }
   17167         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
   17168             mForegroundInfo.mDrawable.jumpToCurrentState();
   17169         }
   17170     }
   17171 
   17172     /**
   17173      * Sets the background color for this view.
   17174      * @param color the color of the background
   17175      */
   17176     @RemotableViewMethod
   17177     public void setBackgroundColor(@ColorInt int color) {
   17178         if (mBackground instanceof ColorDrawable) {
   17179             ((ColorDrawable) mBackground.mutate()).setColor(color);
   17180             computeOpaqueFlags();
   17181             mBackgroundResource = 0;
   17182         } else {
   17183             setBackground(new ColorDrawable(color));
   17184         }
   17185     }
   17186 
   17187     /**
   17188      * Set the background to a given resource. The resource should refer to
   17189      * a Drawable object or 0 to remove the background.
   17190      * @param resid The identifier of the resource.
   17191      *
   17192      * @attr ref android.R.styleable#View_background
   17193      */
   17194     @RemotableViewMethod
   17195     public void setBackgroundResource(@DrawableRes int resid) {
   17196         if (resid != 0 && resid == mBackgroundResource) {
   17197             return;
   17198         }
   17199 
   17200         Drawable d = null;
   17201         if (resid != 0) {
   17202             d = mContext.getDrawable(resid);
   17203         }
   17204         setBackground(d);
   17205 
   17206         mBackgroundResource = resid;
   17207     }
   17208 
   17209     /**
   17210      * Set the background to a given Drawable, or remove the background. If the
   17211      * background has padding, this View's padding is set to the background's
   17212      * padding. However, when a background is removed, this View's padding isn't
   17213      * touched. If setting the padding is desired, please use
   17214      * {@link #setPadding(int, int, int, int)}.
   17215      *
   17216      * @param background The Drawable to use as the background, or null to remove the
   17217      *        background
   17218      */
   17219     public void setBackground(Drawable background) {
   17220         //noinspection deprecation
   17221         setBackgroundDrawable(background);
   17222     }
   17223 
   17224     /**
   17225      * @deprecated use {@link #setBackground(Drawable)} instead
   17226      */
   17227     @Deprecated
   17228     public void setBackgroundDrawable(Drawable background) {
   17229         computeOpaqueFlags();
   17230 
   17231         if (background == mBackground) {
   17232             return;
   17233         }
   17234 
   17235         boolean requestLayout = false;
   17236 
   17237         mBackgroundResource = 0;
   17238 
   17239         /*
   17240          * Regardless of whether we're setting a new background or not, we want
   17241          * to clear the previous drawable.
   17242          */
   17243         if (mBackground != null) {
   17244             mBackground.setCallback(null);
   17245             unscheduleDrawable(mBackground);
   17246         }
   17247 
   17248         if (background != null) {
   17249             Rect padding = sThreadLocal.get();
   17250             if (padding == null) {
   17251                 padding = new Rect();
   17252                 sThreadLocal.set(padding);
   17253             }
   17254             resetResolvedDrawablesInternal();
   17255             background.setLayoutDirection(getLayoutDirection());
   17256             if (background.getPadding(padding)) {
   17257                 resetResolvedPaddingInternal();
   17258                 switch (background.getLayoutDirection()) {
   17259                     case LAYOUT_DIRECTION_RTL:
   17260                         mUserPaddingLeftInitial = padding.right;
   17261                         mUserPaddingRightInitial = padding.left;
   17262                         internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
   17263                         break;
   17264                     case LAYOUT_DIRECTION_LTR:
   17265                     default:
   17266                         mUserPaddingLeftInitial = padding.left;
   17267                         mUserPaddingRightInitial = padding.right;
   17268                         internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
   17269                 }
   17270                 mLeftPaddingDefined = false;
   17271                 mRightPaddingDefined = false;
   17272             }
   17273 
   17274             // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
   17275             // if it has a different minimum size, we should layout again
   17276             if (mBackground == null
   17277                     || mBackground.getMinimumHeight() != background.getMinimumHeight()
   17278                     || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
   17279                 requestLayout = true;
   17280             }
   17281 
   17282             background.setCallback(this);
   17283             if (background.isStateful()) {
   17284                 background.setState(getDrawableState());
   17285             }
   17286             background.setVisible(getVisibility() == VISIBLE, false);
   17287             mBackground = background;
   17288 
   17289             applyBackgroundTint();
   17290 
   17291             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
   17292                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
   17293                 requestLayout = true;
   17294             }
   17295         } else {
   17296             /* Remove the background */
   17297             mBackground = null;
   17298             if ((mViewFlags & WILL_NOT_DRAW) != 0
   17299                     && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
   17300                 mPrivateFlags |= PFLAG_SKIP_DRAW;
   17301             }
   17302 
   17303             /*
   17304              * When the background is set, we try to apply its padding to this
   17305              * View. When the background is removed, we don't touch this View's
   17306              * padding. This is noted in the Javadocs. Hence, we don't need to
   17307              * requestLayout(), the invalidate() below is sufficient.
   17308              */
   17309 
   17310             // The old background's minimum size could have affected this
   17311             // View's layout, so let's requestLayout
   17312             requestLayout = true;
   17313         }
   17314 
   17315         computeOpaqueFlags();
   17316 
   17317         if (requestLayout) {
   17318             requestLayout();
   17319         }
   17320 
   17321         mBackgroundSizeChanged = true;
   17322         invalidate(true);
   17323     }
   17324 
   17325     /**
   17326      * Gets the background drawable
   17327      *
   17328      * @return The drawable used as the background for this view, if any.
   17329      *
   17330      * @see #setBackground(Drawable)
   17331      *
   17332      * @attr ref android.R.styleable#View_background
   17333      */
   17334     public Drawable getBackground() {
   17335         return mBackground;
   17336     }
   17337 
   17338     /**
   17339      * Applies a tint to the background drawable. Does not modify the current tint
   17340      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
   17341      * <p>
   17342      * Subsequent calls to {@link #setBackground(Drawable)} will automatically
   17343      * mutate the drawable and apply the specified tint and tint mode using
   17344      * {@link Drawable#setTintList(ColorStateList)}.
   17345      *
   17346      * @param tint the tint to apply, may be {@code null} to clear tint
   17347      *
   17348      * @attr ref android.R.styleable#View_backgroundTint
   17349      * @see #getBackgroundTintList()
   17350      * @see Drawable#setTintList(ColorStateList)
   17351      */
   17352     public void setBackgroundTintList(@Nullable ColorStateList tint) {
   17353         if (mBackgroundTint == null) {
   17354             mBackgroundTint = new TintInfo();
   17355         }
   17356         mBackgroundTint.mTintList = tint;
   17357         mBackgroundTint.mHasTintList = true;
   17358 
   17359         applyBackgroundTint();
   17360     }
   17361 
   17362     /**
   17363      * Return the tint applied to the background drawable, if specified.
   17364      *
   17365      * @return the tint applied to the background drawable
   17366      * @attr ref android.R.styleable#View_backgroundTint
   17367      * @see #setBackgroundTintList(ColorStateList)
   17368      */
   17369     @Nullable
   17370     public ColorStateList getBackgroundTintList() {
   17371         return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
   17372     }
   17373 
   17374     /**
   17375      * Specifies the blending mode used to apply the tint specified by
   17376      * {@link #setBackgroundTintList(ColorStateList)}} to the background
   17377      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
   17378      *
   17379      * @param tintMode the blending mode used to apply the tint, may be
   17380      *                 {@code null} to clear tint
   17381      * @attr ref android.R.styleable#View_backgroundTintMode
   17382      * @see #getBackgroundTintMode()
   17383      * @see Drawable#setTintMode(PorterDuff.Mode)
   17384      */
   17385     public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
   17386         if (mBackgroundTint == null) {
   17387             mBackgroundTint = new TintInfo();
   17388         }
   17389         mBackgroundTint.mTintMode = tintMode;
   17390         mBackgroundTint.mHasTintMode = true;
   17391 
   17392         applyBackgroundTint();
   17393     }
   17394 
   17395     /**
   17396      * Return the blending mode used to apply the tint to the background
   17397      * drawable, if specified.
   17398      *
   17399      * @return the blending mode used to apply the tint to the background
   17400      *         drawable
   17401      * @attr ref android.R.styleable#View_backgroundTintMode
   17402      * @see #setBackgroundTintMode(PorterDuff.Mode)
   17403      */
   17404     @Nullable
   17405     public PorterDuff.Mode getBackgroundTintMode() {
   17406         return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
   17407     }
   17408 
   17409     private void applyBackgroundTint() {
   17410         if (mBackground != null && mBackgroundTint != null) {
   17411             final TintInfo tintInfo = mBackgroundTint;
   17412             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
   17413                 mBackground = mBackground.mutate();
   17414 
   17415                 if (tintInfo.mHasTintList) {
   17416                     mBackground.setTintList(tintInfo.mTintList);
   17417                 }
   17418 
   17419                 if (tintInfo.mHasTintMode) {
   17420                     mBackground.setTintMode(tintInfo.mTintMode);
   17421                 }
   17422 
   17423                 // The drawable (or one of its children) may not have been
   17424                 // stateful before applying the tint, so let's try again.
   17425                 if (mBackground.isStateful()) {
   17426                     mBackground.setState(getDrawableState());
   17427                 }
   17428             }
   17429         }
   17430     }
   17431 
   17432     /**
   17433      * Returns the drawable used as the foreground of this View. The
   17434      * foreground drawable, if non-null, is always drawn on top of the view's content.
   17435      *
   17436      * @return a Drawable or null if no foreground was set
   17437      *
   17438      * @see #onDrawForeground(Canvas)
   17439      */
   17440     public Drawable getForeground() {
   17441         return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
   17442     }
   17443 
   17444     /**
   17445      * Supply a Drawable that is to be rendered on top of all of the content in the view.
   17446      *
   17447      * @param foreground the Drawable to be drawn on top of the children
   17448      *
   17449      * @attr ref android.R.styleable#View_foreground
   17450      */
   17451     public void setForeground(Drawable foreground) {
   17452         if (mForegroundInfo == null) {
   17453             if (foreground == null) {
   17454                 // Nothing to do.
   17455                 return;
   17456             }
   17457             mForegroundInfo = new ForegroundInfo();
   17458         }
   17459 
   17460         if (foreground == mForegroundInfo.mDrawable) {
   17461             // Nothing to do
   17462             return;
   17463         }
   17464 
   17465         if (mForegroundInfo.mDrawable != null) {
   17466             mForegroundInfo.mDrawable.setCallback(null);
   17467             unscheduleDrawable(mForegroundInfo.mDrawable);
   17468         }
   17469 
   17470         mForegroundInfo.mDrawable = foreground;
   17471         mForegroundInfo.mBoundsChanged = true;
   17472         if (foreground != null) {
   17473             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
   17474                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
   17475             }
   17476             foreground.setCallback(this);
   17477             foreground.setLayoutDirection(getLayoutDirection());
   17478             if (foreground.isStateful()) {
   17479                 foreground.setState(getDrawableState());
   17480             }
   17481             applyForegroundTint();
   17482         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
   17483             mPrivateFlags |= PFLAG_SKIP_DRAW;
   17484         }
   17485         requestLayout();
   17486         invalidate();
   17487     }
   17488 
   17489     /**
   17490      * Magic bit used to support features of framework-internal window decor implementation details.
   17491      * This used to live exclusively in FrameLayout.
   17492      *
   17493      * @return true if the foreground should draw inside the padding region or false
   17494      *         if it should draw inset by the view's padding
   17495      * @hide internal use only; only used by FrameLayout and internal screen layouts.
   17496      */
   17497     public boolean isForegroundInsidePadding() {
   17498         return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
   17499     }
   17500 
   17501     /**
   17502      * Describes how the foreground is positioned.
   17503      *
   17504      * @return foreground gravity.
   17505      *
   17506      * @see #setForegroundGravity(int)
   17507      *
   17508      * @attr ref android.R.styleable#View_foregroundGravity
   17509      */
   17510     public int getForegroundGravity() {
   17511         return mForegroundInfo != null ? mForegroundInfo.mGravity
   17512                 : Gravity.START | Gravity.TOP;
   17513     }
   17514 
   17515     /**
   17516      * Describes how the foreground is positioned. Defaults to START and TOP.
   17517      *
   17518      * @param gravity see {@link android.view.Gravity}
   17519      *
   17520      * @see #getForegroundGravity()
   17521      *
   17522      * @attr ref android.R.styleable#View_foregroundGravity
   17523      */
   17524     public void setForegroundGravity(int gravity) {
   17525         if (mForegroundInfo == null) {
   17526             mForegroundInfo = new ForegroundInfo();
   17527         }
   17528 
   17529         if (mForegroundInfo.mGravity != gravity) {
   17530             if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
   17531                 gravity |= Gravity.START;
   17532             }
   17533 
   17534             if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
   17535                 gravity |= Gravity.TOP;
   17536             }
   17537 
   17538             mForegroundInfo.mGravity = gravity;
   17539             requestLayout();
   17540         }
   17541     }
   17542 
   17543     /**
   17544      * Applies a tint to the foreground drawable. Does not modify the current tint
   17545      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
   17546      * <p>
   17547      * Subsequent calls to {@link #setForeground(Drawable)} will automatically
   17548      * mutate the drawable and apply the specified tint and tint mode using
   17549      * {@link Drawable#setTintList(ColorStateList)}.
   17550      *
   17551      * @param tint the tint to apply, may be {@code null} to clear tint
   17552      *
   17553      * @attr ref android.R.styleable#View_foregroundTint
   17554      * @see #getForegroundTintList()
   17555      * @see Drawable#setTintList(ColorStateList)
   17556      */
   17557     public void setForegroundTintList(@Nullable ColorStateList tint) {
   17558         if (mForegroundInfo == null) {
   17559             mForegroundInfo = new ForegroundInfo();
   17560         }
   17561         if (mForegroundInfo.mTintInfo == null) {
   17562             mForegroundInfo.mTintInfo = new TintInfo();
   17563         }
   17564         mForegroundInfo.mTintInfo.mTintList = tint;
   17565         mForegroundInfo.mTintInfo.mHasTintList = true;
   17566 
   17567         applyForegroundTint();
   17568     }
   17569 
   17570     /**
   17571      * Return the tint applied to the foreground drawable, if specified.
   17572      *
   17573      * @return the tint applied to the foreground drawable
   17574      * @attr ref android.R.styleable#View_foregroundTint
   17575      * @see #setForegroundTintList(ColorStateList)
   17576      */
   17577     @Nullable
   17578     public ColorStateList getForegroundTintList() {
   17579         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
   17580                 ? mForegroundInfo.mTintInfo.mTintList : null;
   17581     }
   17582 
   17583     /**
   17584      * Specifies the blending mode used to apply the tint specified by
   17585      * {@link #setForegroundTintList(ColorStateList)}} to the background
   17586      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
   17587      *
   17588      * @param tintMode the blending mode used to apply the tint, may be
   17589      *                 {@code null} to clear tint
   17590      * @attr ref android.R.styleable#View_foregroundTintMode
   17591      * @see #getForegroundTintMode()
   17592      * @see Drawable#setTintMode(PorterDuff.Mode)
   17593      */
   17594     public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
   17595         if (mForegroundInfo == null) {
   17596             mForegroundInfo = new ForegroundInfo();
   17597         }
   17598         if (mForegroundInfo.mTintInfo == null) {
   17599             mForegroundInfo.mTintInfo = new TintInfo();
   17600         }
   17601         mForegroundInfo.mTintInfo.mTintMode = tintMode;
   17602         mForegroundInfo.mTintInfo.mHasTintMode = true;
   17603 
   17604         applyForegroundTint();
   17605     }
   17606 
   17607     /**
   17608      * Return the blending mode used to apply the tint to the foreground
   17609      * drawable, if specified.
   17610      *
   17611      * @return the blending mode used to apply the tint to the foreground
   17612      *         drawable
   17613      * @attr ref android.R.styleable#View_foregroundTintMode
   17614      * @see #setForegroundTintMode(PorterDuff.Mode)
   17615      */
   17616     @Nullable
   17617     public PorterDuff.Mode getForegroundTintMode() {
   17618         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
   17619                 ? mForegroundInfo.mTintInfo.mTintMode : null;
   17620     }
   17621 
   17622     private void applyForegroundTint() {
   17623         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
   17624                 && mForegroundInfo.mTintInfo != null) {
   17625             final TintInfo tintInfo = mForegroundInfo.mTintInfo;
   17626             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
   17627                 mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
   17628 
   17629                 if (tintInfo.mHasTintList) {
   17630                     mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
   17631                 }
   17632 
   17633                 if (tintInfo.mHasTintMode) {
   17634                     mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
   17635                 }
   17636 
   17637                 // The drawable (or one of its children) may not have been
   17638                 // stateful before applying the tint, so let's try again.
   17639                 if (mForegroundInfo.mDrawable.isStateful()) {
   17640                     mForegroundInfo.mDrawable.setState(getDrawableState());
   17641                 }
   17642             }
   17643         }
   17644     }
   17645 
   17646     /**
   17647      * Draw any foreground content for this view.
   17648      *
   17649      * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
   17650      * drawable or other view-specific decorations. The foreground is drawn on top of the
   17651      * primary view content.</p>
   17652      *
   17653      * @param canvas canvas to draw into
   17654      */
   17655     public void onDrawForeground(Canvas canvas) {
   17656         onDrawScrollIndicators(canvas);
   17657         onDrawScrollBars(canvas);
   17658 
   17659         final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
   17660         if (foreground != null) {
   17661             if (mForegroundInfo.mBoundsChanged) {
   17662                 mForegroundInfo.mBoundsChanged = false;
   17663                 final Rect selfBounds = mForegroundInfo.mSelfBounds;
   17664                 final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
   17665 
   17666                 if (mForegroundInfo.mInsidePadding) {
   17667                     selfBounds.set(0, 0, getWidth(), getHeight());
   17668                 } else {
   17669                     selfBounds.set(getPaddingLeft(), getPaddingTop(),
   17670                             getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
   17671                 }
   17672 
   17673                 final int ld = getLayoutDirection();
   17674                 Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
   17675                         foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
   17676                 foreground.setBounds(overlayBounds);
   17677             }
   17678 
   17679             foreground.draw(canvas);
   17680         }
   17681     }
   17682 
   17683     /**
   17684      * Sets the padding. The view may add on the space required to display
   17685      * the scrollbars, depending on the style and visibility of the scrollbars.
   17686      * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
   17687      * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
   17688      * from the values set in this call.
   17689      *
   17690      * @attr ref android.R.styleable#View_padding
   17691      * @attr ref android.R.styleable#View_paddingBottom
   17692      * @attr ref android.R.styleable#View_paddingLeft
   17693      * @attr ref android.R.styleable#View_paddingRight
   17694      * @attr ref android.R.styleable#View_paddingTop
   17695      * @param left the left padding in pixels
   17696      * @param top the top padding in pixels
   17697      * @param right the right padding in pixels
   17698      * @param bottom the bottom padding in pixels
   17699      */
   17700     public void setPadding(int left, int top, int right, int bottom) {
   17701         resetResolvedPaddingInternal();
   17702 
   17703         mUserPaddingStart = UNDEFINED_PADDING;
   17704         mUserPaddingEnd = UNDEFINED_PADDING;
   17705 
   17706         mUserPaddingLeftInitial = left;
   17707         mUserPaddingRightInitial = right;
   17708 
   17709         mLeftPaddingDefined = true;
   17710         mRightPaddingDefined = true;
   17711 
   17712         internalSetPadding(left, top, right, bottom);
   17713     }
   17714 
   17715     /**
   17716      * @hide
   17717      */
   17718     protected void internalSetPadding(int left, int top, int right, int bottom) {
   17719         mUserPaddingLeft = left;
   17720         mUserPaddingRight = right;
   17721         mUserPaddingBottom = bottom;
   17722 
   17723         final int viewFlags = mViewFlags;
   17724         boolean changed = false;
   17725 
   17726         // Common case is there are no scroll bars.
   17727         if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
   17728             if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
   17729                 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
   17730                         ? 0 : getVerticalScrollbarWidth();
   17731                 switch (mVerticalScrollbarPosition) {
   17732                     case SCROLLBAR_POSITION_DEFAULT:
   17733                         if (isLayoutRtl()) {
   17734                             left += offset;
   17735                         } else {
   17736                             right += offset;
   17737                         }
   17738                         break;
   17739                     case SCROLLBAR_POSITION_RIGHT:
   17740                         right += offset;
   17741                         break;
   17742                     case SCROLLBAR_POSITION_LEFT:
   17743                         left += offset;
   17744                         break;
   17745                 }
   17746             }
   17747             if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
   17748                 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
   17749                         ? 0 : getHorizontalScrollbarHeight();
   17750             }
   17751         }
   17752 
   17753         if (mPaddingLeft != left) {
   17754             changed = true;
   17755             mPaddingLeft = left;
   17756         }
   17757         if (mPaddingTop != top) {
   17758             changed = true;
   17759             mPaddingTop = top;
   17760         }
   17761         if (mPaddingRight != right) {
   17762             changed = true;
   17763             mPaddingRight = right;
   17764         }
   17765         if (mPaddingBottom != bottom) {
   17766             changed = true;
   17767             mPaddingBottom = bottom;
   17768         }
   17769 
   17770         if (changed) {
   17771             requestLayout();
   17772             invalidateOutline();
   17773         }
   17774     }
   17775 
   17776     /**
   17777      * Sets the relative padding. The view may add on the space required to display
   17778      * the scrollbars, depending on the style and visibility of the scrollbars.
   17779      * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
   17780      * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
   17781      * from the values set in this call.
   17782      *
   17783      * @attr ref android.R.styleable#View_padding
   17784      * @attr ref android.R.styleable#View_paddingBottom
   17785      * @attr ref android.R.styleable#View_paddingStart
   17786      * @attr ref android.R.styleable#View_paddingEnd
   17787      * @attr ref android.R.styleable#View_paddingTop
   17788      * @param start the start padding in pixels
   17789      * @param top the top padding in pixels
   17790      * @param end the end padding in pixels
   17791      * @param bottom the bottom padding in pixels
   17792      */
   17793     public void setPaddingRelative(int start, int top, int end, int bottom) {
   17794         resetResolvedPaddingInternal();
   17795 
   17796         mUserPaddingStart = start;
   17797         mUserPaddingEnd = end;
   17798         mLeftPaddingDefined = true;
   17799         mRightPaddingDefined = true;
   17800 
   17801         switch(getLayoutDirection()) {
   17802             case LAYOUT_DIRECTION_RTL:
   17803                 mUserPaddingLeftInitial = end;
   17804                 mUserPaddingRightInitial = start;
   17805                 internalSetPadding(end, top, start, bottom);
   17806                 break;
   17807             case LAYOUT_DIRECTION_LTR:
   17808             default:
   17809                 mUserPaddingLeftInitial = start;
   17810                 mUserPaddingRightInitial = end;
   17811                 internalSetPadding(start, top, end, bottom);
   17812         }
   17813     }
   17814 
   17815     /**
   17816      * Returns the top padding of this view.
   17817      *
   17818      * @return the top padding in pixels
   17819      */
   17820     public int getPaddingTop() {
   17821         return mPaddingTop;
   17822     }
   17823 
   17824     /**
   17825      * Returns the bottom padding of this view. If there are inset and enabled
   17826      * scrollbars, this value may include the space required to display the
   17827      * scrollbars as well.
   17828      *
   17829      * @return the bottom padding in pixels
   17830      */
   17831     public int getPaddingBottom() {
   17832         return mPaddingBottom;
   17833     }
   17834 
   17835     /**
   17836      * Returns the left padding of this view. If there are inset and enabled
   17837      * scrollbars, this value may include the space required to display the
   17838      * scrollbars as well.
   17839      *
   17840      * @return the left padding in pixels
   17841      */
   17842     public int getPaddingLeft() {
   17843         if (!isPaddingResolved()) {
   17844             resolvePadding();
   17845         }
   17846         return mPaddingLeft;
   17847     }
   17848 
   17849     /**
   17850      * Returns the start padding of this view depending on its resolved layout direction.
   17851      * If there are inset and enabled scrollbars, this value may include the space
   17852      * required to display the scrollbars as well.
   17853      *
   17854      * @return the start padding in pixels
   17855      */
   17856     public int getPaddingStart() {
   17857         if (!isPaddingResolved()) {
   17858             resolvePadding();
   17859         }
   17860         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
   17861                 mPaddingRight : mPaddingLeft;
   17862     }
   17863 
   17864     /**
   17865      * Returns the right padding of this view. If there are inset and enabled
   17866      * scrollbars, this value may include the space required to display the
   17867      * scrollbars as well.
   17868      *
   17869      * @return the right padding in pixels
   17870      */
   17871     public int getPaddingRight() {
   17872         if (!isPaddingResolved()) {
   17873             resolvePadding();
   17874         }
   17875         return mPaddingRight;
   17876     }
   17877 
   17878     /**
   17879      * Returns the end padding of this view depending on its resolved layout direction.
   17880      * If there are inset and enabled scrollbars, this value may include the space
   17881      * required to display the scrollbars as well.
   17882      *
   17883      * @return the end padding in pixels
   17884      */
   17885     public int getPaddingEnd() {
   17886         if (!isPaddingResolved()) {
   17887             resolvePadding();
   17888         }
   17889         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
   17890                 mPaddingLeft : mPaddingRight;
   17891     }
   17892 
   17893     /**
   17894      * Return if the padding has been set through relative values
   17895      * {@link #setPaddingRelative(int, int, int, int)} or through
   17896      * @attr ref android.R.styleable#View_paddingStart or
   17897      * @attr ref android.R.styleable#View_paddingEnd
   17898      *
   17899      * @return true if the padding is relative or false if it is not.
   17900      */
   17901     public boolean isPaddingRelative() {
   17902         return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
   17903     }
   17904 
   17905     Insets computeOpticalInsets() {
   17906         return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
   17907     }
   17908 
   17909     /**
   17910      * @hide
   17911      */
   17912     public void resetPaddingToInitialValues() {
   17913         if (isRtlCompatibilityMode()) {
   17914             mPaddingLeft = mUserPaddingLeftInitial;
   17915             mPaddingRight = mUserPaddingRightInitial;
   17916             return;
   17917         }
   17918         if (isLayoutRtl()) {
   17919             mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
   17920             mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
   17921         } else {
   17922             mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
   17923             mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
   17924         }
   17925     }
   17926 
   17927     /**
   17928      * @hide
   17929      */
   17930     public Insets getOpticalInsets() {
   17931         if (mLayoutInsets == null) {
   17932             mLayoutInsets = computeOpticalInsets();
   17933         }
   17934         return mLayoutInsets;
   17935     }
   17936 
   17937     /**
   17938      * Set this view's optical insets.
   17939      *
   17940      * <p>This method should be treated similarly to setMeasuredDimension and not as a general
   17941      * property. Views that compute their own optical insets should call it as part of measurement.
   17942      * This method does not request layout. If you are setting optical insets outside of
   17943      * measure/layout itself you will want to call requestLayout() yourself.
   17944      * </p>
   17945      * @hide
   17946      */
   17947     public void setOpticalInsets(Insets insets) {
   17948         mLayoutInsets = insets;
   17949     }
   17950 
   17951     /**
   17952      * Changes the selection state of this view. A view can be selected or not.
   17953      * Note that selection is not the same as focus. Views are typically
   17954      * selected in the context of an AdapterView like ListView or GridView;
   17955      * the selected view is the view that is highlighted.
   17956      *
   17957      * @param selected true if the view must be selected, false otherwise
   17958      */
   17959     public void setSelected(boolean selected) {
   17960         //noinspection DoubleNegation
   17961         if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
   17962             mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
   17963             if (!selected) resetPressedState();
   17964             invalidate(true);
   17965             refreshDrawableState();
   17966             dispatchSetSelected(selected);
   17967             if (selected) {
   17968                 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
   17969             } else {
   17970                 notifyViewAccessibilityStateChangedIfNeeded(
   17971                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
   17972             }
   17973         }
   17974     }
   17975 
   17976     /**
   17977      * Dispatch setSelected to all of this View's children.
   17978      *
   17979      * @see #setSelected(boolean)
   17980      *
   17981      * @param selected The new selected state
   17982      */
   17983     protected void dispatchSetSelected(boolean selected) {
   17984     }
   17985 
   17986     /**
   17987      * Indicates the selection state of this view.
   17988      *
   17989      * @return true if the view is selected, false otherwise
   17990      */
   17991     @ViewDebug.ExportedProperty
   17992     public boolean isSelected() {
   17993         return (mPrivateFlags & PFLAG_SELECTED) != 0;
   17994     }
   17995 
   17996     /**
   17997      * Changes the activated state of this view. A view can be activated or not.
   17998      * Note that activation is not the same as selection.  Selection is
   17999      * a transient property, representing the view (hierarchy) the user is
   18000      * currently interacting with.  Activation is a longer-term state that the
   18001      * user can move views in and out of.  For example, in a list view with
   18002      * single or multiple selection enabled, the views in the current selection
   18003      * set are activated.  (Um, yeah, we are deeply sorry about the terminology
   18004      * here.)  The activated state is propagated down to children of the view it
   18005      * is set on.
   18006      *
   18007      * @param activated true if the view must be activated, false otherwise
   18008      */
   18009     public void setActivated(boolean activated) {
   18010         //noinspection DoubleNegation
   18011         if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
   18012             mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
   18013             invalidate(true);
   18014             refreshDrawableState();
   18015             dispatchSetActivated(activated);
   18016         }
   18017     }
   18018 
   18019     /**
   18020      * Dispatch setActivated to all of this View's children.
   18021      *
   18022      * @see #setActivated(boolean)
   18023      *
   18024      * @param activated The new activated state
   18025      */
   18026     protected void dispatchSetActivated(boolean activated) {
   18027     }
   18028 
   18029     /**
   18030      * Indicates the activation state of this view.
   18031      *
   18032      * @return true if the view is activated, false otherwise
   18033      */
   18034     @ViewDebug.ExportedProperty
   18035     public boolean isActivated() {
   18036         return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
   18037     }
   18038 
   18039     /**
   18040      * Returns the ViewTreeObserver for this view's hierarchy. The view tree
   18041      * observer can be used to get notifications when global events, like
   18042      * layout, happen.
   18043      *
   18044      * The returned ViewTreeObserver observer is not guaranteed to remain
   18045      * valid for the lifetime of this View. If the caller of this method keeps
   18046      * a long-lived reference to ViewTreeObserver, it should always check for
   18047      * the return value of {@link ViewTreeObserver#isAlive()}.
   18048      *
   18049      * @return The ViewTreeObserver for this view's hierarchy.
   18050      */
   18051     public ViewTreeObserver getViewTreeObserver() {
   18052         if (mAttachInfo != null) {
   18053             return mAttachInfo.mTreeObserver;
   18054         }
   18055         if (mFloatingTreeObserver == null) {
   18056             mFloatingTreeObserver = new ViewTreeObserver();
   18057         }
   18058         return mFloatingTreeObserver;
   18059     }
   18060 
   18061     /**
   18062      * <p>Finds the topmost view in the current view hierarchy.</p>
   18063      *
   18064      * @return the topmost view containing this view
   18065      */
   18066     public View getRootView() {
   18067         if (mAttachInfo != null) {
   18068             final View v = mAttachInfo.mRootView;
   18069             if (v != null) {
   18070                 return v;
   18071             }
   18072         }
   18073 
   18074         View parent = this;
   18075 
   18076         while (parent.mParent != null && parent.mParent instanceof View) {
   18077             parent = (View) parent.mParent;
   18078         }
   18079 
   18080         return parent;
   18081     }
   18082 
   18083     /**
   18084      * Transforms a motion event from view-local coordinates to on-screen
   18085      * coordinates.
   18086      *
   18087      * @param ev the view-local motion event
   18088      * @return false if the transformation could not be applied
   18089      * @hide
   18090      */
   18091     public boolean toGlobalMotionEvent(MotionEvent ev) {
   18092         final AttachInfo info = mAttachInfo;
   18093         if (info == null) {
   18094             return false;
   18095         }
   18096 
   18097         final Matrix m = info.mTmpMatrix;
   18098         m.set(Matrix.IDENTITY_MATRIX);
   18099         transformMatrixToGlobal(m);
   18100         ev.transform(m);
   18101         return true;
   18102     }
   18103 
   18104     /**
   18105      * Transforms a motion event from on-screen coordinates to view-local
   18106      * coordinates.
   18107      *
   18108      * @param ev the on-screen motion event
   18109      * @return false if the transformation could not be applied
   18110      * @hide
   18111      */
   18112     public boolean toLocalMotionEvent(MotionEvent ev) {
   18113         final AttachInfo info = mAttachInfo;
   18114         if (info == null) {
   18115             return false;
   18116         }
   18117 
   18118         final Matrix m = info.mTmpMatrix;
   18119         m.set(Matrix.IDENTITY_MATRIX);
   18120         transformMatrixToLocal(m);
   18121         ev.transform(m);
   18122         return true;
   18123     }
   18124 
   18125     /**
   18126      * Modifies the input matrix such that it maps view-local coordinates to
   18127      * on-screen coordinates.
   18128      *
   18129      * @param m input matrix to modify
   18130      * @hide
   18131      */
   18132     public void transformMatrixToGlobal(Matrix m) {
   18133         final ViewParent parent = mParent;
   18134         if (parent instanceof View) {
   18135             final View vp = (View) parent;
   18136             vp.transformMatrixToGlobal(m);
   18137             m.preTranslate(-vp.mScrollX, -vp.mScrollY);
   18138         } else if (parent instanceof ViewRootImpl) {
   18139             final ViewRootImpl vr = (ViewRootImpl) parent;
   18140             vr.transformMatrixToGlobal(m);
   18141             m.preTranslate(0, -vr.mCurScrollY);
   18142         }
   18143 
   18144         m.preTranslate(mLeft, mTop);
   18145 
   18146         if (!hasIdentityMatrix()) {
   18147             m.preConcat(getMatrix());
   18148         }
   18149     }
   18150 
   18151     /**
   18152      * Modifies the input matrix such that it maps on-screen coordinates to
   18153      * view-local coordinates.
   18154      *
   18155      * @param m input matrix to modify
   18156      * @hide
   18157      */
   18158     public void transformMatrixToLocal(Matrix m) {
   18159         final ViewParent parent = mParent;
   18160         if (parent instanceof View) {
   18161             final View vp = (View) parent;
   18162             vp.transformMatrixToLocal(m);
   18163             m.postTranslate(vp.mScrollX, vp.mScrollY);
   18164         } else if (parent instanceof ViewRootImpl) {
   18165             final ViewRootImpl vr = (ViewRootImpl) parent;
   18166             vr.transformMatrixToLocal(m);
   18167             m.postTranslate(0, vr.mCurScrollY);
   18168         }
   18169 
   18170         m.postTranslate(-mLeft, -mTop);
   18171 
   18172         if (!hasIdentityMatrix()) {
   18173             m.postConcat(getInverseMatrix());
   18174         }
   18175     }
   18176 
   18177     /**
   18178      * @hide
   18179      */
   18180     @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
   18181             @ViewDebug.IntToString(from = 0, to = "x"),
   18182             @ViewDebug.IntToString(from = 1, to = "y")
   18183     })
   18184     public int[] getLocationOnScreen() {
   18185         int[] location = new int[2];
   18186         getLocationOnScreen(location);
   18187         return location;
   18188     }
   18189 
   18190     /**
   18191      * <p>Computes the coordinates of this view on the screen. The argument
   18192      * must be an array of two integers. After the method returns, the array
   18193      * contains the x and y location in that order.</p>
   18194      *
   18195      * @param location an array of two integers in which to hold the coordinates
   18196      */
   18197     public void getLocationOnScreen(@Size(2) int[] location) {
   18198         getLocationInWindow(location);
   18199 
   18200         final AttachInfo info = mAttachInfo;
   18201         if (info != null) {
   18202             location[0] += info.mWindowLeft;
   18203             location[1] += info.mWindowTop;
   18204         }
   18205     }
   18206 
   18207     /**
   18208      * <p>Computes the coordinates of this view in its window. The argument
   18209      * must be an array of two integers. After the method returns, the array
   18210      * contains the x and y location in that order.</p>
   18211      *
   18212      * @param location an array of two integers in which to hold the coordinates
   18213      */
   18214     public void getLocationInWindow(@Size(2) int[] location) {
   18215         if (location == null || location.length < 2) {
   18216             throw new IllegalArgumentException("location must be an array of two integers");
   18217         }
   18218 
   18219         if (mAttachInfo == null) {
   18220             // When the view is not attached to a window, this method does not make sense
   18221             location[0] = location[1] = 0;
   18222             return;
   18223         }
   18224 
   18225         float[] position = mAttachInfo.mTmpTransformLocation;
   18226         position[0] = position[1] = 0.0f;
   18227 
   18228         if (!hasIdentityMatrix()) {
   18229             getMatrix().mapPoints(position);
   18230         }
   18231 
   18232         position[0] += mLeft;
   18233         position[1] += mTop;
   18234 
   18235         ViewParent viewParent = mParent;
   18236         while (viewParent instanceof View) {
   18237             final View view = (View) viewParent;
   18238 
   18239             position[0] -= view.mScrollX;
   18240             position[1] -= view.mScrollY;
   18241 
   18242             if (!view.hasIdentityMatrix()) {
   18243                 view.getMatrix().mapPoints(position);
   18244             }
   18245 
   18246             position[0] += view.mLeft;
   18247             position[1] += view.mTop;
   18248 
   18249             viewParent = view.mParent;
   18250          }
   18251 
   18252         if (viewParent instanceof ViewRootImpl) {
   18253             // *cough*
   18254             final ViewRootImpl vr = (ViewRootImpl) viewParent;
   18255             position[1] -= vr.mCurScrollY;
   18256         }
   18257 
   18258         location[0] = (int) (position[0] + 0.5f);
   18259         location[1] = (int) (position[1] + 0.5f);
   18260     }
   18261 
   18262     /**
   18263      * {@hide}
   18264      * @param id the id of the view to be found
   18265      * @return the view of the specified id, null if cannot be found
   18266      */
   18267     protected View findViewTraversal(@IdRes int id) {
   18268         if (id == mID) {
   18269             return this;
   18270         }
   18271         return null;
   18272     }
   18273 
   18274     /**
   18275      * {@hide}
   18276      * @param tag the tag of the view to be found
   18277      * @return the view of specified tag, null if cannot be found
   18278      */
   18279     protected View findViewWithTagTraversal(Object tag) {
   18280         if (tag != null && tag.equals(mTag)) {
   18281             return this;
   18282         }
   18283         return null;
   18284     }
   18285 
   18286     /**
   18287      * {@hide}
   18288      * @param predicate The predicate to evaluate.
   18289      * @param childToSkip If not null, ignores this child during the recursive traversal.
   18290      * @return The first view that matches the predicate or null.
   18291      */
   18292     protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
   18293         if (predicate.apply(this)) {
   18294             return this;
   18295         }
   18296         return null;
   18297     }
   18298 
   18299     /**
   18300      * Look for a child view with the given id.  If this view has the given
   18301      * id, return this view.
   18302      *
   18303      * @param id The id to search for.
   18304      * @return The view that has the given id in the hierarchy or null
   18305      */
   18306     @Nullable
   18307     public final View findViewById(@IdRes int id) {
   18308         if (id < 0) {
   18309             return null;
   18310         }
   18311         return findViewTraversal(id);
   18312     }
   18313 
   18314     /**
   18315      * Finds a view by its unuque and stable accessibility id.
   18316      *
   18317      * @param accessibilityId The searched accessibility id.
   18318      * @return The found view.
   18319      */
   18320     final View findViewByAccessibilityId(int accessibilityId) {
   18321         if (accessibilityId < 0) {
   18322             return null;
   18323         }
   18324         View view = findViewByAccessibilityIdTraversal(accessibilityId);
   18325         if (view != null) {
   18326             return view.includeForAccessibility() ? view : null;
   18327         }
   18328         return null;
   18329     }
   18330 
   18331     /**
   18332      * Performs the traversal to find a view by its unuque and stable accessibility id.
   18333      *
   18334      * <strong>Note:</strong>This method does not stop at the root namespace
   18335      * boundary since the user can touch the screen at an arbitrary location
   18336      * potentially crossing the root namespace bounday which will send an
   18337      * accessibility event to accessibility services and they should be able
   18338      * to obtain the event source. Also accessibility ids are guaranteed to be
   18339      * unique in the window.
   18340      *
   18341      * @param accessibilityId The accessibility id.
   18342      * @return The found view.
   18343      *
   18344      * @hide
   18345      */
   18346     public View findViewByAccessibilityIdTraversal(int accessibilityId) {
   18347         if (getAccessibilityViewId() == accessibilityId) {
   18348             return this;
   18349         }
   18350         return null;
   18351     }
   18352 
   18353     /**
   18354      * Look for a child view with the given tag.  If this view has the given
   18355      * tag, return this view.
   18356      *
   18357      * @param tag The tag to search for, using "tag.equals(getTag())".
   18358      * @return The View that has the given tag in the hierarchy or null
   18359      */
   18360     public final View findViewWithTag(Object tag) {
   18361         if (tag == null) {
   18362             return null;
   18363         }
   18364         return findViewWithTagTraversal(tag);
   18365     }
   18366 
   18367     /**
   18368      * {@hide}
   18369      * Look for a child view that matches the specified predicate.
   18370      * If this view matches the predicate, return this view.
   18371      *
   18372      * @param predicate The predicate to evaluate.
   18373      * @return The first view that matches the predicate or null.
   18374      */
   18375     public final View findViewByPredicate(Predicate<View> predicate) {
   18376         return findViewByPredicateTraversal(predicate, null);
   18377     }
   18378 
   18379     /**
   18380      * {@hide}
   18381      * Look for a child view that matches the specified predicate,
   18382      * starting with the specified view and its descendents and then
   18383      * recusively searching the ancestors and siblings of that view
   18384      * until this view is reached.
   18385      *
   18386      * This method is useful in cases where the predicate does not match
   18387      * a single unique view (perhaps multiple views use the same id)
   18388      * and we are trying to find the view that is "closest" in scope to the
   18389      * starting view.
   18390      *
   18391      * @param start The view to start from.
   18392      * @param predicate The predicate to evaluate.
   18393      * @return The first view that matches the predicate or null.
   18394      */
   18395     public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
   18396         View childToSkip = null;
   18397         for (;;) {
   18398             View view = start.findViewByPredicateTraversal(predicate, childToSkip);
   18399             if (view != null || start == this) {
   18400                 return view;
   18401             }
   18402 
   18403             ViewParent parent = start.getParent();
   18404             if (parent == null || !(parent instanceof View)) {
   18405                 return null;
   18406             }
   18407 
   18408             childToSkip = start;
   18409             start = (View) parent;
   18410         }
   18411     }
   18412 
   18413     /**
   18414      * Sets the identifier for this view. The identifier does not have to be
   18415      * unique in this view's hierarchy. The identifier should be a positive
   18416      * number.
   18417      *
   18418      * @see #NO_ID
   18419      * @see #getId()
   18420      * @see #findViewById(int)
   18421      *
   18422      * @param id a number used to identify the view
   18423      *
   18424      * @attr ref android.R.styleable#View_id
   18425      */
   18426     public void setId(@IdRes int id) {
   18427         mID = id;
   18428         if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
   18429             mID = generateViewId();
   18430         }
   18431     }
   18432 
   18433     /**
   18434      * {@hide}
   18435      *
   18436      * @param isRoot true if the view belongs to the root namespace, false
   18437      *        otherwise
   18438      */
   18439     public void setIsRootNamespace(boolean isRoot) {
   18440         if (isRoot) {
   18441             mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
   18442         } else {
   18443             mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
   18444         }
   18445     }
   18446 
   18447     /**
   18448      * {@hide}
   18449      *
   18450      * @return true if the view belongs to the root namespace, false otherwise
   18451      */
   18452     public boolean isRootNamespace() {
   18453         return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
   18454     }
   18455 
   18456     /**
   18457      * Returns this view's identifier.
   18458      *
   18459      * @return a positive integer used to identify the view or {@link #NO_ID}
   18460      *         if the view has no ID
   18461      *
   18462      * @see #setId(int)
   18463      * @see #findViewById(int)
   18464      * @attr ref android.R.styleable#View_id
   18465      */
   18466     @IdRes
   18467     @ViewDebug.CapturedViewProperty
   18468     public int getId() {
   18469         return mID;
   18470     }
   18471 
   18472     /**
   18473      * Returns this view's tag.
   18474      *
   18475      * @return the Object stored in this view as a tag, or {@code null} if not
   18476      *         set
   18477      *
   18478      * @see #setTag(Object)
   18479      * @see #getTag(int)
   18480      */
   18481     @ViewDebug.ExportedProperty
   18482     public Object getTag() {
   18483         return mTag;
   18484     }
   18485 
   18486     /**
   18487      * Sets the tag associated with this view. A tag can be used to mark
   18488      * a view in its hierarchy and does not have to be unique within the
   18489      * hierarchy. Tags can also be used to store data within a view without
   18490      * resorting to another data structure.
   18491      *
   18492      * @param tag an Object to tag the view with
   18493      *
   18494      * @see #getTag()
   18495      * @see #setTag(int, Object)
   18496      */
   18497     public void setTag(final Object tag) {
   18498         mTag = tag;
   18499     }
   18500 
   18501     /**
   18502      * Returns the tag associated with this view and the specified key.
   18503      *
   18504      * @param key The key identifying the tag
   18505      *
   18506      * @return the Object stored in this view as a tag, or {@code null} if not
   18507      *         set
   18508      *
   18509      * @see #setTag(int, Object)
   18510      * @see #getTag()
   18511      */
   18512     public Object getTag(int key) {
   18513         if (mKeyedTags != null) return mKeyedTags.get(key);
   18514         return null;
   18515     }
   18516 
   18517     /**
   18518      * Sets a tag associated with this view and a key. A tag can be used
   18519      * to mark a view in its hierarchy and does not have to be unique within
   18520      * the hierarchy. Tags can also be used to store data within a view
   18521      * without resorting to another data structure.
   18522      *
   18523      * The specified key should be an id declared in the resources of the
   18524      * application to ensure it is unique (see the <a
   18525      * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
   18526      * Keys identified as belonging to
   18527      * the Android framework or not associated with any package will cause
   18528      * an {@link IllegalArgumentException} to be thrown.
   18529      *
   18530      * @param key The key identifying the tag
   18531      * @param tag An Object to tag the view with
   18532      *
   18533      * @throws IllegalArgumentException If they specified key is not valid
   18534      *
   18535      * @see #setTag(Object)
   18536      * @see #getTag(int)
   18537      */
   18538     public void setTag(int key, final Object tag) {
   18539         // If the package id is 0x00 or 0x01, it's either an undefined package
   18540         // or a framework id
   18541         if ((key >>> 24) < 2) {
   18542             throw new IllegalArgumentException("The key must be an application-specific "
   18543                     + "resource id.");
   18544         }
   18545 
   18546         setKeyedTag(key, tag);
   18547     }
   18548 
   18549     /**
   18550      * Variation of {@link #setTag(int, Object)} that enforces the key to be a
   18551      * framework id.
   18552      *
   18553      * @hide
   18554      */
   18555     public void setTagInternal(int key, Object tag) {
   18556         if ((key >>> 24) != 0x1) {
   18557             throw new IllegalArgumentException("The key must be a framework-specific "
   18558                     + "resource id.");
   18559         }
   18560 
   18561         setKeyedTag(key, tag);
   18562     }
   18563 
   18564     private void setKeyedTag(int key, Object tag) {
   18565         if (mKeyedTags == null) {
   18566             mKeyedTags = new SparseArray<Object>(2);
   18567         }
   18568 
   18569         mKeyedTags.put(key, tag);
   18570     }
   18571 
   18572     /**
   18573      * Prints information about this view in the log output, with the tag
   18574      * {@link #VIEW_LOG_TAG}.
   18575      *
   18576      * @hide
   18577      */
   18578     public void debug() {
   18579         debug(0);
   18580     }
   18581 
   18582     /**
   18583      * Prints information about this view in the log output, with the tag
   18584      * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
   18585      * indentation defined by the <code>depth</code>.
   18586      *
   18587      * @param depth the indentation level
   18588      *
   18589      * @hide
   18590      */
   18591     protected void debug(int depth) {
   18592         String output = debugIndent(depth - 1);
   18593 
   18594         output += "+ " + this;
   18595         int id = getId();
   18596         if (id != -1) {
   18597             output += " (id=" + id + ")";
   18598         }
   18599         Object tag = getTag();
   18600         if (tag != null) {
   18601             output += " (tag=" + tag + ")";
   18602         }
   18603         Log.d(VIEW_LOG_TAG, output);
   18604 
   18605         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
   18606             output = debugIndent(depth) + " FOCUSED";
   18607             Log.d(VIEW_LOG_TAG, output);
   18608         }
   18609 
   18610         output = debugIndent(depth);
   18611         output += "frame={" + mLeft + ", " + mTop + ", " + mRight
   18612                 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
   18613                 + "} ";
   18614         Log.d(VIEW_LOG_TAG, output);
   18615 
   18616         if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
   18617                 || mPaddingBottom != 0) {
   18618             output = debugIndent(depth);
   18619             output += "padding={" + mPaddingLeft + ", " + mPaddingTop
   18620                     + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
   18621             Log.d(VIEW_LOG_TAG, output);
   18622         }
   18623 
   18624         output = debugIndent(depth);
   18625         output += "mMeasureWidth=" + mMeasuredWidth +
   18626                 " mMeasureHeight=" + mMeasuredHeight;
   18627         Log.d(VIEW_LOG_TAG, output);
   18628 
   18629         output = debugIndent(depth);
   18630         if (mLayoutParams == null) {
   18631             output += "BAD! no layout params";
   18632         } else {
   18633             output = mLayoutParams.debug(output);
   18634         }
   18635         Log.d(VIEW_LOG_TAG, output);
   18636 
   18637         output = debugIndent(depth);
   18638         output += "flags={";
   18639         output += View.printFlags(mViewFlags);
   18640         output += "}";
   18641         Log.d(VIEW_LOG_TAG, output);
   18642 
   18643         output = debugIndent(depth);
   18644         output += "privateFlags={";
   18645         output += View.printPrivateFlags(mPrivateFlags);
   18646         output += "}";
   18647         Log.d(VIEW_LOG_TAG, output);
   18648     }
   18649 
   18650     /**
   18651      * Creates a string of whitespaces used for indentation.
   18652      *
   18653      * @param depth the indentation level
   18654      * @return a String containing (depth * 2 + 3) * 2 white spaces
   18655      *
   18656      * @hide
   18657      */
   18658     protected static String debugIndent(int depth) {
   18659         StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
   18660         for (int i = 0; i < (depth * 2) + 3; i++) {
   18661             spaces.append(' ').append(' ');
   18662         }
   18663         return spaces.toString();
   18664     }
   18665 
   18666     /**
   18667      * <p>Return the offset of the widget's text baseline from the widget's top
   18668      * boundary. If this widget does not support baseline alignment, this
   18669      * method returns -1. </p>
   18670      *
   18671      * @return the offset of the baseline within the widget's bounds or -1
   18672      *         if baseline alignment is not supported
   18673      */
   18674     @ViewDebug.ExportedProperty(category = "layout")
   18675     public int getBaseline() {
   18676         return -1;
   18677     }
   18678 
   18679     /**
   18680      * Returns whether the view hierarchy is currently undergoing a layout pass. This
   18681      * information is useful to avoid situations such as calling {@link #requestLayout()} during
   18682      * a layout pass.
   18683      *
   18684      * @return whether the view hierarchy is currently undergoing a layout pass
   18685      */
   18686     public boolean isInLayout() {
   18687         ViewRootImpl viewRoot = getViewRootImpl();
   18688         return (viewRoot != null && viewRoot.isInLayout());
   18689     }
   18690 
   18691     /**
   18692      * Call this when something has changed which has invalidated the
   18693      * layout of this view. This will schedule a layout pass of the view
   18694      * tree. This should not be called while the view hierarchy is currently in a layout
   18695      * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
   18696      * end of the current layout pass (and then layout will run again) or after the current
   18697      * frame is drawn and the next layout occurs.
   18698      *
   18699      * <p>Subclasses which override this method should call the superclass method to
   18700      * handle possible request-during-layout errors correctly.</p>
   18701      */
   18702     @CallSuper
   18703     public void requestLayout() {
   18704         if (mMeasureCache != null) mMeasureCache.clear();
   18705 
   18706         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
   18707             // Only trigger request-during-layout logic if this is the view requesting it,
   18708             // not the views in its parent hierarchy
   18709             ViewRootImpl viewRoot = getViewRootImpl();
   18710             if (viewRoot != null && viewRoot.isInLayout()) {
   18711                 if (!viewRoot.requestLayoutDuringLayout(this)) {
   18712                     return;
   18713                 }
   18714             }
   18715             mAttachInfo.mViewRequestingLayout = this;
   18716         }
   18717 
   18718         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
   18719         mPrivateFlags |= PFLAG_INVALIDATED;
   18720 
   18721         if (mParent != null && !mParent.isLayoutRequested()) {
   18722             mParent.requestLayout();
   18723         }
   18724         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
   18725             mAttachInfo.mViewRequestingLayout = null;
   18726         }
   18727     }
   18728 
   18729     /**
   18730      * Forces this view to be laid out during the next layout pass.
   18731      * This method does not call requestLayout() or forceLayout()
   18732      * on the parent.
   18733      */
   18734     public void forceLayout() {
   18735         if (mMeasureCache != null) mMeasureCache.clear();
   18736 
   18737         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
   18738         mPrivateFlags |= PFLAG_INVALIDATED;
   18739     }
   18740 
   18741     /**
   18742      * <p>
   18743      * This is called to find out how big a view should be. The parent
   18744      * supplies constraint information in the width and height parameters.
   18745      * </p>
   18746      *
   18747      * <p>
   18748      * The actual measurement work of a view is performed in
   18749      * {@link #onMeasure(int, int)}, called by this method. Therefore, only
   18750      * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
   18751      * </p>
   18752      *
   18753      *
   18754      * @param widthMeasureSpec Horizontal space requirements as imposed by the
   18755      *        parent
   18756      * @param heightMeasureSpec Vertical space requirements as imposed by the
   18757      *        parent
   18758      *
   18759      * @see #onMeasure(int, int)
   18760      */
   18761     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
   18762         boolean optical = isLayoutModeOptical(this);
   18763         if (optical != isLayoutModeOptical(mParent)) {
   18764             Insets insets = getOpticalInsets();
   18765             int oWidth  = insets.left + insets.right;
   18766             int oHeight = insets.top  + insets.bottom;
   18767             widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
   18768             heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
   18769         }
   18770 
   18771         // Suppress sign extension for the low bytes
   18772         long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
   18773         if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
   18774 
   18775         if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ||
   18776                 widthMeasureSpec != mOldWidthMeasureSpec ||
   18777                 heightMeasureSpec != mOldHeightMeasureSpec) {
   18778 
   18779             // first clears the measured dimension flag
   18780             mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
   18781 
   18782             resolveRtlPropertiesIfNeeded();
   18783 
   18784             int cacheIndex = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ? -1 :
   18785                     mMeasureCache.indexOfKey(key);
   18786             if (cacheIndex < 0 || sIgnoreMeasureCache) {
   18787                 // measure ourselves, this should set the measured dimension flag back
   18788                 onMeasure(widthMeasureSpec, heightMeasureSpec);
   18789                 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
   18790             } else {
   18791                 long value = mMeasureCache.valueAt(cacheIndex);
   18792                 // Casting a long to int drops the high 32 bits, no mask needed
   18793                 setMeasuredDimensionRaw((int) (value >> 32), (int) value);
   18794                 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
   18795             }
   18796 
   18797             // flag not set, setMeasuredDimension() was not invoked, we raise
   18798             // an exception to warn the developer
   18799             if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
   18800                 throw new IllegalStateException("View with id " + getId() + ": "
   18801                         + getClass().getName() + "#onMeasure() did not set the"
   18802                         + " measured dimension by calling"
   18803                         + " setMeasuredDimension()");
   18804             }
   18805 
   18806             mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
   18807         }
   18808 
   18809         mOldWidthMeasureSpec = widthMeasureSpec;
   18810         mOldHeightMeasureSpec = heightMeasureSpec;
   18811 
   18812         mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
   18813                 (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
   18814     }
   18815 
   18816     /**
   18817      * <p>
   18818      * Measure the view and its content to determine the measured width and the
   18819      * measured height. This method is invoked by {@link #measure(int, int)} and
   18820      * should be overridden by subclasses to provide accurate and efficient
   18821      * measurement of their contents.
   18822      * </p>
   18823      *
   18824      * <p>
   18825      * <strong>CONTRACT:</strong> When overriding this method, you
   18826      * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
   18827      * measured width and height of this view. Failure to do so will trigger an
   18828      * <code>IllegalStateException</code>, thrown by
   18829      * {@link #measure(int, int)}. Calling the superclass'
   18830      * {@link #onMeasure(int, int)} is a valid use.
   18831      * </p>
   18832      *
   18833      * <p>
   18834      * The base class implementation of measure defaults to the background size,
   18835      * unless a larger size is allowed by the MeasureSpec. Subclasses should
   18836      * override {@link #onMeasure(int, int)} to provide better measurements of
   18837      * their content.
   18838      * </p>
   18839      *
   18840      * <p>
   18841      * If this method is overridden, it is the subclass's responsibility to make
   18842      * sure the measured height and width are at least the view's minimum height
   18843      * and width ({@link #getSuggestedMinimumHeight()} and
   18844      * {@link #getSuggestedMinimumWidth()}).
   18845      * </p>
   18846      *
   18847      * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
   18848      *                         The requirements are encoded with
   18849      *                         {@link android.view.View.MeasureSpec}.
   18850      * @param heightMeasureSpec vertical space requirements as imposed by the parent.
   18851      *                         The requirements are encoded with
   18852      *                         {@link android.view.View.MeasureSpec}.
   18853      *
   18854      * @see #getMeasuredWidth()
   18855      * @see #getMeasuredHeight()
   18856      * @see #setMeasuredDimension(int, int)
   18857      * @see #getSuggestedMinimumHeight()
   18858      * @see #getSuggestedMinimumWidth()
   18859      * @see android.view.View.MeasureSpec#getMode(int)
   18860      * @see android.view.View.MeasureSpec#getSize(int)
   18861      */
   18862     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
   18863         setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
   18864                 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
   18865     }
   18866 
   18867     /**
   18868      * <p>This method must be called by {@link #onMeasure(int, int)} to store the
   18869      * measured width and measured height. Failing to do so will trigger an
   18870      * exception at measurement time.</p>
   18871      *
   18872      * @param measuredWidth The measured width of this view.  May be a complex
   18873      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
   18874      * {@link #MEASURED_STATE_TOO_SMALL}.
   18875      * @param measuredHeight The measured height of this view.  May be a complex
   18876      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
   18877      * {@link #MEASURED_STATE_TOO_SMALL}.
   18878      */
   18879     protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
   18880         boolean optical = isLayoutModeOptical(this);
   18881         if (optical != isLayoutModeOptical(mParent)) {
   18882             Insets insets = getOpticalInsets();
   18883             int opticalWidth  = insets.left + insets.right;
   18884             int opticalHeight = insets.top  + insets.bottom;
   18885 
   18886             measuredWidth  += optical ? opticalWidth  : -opticalWidth;
   18887             measuredHeight += optical ? opticalHeight : -opticalHeight;
   18888         }
   18889         setMeasuredDimensionRaw(measuredWidth, measuredHeight);
   18890     }
   18891 
   18892     /**
   18893      * Sets the measured dimension without extra processing for things like optical bounds.
   18894      * Useful for reapplying consistent values that have already been cooked with adjustments
   18895      * for optical bounds, etc. such as those from the measurement cache.
   18896      *
   18897      * @param measuredWidth The measured width of this view.  May be a complex
   18898      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
   18899      * {@link #MEASURED_STATE_TOO_SMALL}.
   18900      * @param measuredHeight The measured height of this view.  May be a complex
   18901      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
   18902      * {@link #MEASURED_STATE_TOO_SMALL}.
   18903      */
   18904     private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
   18905         mMeasuredWidth = measuredWidth;
   18906         mMeasuredHeight = measuredHeight;
   18907 
   18908         mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
   18909     }
   18910 
   18911     /**
   18912      * Merge two states as returned by {@link #getMeasuredState()}.
   18913      * @param curState The current state as returned from a view or the result
   18914      * of combining multiple views.
   18915      * @param newState The new view state to combine.
   18916      * @return Returns a new integer reflecting the combination of the two
   18917      * states.
   18918      */
   18919     public static int combineMeasuredStates(int curState, int newState) {
   18920         return curState | newState;
   18921     }
   18922 
   18923     /**
   18924      * Version of {@link #resolveSizeAndState(int, int, int)}
   18925      * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
   18926      */
   18927     public static int resolveSize(int size, int measureSpec) {
   18928         return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
   18929     }
   18930 
   18931     /**
   18932      * Utility to reconcile a desired size and state, with constraints imposed
   18933      * by a MeasureSpec. Will take the desired size, unless a different size
   18934      * is imposed by the constraints. The returned value is a compound integer,
   18935      * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
   18936      * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
   18937      * resulting size is smaller than the size the view wants to be.
   18938      *
   18939      * @param size How big the view wants to be.
   18940      * @param measureSpec Constraints imposed by the parent.
   18941      * @param childMeasuredState Size information bit mask for the view's
   18942      *                           children.
   18943      * @return Size information bit mask as defined by
   18944      *         {@link #MEASURED_SIZE_MASK} and
   18945      *         {@link #MEASURED_STATE_TOO_SMALL}.
   18946      */
   18947     public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
   18948         final int specMode = MeasureSpec.getMode(measureSpec);
   18949         final int specSize = MeasureSpec.getSize(measureSpec);
   18950         final int result;
   18951         switch (specMode) {
   18952             case MeasureSpec.AT_MOST:
   18953                 if (specSize < size) {
   18954                     result = specSize | MEASURED_STATE_TOO_SMALL;
   18955                 } else {
   18956                     result = size;
   18957                 }
   18958                 break;
   18959             case MeasureSpec.EXACTLY:
   18960                 result = specSize;
   18961                 break;
   18962             case MeasureSpec.UNSPECIFIED:
   18963             default:
   18964                 result = size;
   18965         }
   18966         return result | (childMeasuredState & MEASURED_STATE_MASK);
   18967     }
   18968 
   18969     /**
   18970      * Utility to return a default size. Uses the supplied size if the
   18971      * MeasureSpec imposed no constraints. Will get larger if allowed
   18972      * by the MeasureSpec.
   18973      *
   18974      * @param size Default size for this view
   18975      * @param measureSpec Constraints imposed by the parent
   18976      * @return The size this view should be.
   18977      */
   18978     public static int getDefaultSize(int size, int measureSpec) {
   18979         int result = size;
   18980         int specMode = MeasureSpec.getMode(measureSpec);
   18981         int specSize = MeasureSpec.getSize(measureSpec);
   18982 
   18983         switch (specMode) {
   18984         case MeasureSpec.UNSPECIFIED:
   18985             result = size;
   18986             break;
   18987         case MeasureSpec.AT_MOST:
   18988         case MeasureSpec.EXACTLY:
   18989             result = specSize;
   18990             break;
   18991         }
   18992         return result;
   18993     }
   18994 
   18995     /**
   18996      * Returns the suggested minimum height that the view should use. This
   18997      * returns the maximum of the view's minimum height
   18998      * and the background's minimum height
   18999      * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
   19000      * <p>
   19001      * When being used in {@link #onMeasure(int, int)}, the caller should still
   19002      * ensure the returned height is within the requirements of the parent.
   19003      *
   19004      * @return The suggested minimum height of the view.
   19005      */
   19006     protected int getSuggestedMinimumHeight() {
   19007         return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
   19008 
   19009     }
   19010 
   19011     /**
   19012      * Returns the suggested minimum width that the view should use. This
   19013      * returns the maximum of the view's minimum width)
   19014      * and the background's minimum width
   19015      *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
   19016      * <p>
   19017      * When being used in {@link #onMeasure(int, int)}, the caller should still
   19018      * ensure the returned width is within the requirements of the parent.
   19019      *
   19020      * @return The suggested minimum width of the view.
   19021      */
   19022     protected int getSuggestedMinimumWidth() {
   19023         return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
   19024     }
   19025 
   19026     /**
   19027      * Returns the minimum height of the view.
   19028      *
   19029      * @return the minimum height the view will try to be.
   19030      *
   19031      * @see #setMinimumHeight(int)
   19032      *
   19033      * @attr ref android.R.styleable#View_minHeight
   19034      */
   19035     public int getMinimumHeight() {
   19036         return mMinHeight;
   19037     }
   19038 
   19039     /**
   19040      * Sets the minimum height of the view. It is not guaranteed the view will
   19041      * be able to achieve this minimum height (for example, if its parent layout
   19042      * constrains it with less available height).
   19043      *
   19044      * @param minHeight The minimum height the view will try to be.
   19045      *
   19046      * @see #getMinimumHeight()
   19047      *
   19048      * @attr ref android.R.styleable#View_minHeight
   19049      */
   19050     public void setMinimumHeight(int minHeight) {
   19051         mMinHeight = minHeight;
   19052         requestLayout();
   19053     }
   19054 
   19055     /**
   19056      * Returns the minimum width of the view.
   19057      *
   19058      * @return the minimum width the view will try to be.
   19059      *
   19060      * @see #setMinimumWidth(int)
   19061      *
   19062      * @attr ref android.R.styleable#View_minWidth
   19063      */
   19064     public int getMinimumWidth() {
   19065         return mMinWidth;
   19066     }
   19067 
   19068     /**
   19069      * Sets the minimum width of the view. It is not guaranteed the view will
   19070      * be able to achieve this minimum width (for example, if its parent layout
   19071      * constrains it with less available width).
   19072      *
   19073      * @param minWidth The minimum width the view will try to be.
   19074      *
   19075      * @see #getMinimumWidth()
   19076      *
   19077      * @attr ref android.R.styleable#View_minWidth
   19078      */
   19079     public void setMinimumWidth(int minWidth) {
   19080         mMinWidth = minWidth;
   19081         requestLayout();
   19082 
   19083     }
   19084 
   19085     /**
   19086      * Get the animation currently associated with this view.
   19087      *
   19088      * @return The animation that is currently playing or
   19089      *         scheduled to play for this view.
   19090      */
   19091     public Animation getAnimation() {
   19092         return mCurrentAnimation;
   19093     }
   19094 
   19095     /**
   19096      * Start the specified animation now.
   19097      *
   19098      * @param animation the animation to start now
   19099      */
   19100     public void startAnimation(Animation animation) {
   19101         animation.setStartTime(Animation.START_ON_FIRST_FRAME);
   19102         setAnimation(animation);
   19103         invalidateParentCaches();
   19104         invalidate(true);
   19105     }
   19106 
   19107     /**
   19108      * Cancels any animations for this view.
   19109      */
   19110     public void clearAnimation() {
   19111         if (mCurrentAnimation != null) {
   19112             mCurrentAnimation.detach();
   19113         }
   19114         mCurrentAnimation = null;
   19115         invalidateParentIfNeeded();
   19116     }
   19117 
   19118     /**
   19119      * Sets the next animation to play for this view.
   19120      * If you want the animation to play immediately, use
   19121      * {@link #startAnimation(android.view.animation.Animation)} instead.
   19122      * This method provides allows fine-grained
   19123      * control over the start time and invalidation, but you
   19124      * must make sure that 1) the animation has a start time set, and
   19125      * 2) the view's parent (which controls animations on its children)
   19126      * will be invalidated when the animation is supposed to
   19127      * start.
   19128      *
   19129      * @param animation The next animation, or null.
   19130      */
   19131     public void setAnimation(Animation animation) {
   19132         mCurrentAnimation = animation;
   19133 
   19134         if (animation != null) {
   19135             // If the screen is off assume the animation start time is now instead of
   19136             // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
   19137             // would cause the animation to start when the screen turns back on
   19138             if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
   19139                     && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
   19140                 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
   19141             }
   19142             animation.reset();
   19143         }
   19144     }
   19145 
   19146     /**
   19147      * Invoked by a parent ViewGroup to notify the start of the animation
   19148      * currently associated with this view. If you override this method,
   19149      * always call super.onAnimationStart();
   19150      *
   19151      * @see #setAnimation(android.view.animation.Animation)
   19152      * @see #getAnimation()
   19153      */
   19154     @CallSuper
   19155     protected void onAnimationStart() {
   19156         mPrivateFlags |= PFLAG_ANIMATION_STARTED;
   19157     }
   19158 
   19159     /**
   19160      * Invoked by a parent ViewGroup to notify the end of the animation
   19161      * currently associated with this view. If you override this method,
   19162      * always call super.onAnimationEnd();
   19163      *
   19164      * @see #setAnimation(android.view.animation.Animation)
   19165      * @see #getAnimation()
   19166      */
   19167     @CallSuper
   19168     protected void onAnimationEnd() {
   19169         mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
   19170     }
   19171 
   19172     /**
   19173      * Invoked if there is a Transform that involves alpha. Subclass that can
   19174      * draw themselves with the specified alpha should return true, and then
   19175      * respect that alpha when their onDraw() is called. If this returns false
   19176      * then the view may be redirected to draw into an offscreen buffer to
   19177      * fulfill the request, which will look fine, but may be slower than if the
   19178      * subclass handles it internally. The default implementation returns false.
   19179      *
   19180      * @param alpha The alpha (0..255) to apply to the view's drawing
   19181      * @return true if the view can draw with the specified alpha.
   19182      */
   19183     protected boolean onSetAlpha(int alpha) {
   19184         return false;
   19185     }
   19186 
   19187     /**
   19188      * This is used by the RootView to perform an optimization when
   19189      * the view hierarchy contains one or several SurfaceView.
   19190      * SurfaceView is always considered transparent, but its children are not,
   19191      * therefore all View objects remove themselves from the global transparent
   19192      * region (passed as a parameter to this function).
   19193      *
   19194      * @param region The transparent region for this ViewAncestor (window).
   19195      *
   19196      * @return Returns true if the effective visibility of the view at this
   19197      * point is opaque, regardless of the transparent region; returns false
   19198      * if it is possible for underlying windows to be seen behind the view.
   19199      *
   19200      * {@hide}
   19201      */
   19202     public boolean gatherTransparentRegion(Region region) {
   19203         final AttachInfo attachInfo = mAttachInfo;
   19204         if (region != null && attachInfo != null) {
   19205             final int pflags = mPrivateFlags;
   19206             if ((pflags & PFLAG_SKIP_DRAW) == 0) {
   19207                 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
   19208                 // remove it from the transparent region.
   19209                 final int[] location = attachInfo.mTransparentLocation;
   19210                 getLocationInWindow(location);
   19211                 region.op(location[0], location[1], location[0] + mRight - mLeft,
   19212                         location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
   19213             } else {
   19214                 if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
   19215                     // The SKIP_DRAW flag IS set and the background drawable exists, we remove
   19216                     // the background drawable's non-transparent parts from this transparent region.
   19217                     applyDrawableToTransparentRegion(mBackground, region);
   19218                 }
   19219                 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
   19220                         && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
   19221                     // Similarly, we remove the foreground drawable's non-transparent parts.
   19222                     applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
   19223                 }
   19224             }
   19225         }
   19226         return true;
   19227     }
   19228 
   19229     /**
   19230      * Play a sound effect for this view.
   19231      *
   19232      * <p>The framework will play sound effects for some built in actions, such as
   19233      * clicking, but you may wish to play these effects in your widget,
   19234      * for instance, for internal navigation.
   19235      *
   19236      * <p>The sound effect will only be played if sound effects are enabled by the user, and
   19237      * {@link #isSoundEffectsEnabled()} is true.
   19238      *
   19239      * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
   19240      */
   19241     public void playSoundEffect(int soundConstant) {
   19242         if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
   19243             return;
   19244         }
   19245         mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
   19246     }
   19247 
   19248     /**
   19249      * BZZZTT!!1!
   19250      *
   19251      * <p>Provide haptic feedback to the user for this view.
   19252      *
   19253      * <p>The framework will provide haptic feedback for some built in actions,
   19254      * such as long presses, but you may wish to provide feedback for your
   19255      * own widget.
   19256      *
   19257      * <p>The feedback will only be performed if
   19258      * {@link #isHapticFeedbackEnabled()} is true.
   19259      *
   19260      * @param feedbackConstant One of the constants defined in
   19261      * {@link HapticFeedbackConstants}
   19262      */
   19263     public boolean performHapticFeedback(int feedbackConstant) {
   19264         return performHapticFeedback(feedbackConstant, 0);
   19265     }
   19266 
   19267     /**
   19268      * BZZZTT!!1!
   19269      *
   19270      * <p>Like {@link #performHapticFeedback(int)}, with additional options.
   19271      *
   19272      * @param feedbackConstant One of the constants defined in
   19273      * {@link HapticFeedbackConstants}
   19274      * @param flags Additional flags as per {@link HapticFeedbackConstants}.
   19275      */
   19276     public boolean performHapticFeedback(int feedbackConstant, int flags) {
   19277         if (mAttachInfo == null) {
   19278             return false;
   19279         }
   19280         //noinspection SimplifiableIfStatement
   19281         if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
   19282                 && !isHapticFeedbackEnabled()) {
   19283             return false;
   19284         }
   19285         return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
   19286                 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
   19287     }
   19288 
   19289     /**
   19290      * Request that the visibility of the status bar or other screen/window
   19291      * decorations be changed.
   19292      *
   19293      * <p>This method is used to put the over device UI into temporary modes
   19294      * where the user's attention is focused more on the application content,
   19295      * by dimming or hiding surrounding system affordances.  This is typically
   19296      * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
   19297      * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
   19298      * to be placed behind the action bar (and with these flags other system
   19299      * affordances) so that smooth transitions between hiding and showing them
   19300      * can be done.
   19301      *
   19302      * <p>Two representative examples of the use of system UI visibility is
   19303      * implementing a content browsing application (like a magazine reader)
   19304      * and a video playing application.
   19305      *
   19306      * <p>The first code shows a typical implementation of a View in a content
   19307      * browsing application.  In this implementation, the application goes
   19308      * into a content-oriented mode by hiding the status bar and action bar,
   19309      * and putting the navigation elements into lights out mode.  The user can
   19310      * then interact with content while in this mode.  Such an application should
   19311      * provide an easy way for the user to toggle out of the mode (such as to
   19312      * check information in the status bar or access notifications).  In the
   19313      * implementation here, this is done simply by tapping on the content.
   19314      *
   19315      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
   19316      *      content}
   19317      *
   19318      * <p>This second code sample shows a typical implementation of a View
   19319      * in a video playing application.  In this situation, while the video is
   19320      * playing the application would like to go into a complete full-screen mode,
   19321      * to use as much of the display as possible for the video.  When in this state
   19322      * the user can not interact with the application; the system intercepts
   19323      * touching on the screen to pop the UI out of full screen mode.  See
   19324      * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
   19325      *
   19326      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
   19327      *      content}
   19328      *
   19329      * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
   19330      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
   19331      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
   19332      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
   19333      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
   19334      */
   19335     public void setSystemUiVisibility(int visibility) {
   19336         if (visibility != mSystemUiVisibility) {
   19337             mSystemUiVisibility = visibility;
   19338             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
   19339                 mParent.recomputeViewAttributes(this);
   19340             }
   19341         }
   19342     }
   19343 
   19344     /**
   19345      * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
   19346      * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
   19347      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
   19348      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
   19349      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
   19350      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
   19351      */
   19352     public int getSystemUiVisibility() {
   19353         return mSystemUiVisibility;
   19354     }
   19355 
   19356     /**
   19357      * Returns the current system UI visibility that is currently set for
   19358      * the entire window.  This is the combination of the
   19359      * {@link #setSystemUiVisibility(int)} values supplied by all of the
   19360      * views in the window.
   19361      */
   19362     public int getWindowSystemUiVisibility() {
   19363         return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
   19364     }
   19365 
   19366     /**
   19367      * Override to find out when the window's requested system UI visibility
   19368      * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
   19369      * This is different from the callbacks received through
   19370      * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
   19371      * in that this is only telling you about the local request of the window,
   19372      * not the actual values applied by the system.
   19373      */
   19374     public void onWindowSystemUiVisibilityChanged(int visible) {
   19375     }
   19376 
   19377     /**
   19378      * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
   19379      * the view hierarchy.
   19380      */
   19381     public void dispatchWindowSystemUiVisiblityChanged(int visible) {
   19382         onWindowSystemUiVisibilityChanged(visible);
   19383     }
   19384 
   19385     /**
   19386      * Set a listener to receive callbacks when the visibility of the system bar changes.
   19387      * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
   19388      */
   19389     public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
   19390         getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
   19391         if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
   19392             mParent.recomputeViewAttributes(this);
   19393         }
   19394     }
   19395 
   19396     /**
   19397      * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
   19398      * the view hierarchy.
   19399      */
   19400     public void dispatchSystemUiVisibilityChanged(int visibility) {
   19401         ListenerInfo li = mListenerInfo;
   19402         if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
   19403             li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
   19404                     visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
   19405         }
   19406     }
   19407 
   19408     boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
   19409         int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
   19410         if (val != mSystemUiVisibility) {
   19411             setSystemUiVisibility(val);
   19412             return true;
   19413         }
   19414         return false;
   19415     }
   19416 
   19417     /** @hide */
   19418     public void setDisabledSystemUiVisibility(int flags) {
   19419         if (mAttachInfo != null) {
   19420             if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
   19421                 mAttachInfo.mDisabledSystemUiVisibility = flags;
   19422                 if (mParent != null) {
   19423                     mParent.recomputeViewAttributes(this);
   19424                 }
   19425             }
   19426         }
   19427     }
   19428 
   19429     /**
   19430      * Creates an image that the system displays during the drag and drop
   19431      * operation. This is called a &quot;drag shadow&quot;. The default implementation
   19432      * for a DragShadowBuilder based on a View returns an image that has exactly the same
   19433      * appearance as the given View. The default also positions the center of the drag shadow
   19434      * directly under the touch point. If no View is provided (the constructor with no parameters
   19435      * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
   19436      * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
   19437      * default is an invisible drag shadow.
   19438      * <p>
   19439      * You are not required to use the View you provide to the constructor as the basis of the
   19440      * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
   19441      * anything you want as the drag shadow.
   19442      * </p>
   19443      * <p>
   19444      *  You pass a DragShadowBuilder object to the system when you start the drag. The system
   19445      *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
   19446      *  size and position of the drag shadow. It uses this data to construct a
   19447      *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
   19448      *  so that your application can draw the shadow image in the Canvas.
   19449      * </p>
   19450      *
   19451      * <div class="special reference">
   19452      * <h3>Developer Guides</h3>
   19453      * <p>For a guide to implementing drag and drop features, read the
   19454      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
   19455      * </div>
   19456      */
   19457     public static class DragShadowBuilder {
   19458         private final WeakReference<View> mView;
   19459 
   19460         /**
   19461          * Constructs a shadow image builder based on a View. By default, the resulting drag
   19462          * shadow will have the same appearance and dimensions as the View, with the touch point
   19463          * over the center of the View.
   19464          * @param view A View. Any View in scope can be used.
   19465          */
   19466         public DragShadowBuilder(View view) {
   19467             mView = new WeakReference<View>(view);
   19468         }
   19469 
   19470         /**
   19471          * Construct a shadow builder object with no associated View.  This
   19472          * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
   19473          * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
   19474          * to supply the drag shadow's dimensions and appearance without
   19475          * reference to any View object. If they are not overridden, then the result is an
   19476          * invisible drag shadow.
   19477          */
   19478         public DragShadowBuilder() {
   19479             mView = new WeakReference<View>(null);
   19480         }
   19481 
   19482         /**
   19483          * Returns the View object that had been passed to the
   19484          * {@link #View.DragShadowBuilder(View)}
   19485          * constructor.  If that View parameter was {@code null} or if the
   19486          * {@link #View.DragShadowBuilder()}
   19487          * constructor was used to instantiate the builder object, this method will return
   19488          * null.
   19489          *
   19490          * @return The View object associate with this builder object.
   19491          */
   19492         @SuppressWarnings({"JavadocReference"})
   19493         final public View getView() {
   19494             return mView.get();
   19495         }
   19496 
   19497         /**
   19498          * Provides the metrics for the shadow image. These include the dimensions of
   19499          * the shadow image, and the point within that shadow that should
   19500          * be centered under the touch location while dragging.
   19501          * <p>
   19502          * The default implementation sets the dimensions of the shadow to be the
   19503          * same as the dimensions of the View itself and centers the shadow under
   19504          * the touch point.
   19505          * </p>
   19506          *
   19507          * @param shadowSize A {@link android.graphics.Point} containing the width and height
   19508          * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
   19509          * desired width and must set {@link android.graphics.Point#y} to the desired height of the
   19510          * image.
   19511          *
   19512          * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
   19513          * shadow image that should be underneath the touch point during the drag and drop
   19514          * operation. Your application must set {@link android.graphics.Point#x} to the
   19515          * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
   19516          */
   19517         public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
   19518             final View view = mView.get();
   19519             if (view != null) {
   19520                 shadowSize.set(view.getWidth(), view.getHeight());
   19521                 shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
   19522             } else {
   19523                 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
   19524             }
   19525         }
   19526 
   19527         /**
   19528          * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
   19529          * based on the dimensions it received from the
   19530          * {@link #onProvideShadowMetrics(Point, Point)} callback.
   19531          *
   19532          * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
   19533          */
   19534         public void onDrawShadow(Canvas canvas) {
   19535             final View view = mView.get();
   19536             if (view != null) {
   19537                 view.draw(canvas);
   19538             } else {
   19539                 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
   19540             }
   19541         }
   19542     }
   19543 
   19544     /**
   19545      * Starts a drag and drop operation. When your application calls this method, it passes a
   19546      * {@link android.view.View.DragShadowBuilder} object to the system. The
   19547      * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
   19548      * to get metrics for the drag shadow, and then calls the object's
   19549      * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
   19550      * <p>
   19551      *  Once the system has the drag shadow, it begins the drag and drop operation by sending
   19552      *  drag events to all the View objects in your application that are currently visible. It does
   19553      *  this either by calling the View object's drag listener (an implementation of
   19554      *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
   19555      *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
   19556      *  Both are passed a {@link android.view.DragEvent} object that has a
   19557      *  {@link android.view.DragEvent#getAction()} value of
   19558      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
   19559      * </p>
   19560      * <p>
   19561      * Your application can invoke startDrag() on any attached View object. The View object does not
   19562      * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to
   19563      * be related to the View the user selected for dragging.
   19564      * </p>
   19565      * @param data A {@link android.content.ClipData} object pointing to the data to be
   19566      * transferred by the drag and drop operation.
   19567      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
   19568      * drag shadow.
   19569      * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
   19570      * drop operation. This Object is put into every DragEvent object sent by the system during the
   19571      * current drag.
   19572      * <p>
   19573      * myLocalState is a lightweight mechanism for the sending information from the dragged View
   19574      * to the target Views. For example, it can contain flags that differentiate between a
   19575      * a copy operation and a move operation.
   19576      * </p>
   19577      * @param flags Flags that control the drag and drop operation. No flags are currently defined,
   19578      * so the parameter should be set to 0.
   19579      * @return {@code true} if the method completes successfully, or
   19580      * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
   19581      * do a drag, and so no drag operation is in progress.
   19582      */
   19583     public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
   19584             Object myLocalState, int flags) {
   19585         if (ViewDebug.DEBUG_DRAG) {
   19586             Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags);
   19587         }
   19588         boolean okay = false;
   19589 
   19590         Point shadowSize = new Point();
   19591         Point shadowTouchPoint = new Point();
   19592         shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
   19593 
   19594         if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
   19595                 (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
   19596             throw new IllegalStateException("Drag shadow dimensions must not be negative");
   19597         }
   19598 
   19599         if (ViewDebug.DEBUG_DRAG) {
   19600             Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
   19601                     + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
   19602         }
   19603         Surface surface = new Surface();
   19604         try {
   19605             IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
   19606                     flags, shadowSize.x, shadowSize.y, surface);
   19607             if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
   19608                     + " surface=" + surface);
   19609             if (token != null) {
   19610                 Canvas canvas = surface.lockCanvas(null);
   19611                 try {
   19612                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
   19613                     shadowBuilder.onDrawShadow(canvas);
   19614                 } finally {
   19615                     surface.unlockCanvasAndPost(canvas);
   19616                 }
   19617 
   19618                 final ViewRootImpl root = getViewRootImpl();
   19619 
   19620                 // Cache the local state object for delivery with DragEvents
   19621                 root.setLocalDragState(myLocalState);
   19622 
   19623                 // repurpose 'shadowSize' for the last touch point
   19624                 root.getLastTouchPoint(shadowSize);
   19625 
   19626                 okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
   19627                         shadowSize.x, shadowSize.y,
   19628                         shadowTouchPoint.x, shadowTouchPoint.y, data);
   19629                 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
   19630 
   19631                 // Off and running!  Release our local surface instance; the drag
   19632                 // shadow surface is now managed by the system process.
   19633                 surface.release();
   19634             }
   19635         } catch (Exception e) {
   19636             Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
   19637             surface.destroy();
   19638         }
   19639 
   19640         return okay;
   19641     }
   19642 
   19643     /**
   19644      * Handles drag events sent by the system following a call to
   19645      * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}.
   19646      *<p>
   19647      * When the system calls this method, it passes a
   19648      * {@link android.view.DragEvent} object. A call to
   19649      * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
   19650      * in DragEvent. The method uses these to determine what is happening in the drag and drop
   19651      * operation.
   19652      * @param event The {@link android.view.DragEvent} sent by the system.
   19653      * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
   19654      * in DragEvent, indicating the type of drag event represented by this object.
   19655      * @return {@code true} if the method was successful, otherwise {@code false}.
   19656      * <p>
   19657      *  The method should return {@code true} in response to an action type of
   19658      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
   19659      *  operation.
   19660      * </p>
   19661      * <p>
   19662      *  The method should also return {@code true} in response to an action type of
   19663      *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
   19664      *  {@code false} if it didn't.
   19665      * </p>
   19666      */
   19667     public boolean onDragEvent(DragEvent event) {
   19668         return false;
   19669     }
   19670 
   19671     /**
   19672      * Detects if this View is enabled and has a drag event listener.
   19673      * If both are true, then it calls the drag event listener with the
   19674      * {@link android.view.DragEvent} it received. If the drag event listener returns
   19675      * {@code true}, then dispatchDragEvent() returns {@code true}.
   19676      * <p>
   19677      * For all other cases, the method calls the
   19678      * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
   19679      * method and returns its result.
   19680      * </p>
   19681      * <p>
   19682      * This ensures that a drag event is always consumed, even if the View does not have a drag
   19683      * event listener. However, if the View has a listener and the listener returns true, then
   19684      * onDragEvent() is not called.
   19685      * </p>
   19686      */
   19687     public boolean dispatchDragEvent(DragEvent event) {
   19688         ListenerInfo li = mListenerInfo;
   19689         //noinspection SimplifiableIfStatement
   19690         if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
   19691                 && li.mOnDragListener.onDrag(this, event)) {
   19692             return true;
   19693         }
   19694         return onDragEvent(event);
   19695     }
   19696 
   19697     boolean canAcceptDrag() {
   19698         return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
   19699     }
   19700 
   19701     /**
   19702      * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
   19703      * it is ever exposed at all.
   19704      * @hide
   19705      */
   19706     public void onCloseSystemDialogs(String reason) {
   19707     }
   19708 
   19709     /**
   19710      * Given a Drawable whose bounds have been set to draw into this view,
   19711      * update a Region being computed for
   19712      * {@link #gatherTransparentRegion(android.graphics.Region)} so
   19713      * that any non-transparent parts of the Drawable are removed from the
   19714      * given transparent region.
   19715      *
   19716      * @param dr The Drawable whose transparency is to be applied to the region.
   19717      * @param region A Region holding the current transparency information,
   19718      * where any parts of the region that are set are considered to be
   19719      * transparent.  On return, this region will be modified to have the
   19720      * transparency information reduced by the corresponding parts of the
   19721      * Drawable that are not transparent.
   19722      * {@hide}
   19723      */
   19724     public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
   19725         if (DBG) {
   19726             Log.i("View", "Getting transparent region for: " + this);
   19727         }
   19728         final Region r = dr.getTransparentRegion();
   19729         final Rect db = dr.getBounds();
   19730         final AttachInfo attachInfo = mAttachInfo;
   19731         if (r != null && attachInfo != null) {
   19732             final int w = getRight()-getLeft();
   19733             final int h = getBottom()-getTop();
   19734             if (db.left > 0) {
   19735                 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
   19736                 r.op(0, 0, db.left, h, Region.Op.UNION);
   19737             }
   19738             if (db.right < w) {
   19739                 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
   19740                 r.op(db.right, 0, w, h, Region.Op.UNION);
   19741             }
   19742             if (db.top > 0) {
   19743                 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
   19744                 r.op(0, 0, w, db.top, Region.Op.UNION);
   19745             }
   19746             if (db.bottom < h) {
   19747                 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
   19748                 r.op(0, db.bottom, w, h, Region.Op.UNION);
   19749             }
   19750             final int[] location = attachInfo.mTransparentLocation;
   19751             getLocationInWindow(location);
   19752             r.translate(location[0], location[1]);
   19753             region.op(r, Region.Op.INTERSECT);
   19754         } else {
   19755             region.op(db, Region.Op.DIFFERENCE);
   19756         }
   19757     }
   19758 
   19759     private void checkForLongClick(int delayOffset) {
   19760         if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
   19761             mHasPerformedLongPress = false;
   19762 
   19763             if (mPendingCheckForLongPress == null) {
   19764                 mPendingCheckForLongPress = new CheckForLongPress();
   19765             }
   19766             mPendingCheckForLongPress.rememberWindowAttachCount();
   19767             postDelayed(mPendingCheckForLongPress,
   19768                     ViewConfiguration.getLongPressTimeout() - delayOffset);
   19769         }
   19770     }
   19771 
   19772     /**
   19773      * Inflate a view from an XML resource.  This convenience method wraps the {@link
   19774      * LayoutInflater} class, which provides a full range of options for view inflation.
   19775      *
   19776      * @param context The Context object for your activity or application.
   19777      * @param resource The resource ID to inflate
   19778      * @param root A view group that will be the parent.  Used to properly inflate the
   19779      * layout_* parameters.
   19780      * @see LayoutInflater
   19781      */
   19782     public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
   19783         LayoutInflater factory = LayoutInflater.from(context);
   19784         return factory.inflate(resource, root);
   19785     }
   19786 
   19787     /**
   19788      * Scroll the view with standard behavior for scrolling beyond the normal
   19789      * content boundaries. Views that call this method should override
   19790      * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
   19791      * results of an over-scroll operation.
   19792      *
   19793      * Views can use this method to handle any touch or fling-based scrolling.
   19794      *
   19795      * @param deltaX Change in X in pixels
   19796      * @param deltaY Change in Y in pixels
   19797      * @param scrollX Current X scroll value in pixels before applying deltaX
   19798      * @param scrollY Current Y scroll value in pixels before applying deltaY
   19799      * @param scrollRangeX Maximum content scroll range along the X axis
   19800      * @param scrollRangeY Maximum content scroll range along the Y axis
   19801      * @param maxOverScrollX Number of pixels to overscroll by in either direction
   19802      *          along the X axis.
   19803      * @param maxOverScrollY Number of pixels to overscroll by in either direction
   19804      *          along the Y axis.
   19805      * @param isTouchEvent true if this scroll operation is the result of a touch event.
   19806      * @return true if scrolling was clamped to an over-scroll boundary along either
   19807      *          axis, false otherwise.
   19808      */
   19809     @SuppressWarnings({"UnusedParameters"})
   19810     protected boolean overScrollBy(int deltaX, int deltaY,
   19811             int scrollX, int scrollY,
   19812             int scrollRangeX, int scrollRangeY,
   19813             int maxOverScrollX, int maxOverScrollY,
   19814             boolean isTouchEvent) {
   19815         final int overScrollMode = mOverScrollMode;
   19816         final boolean canScrollHorizontal =
   19817                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
   19818         final boolean canScrollVertical =
   19819                 computeVerticalScrollRange() > computeVerticalScrollExtent();
   19820         final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
   19821                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
   19822         final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
   19823                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
   19824 
   19825         int newScrollX = scrollX + deltaX;
   19826         if (!overScrollHorizontal) {
   19827             maxOverScrollX = 0;
   19828         }
   19829 
   19830         int newScrollY = scrollY + deltaY;
   19831         if (!overScrollVertical) {
   19832             maxOverScrollY = 0;
   19833         }
   19834 
   19835         // Clamp values if at the limits and record
   19836         final int left = -maxOverScrollX;
   19837         final int right = maxOverScrollX + scrollRangeX;
   19838         final int top = -maxOverScrollY;
   19839         final int bottom = maxOverScrollY + scrollRangeY;
   19840 
   19841         boolean clampedX = false;
   19842         if (newScrollX > right) {
   19843             newScrollX = right;
   19844             clampedX = true;
   19845         } else if (newScrollX < left) {
   19846             newScrollX = left;
   19847             clampedX = true;
   19848         }
   19849 
   19850         boolean clampedY = false;
   19851         if (newScrollY > bottom) {
   19852             newScrollY = bottom;
   19853             clampedY = true;
   19854         } else if (newScrollY < top) {
   19855             newScrollY = top;
   19856             clampedY = true;
   19857         }
   19858 
   19859         onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
   19860 
   19861         return clampedX || clampedY;
   19862     }
   19863 
   19864     /**
   19865      * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
   19866      * respond to the results of an over-scroll operation.
   19867      *
   19868      * @param scrollX New X scroll value in pixels
   19869      * @param scrollY New Y scroll value in pixels
   19870      * @param clampedX True if scrollX was clamped to an over-scroll boundary
   19871      * @param clampedY True if scrollY was clamped to an over-scroll boundary
   19872      */
   19873     protected void onOverScrolled(int scrollX, int scrollY,
   19874             boolean clampedX, boolean clampedY) {
   19875         // Intentionally empty.
   19876     }
   19877 
   19878     /**
   19879      * Returns the over-scroll mode for this view. The result will be
   19880      * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
   19881      * (allow over-scrolling only if the view content is larger than the container),
   19882      * or {@link #OVER_SCROLL_NEVER}.
   19883      *
   19884      * @return This view's over-scroll mode.
   19885      */
   19886     public int getOverScrollMode() {
   19887         return mOverScrollMode;
   19888     }
   19889 
   19890     /**
   19891      * Set the over-scroll mode for this view. Valid over-scroll modes are
   19892      * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
   19893      * (allow over-scrolling only if the view content is larger than the container),
   19894      * or {@link #OVER_SCROLL_NEVER}.
   19895      *
   19896      * Setting the over-scroll mode of a view will have an effect only if the
   19897      * view is capable of scrolling.
   19898      *
   19899      * @param overScrollMode The new over-scroll mode for this view.
   19900      */
   19901     public void setOverScrollMode(int overScrollMode) {
   19902         if (overScrollMode != OVER_SCROLL_ALWAYS &&
   19903                 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
   19904                 overScrollMode != OVER_SCROLL_NEVER) {
   19905             throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
   19906         }
   19907         mOverScrollMode = overScrollMode;
   19908     }
   19909 
   19910     /**
   19911      * Enable or disable nested scrolling for this view.
   19912      *
   19913      * <p>If this property is set to true the view will be permitted to initiate nested
   19914      * scrolling operations with a compatible parent view in the current hierarchy. If this
   19915      * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
   19916      * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
   19917      * the nested scroll.</p>
   19918      *
   19919      * @param enabled true to enable nested scrolling, false to disable
   19920      *
   19921      * @see #isNestedScrollingEnabled()
   19922      */
   19923     public void setNestedScrollingEnabled(boolean enabled) {
   19924         if (enabled) {
   19925             mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
   19926         } else {
   19927             stopNestedScroll();
   19928             mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
   19929         }
   19930     }
   19931 
   19932     /**
   19933      * Returns true if nested scrolling is enabled for this view.
   19934      *
   19935      * <p>If nested scrolling is enabled and this View class implementation supports it,
   19936      * this view will act as a nested scrolling child view when applicable, forwarding data
   19937      * about the scroll operation in progress to a compatible and cooperating nested scrolling
   19938      * parent.</p>
   19939      *
   19940      * @return true if nested scrolling is enabled
   19941      *
   19942      * @see #setNestedScrollingEnabled(boolean)
   19943      */
   19944     public boolean isNestedScrollingEnabled() {
   19945         return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
   19946                 PFLAG3_NESTED_SCROLLING_ENABLED;
   19947     }
   19948 
   19949     /**
   19950      * Begin a nestable scroll operation along the given axes.
   19951      *
   19952      * <p>A view starting a nested scroll promises to abide by the following contract:</p>
   19953      *
   19954      * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
   19955      * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
   19956      * In the case of touch scrolling the nested scroll will be terminated automatically in
   19957      * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
   19958      * In the event of programmatic scrolling the caller must explicitly call
   19959      * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
   19960      *
   19961      * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
   19962      * If it returns false the caller may ignore the rest of this contract until the next scroll.
   19963      * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
   19964      *
   19965      * <p>At each incremental step of the scroll the caller should invoke
   19966      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
   19967      * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
   19968      * parent at least partially consumed the scroll and the caller should adjust the amount it
   19969      * scrolls by.</p>
   19970      *
   19971      * <p>After applying the remainder of the scroll delta the caller should invoke
   19972      * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
   19973      * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
   19974      * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
   19975      * </p>
   19976      *
   19977      * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
   19978      *             {@link #SCROLL_AXIS_VERTICAL}.
   19979      * @return true if a cooperative parent was found and nested scrolling has been enabled for
   19980      *         the current gesture.
   19981      *
   19982      * @see #stopNestedScroll()
   19983      * @see #dispatchNestedPreScroll(int, int, int[], int[])
   19984      * @see #dispatchNestedScroll(int, int, int, int, int[])
   19985      */
   19986     public boolean startNestedScroll(int axes) {
   19987         if (hasNestedScrollingParent()) {
   19988             // Already in progress
   19989             return true;
   19990         }
   19991         if (isNestedScrollingEnabled()) {
   19992             ViewParent p = getParent();
   19993             View child = this;
   19994             while (p != null) {
   19995                 try {
   19996                     if (p.onStartNestedScroll(child, this, axes)) {
   19997                         mNestedScrollingParent = p;
   19998                         p.onNestedScrollAccepted(child, this, axes);
   19999                         return true;
   20000                     }
   20001                 } catch (AbstractMethodError e) {
   20002                     Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
   20003                             "method onStartNestedScroll", e);
   20004                     // Allow the search upward to continue
   20005                 }
   20006                 if (p instanceof View) {
   20007                     child = (View) p;
   20008                 }
   20009                 p = p.getParent();
   20010             }
   20011         }
   20012         return false;
   20013     }
   20014 
   20015     /**
   20016      * Stop a nested scroll in progress.
   20017      *
   20018      * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
   20019      *
   20020      * @see #startNestedScroll(int)
   20021      */
   20022     public void stopNestedScroll() {
   20023         if (mNestedScrollingParent != null) {
   20024             mNestedScrollingParent.onStopNestedScroll(this);
   20025             mNestedScrollingParent = null;
   20026         }
   20027     }
   20028 
   20029     /**
   20030      * Returns true if this view has a nested scrolling parent.
   20031      *
   20032      * <p>The presence of a nested scrolling parent indicates that this view has initiated
   20033      * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
   20034      *
   20035      * @return whether this view has a nested scrolling parent
   20036      */
   20037     public boolean hasNestedScrollingParent() {
   20038         return mNestedScrollingParent != null;
   20039     }
   20040 
   20041     /**
   20042      * Dispatch one step of a nested scroll in progress.
   20043      *
   20044      * <p>Implementations of views that support nested scrolling should call this to report
   20045      * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
   20046      * is not currently in progress or nested scrolling is not
   20047      * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
   20048      *
   20049      * <p>Compatible View implementations should also call
   20050      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
   20051      * consuming a component of the scroll event themselves.</p>
   20052      *
   20053      * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
   20054      * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
   20055      * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
   20056      * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
   20057      * @param offsetInWindow Optional. If not null, on return this will contain the offset
   20058      *                       in local view coordinates of this view from before this operation
   20059      *                       to after it completes. View implementations may use this to adjust
   20060      *                       expected input coordinate tracking.
   20061      * @return true if the event was dispatched, false if it could not be dispatched.
   20062      * @see #dispatchNestedPreScroll(int, int, int[], int[])
   20063      */
   20064     public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
   20065             int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
   20066         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
   20067             if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
   20068                 int startX = 0;
   20069                 int startY = 0;
   20070                 if (offsetInWindow != null) {
   20071                     getLocationInWindow(offsetInWindow);
   20072                     startX = offsetInWindow[0];
   20073                     startY = offsetInWindow[1];
   20074                 }
   20075 
   20076                 mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
   20077                         dxUnconsumed, dyUnconsumed);
   20078 
   20079                 if (offsetInWindow != null) {
   20080                     getLocationInWindow(offsetInWindow);
   20081                     offsetInWindow[0] -= startX;
   20082                     offsetInWindow[1] -= startY;
   20083                 }
   20084                 return true;
   20085             } else if (offsetInWindow != null) {
   20086                 // No motion, no dispatch. Keep offsetInWindow up to date.
   20087                 offsetInWindow[0] = 0;
   20088                 offsetInWindow[1] = 0;
   20089             }
   20090         }
   20091         return false;
   20092     }
   20093 
   20094     /**
   20095      * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
   20096      *
   20097      * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
   20098      * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
   20099      * scrolling operation to consume some or all of the scroll operation before the child view
   20100      * consumes it.</p>
   20101      *
   20102      * @param dx Horizontal scroll distance in pixels
   20103      * @param dy Vertical scroll distance in pixels
   20104      * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
   20105      *                 and consumed[1] the consumed dy.
   20106      * @param offsetInWindow Optional. If not null, on return this will contain the offset
   20107      *                       in local view coordinates of this view from before this operation
   20108      *                       to after it completes. View implementations may use this to adjust
   20109      *                       expected input coordinate tracking.
   20110      * @return true if the parent consumed some or all of the scroll delta
   20111      * @see #dispatchNestedScroll(int, int, int, int, int[])
   20112      */
   20113     public boolean dispatchNestedPreScroll(int dx, int dy,
   20114             @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
   20115         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
   20116             if (dx != 0 || dy != 0) {
   20117                 int startX = 0;
   20118                 int startY = 0;
   20119                 if (offsetInWindow != null) {
   20120                     getLocationInWindow(offsetInWindow);
   20121                     startX = offsetInWindow[0];
   20122                     startY = offsetInWindow[1];
   20123                 }
   20124 
   20125                 if (consumed == null) {
   20126                     if (mTempNestedScrollConsumed == null) {
   20127                         mTempNestedScrollConsumed = new int[2];
   20128                     }
   20129                     consumed = mTempNestedScrollConsumed;
   20130                 }
   20131                 consumed[0] = 0;
   20132                 consumed[1] = 0;
   20133                 mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
   20134 
   20135                 if (offsetInWindow != null) {
   20136                     getLocationInWindow(offsetInWindow);
   20137                     offsetInWindow[0] -= startX;
   20138                     offsetInWindow[1] -= startY;
   20139                 }
   20140                 return consumed[0] != 0 || consumed[1] != 0;
   20141             } else if (offsetInWindow != null) {
   20142                 offsetInWindow[0] = 0;
   20143                 offsetInWindow[1] = 0;
   20144             }
   20145         }
   20146         return false;
   20147     }
   20148 
   20149     /**
   20150      * Dispatch a fling to a nested scrolling parent.
   20151      *
   20152      * <p>This method should be used to indicate that a nested scrolling child has detected
   20153      * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
   20154      * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
   20155      * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
   20156      * along a scrollable axis.</p>
   20157      *
   20158      * <p>If a nested scrolling child view would normally fling but it is at the edge of
   20159      * its own content, it can use this method to delegate the fling to its nested scrolling
   20160      * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
   20161      *
   20162      * @param velocityX Horizontal fling velocity in pixels per second
   20163      * @param velocityY Vertical fling velocity in pixels per second
   20164      * @param consumed true if the child consumed the fling, false otherwise
   20165      * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
   20166      */
   20167     public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
   20168         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
   20169             return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
   20170         }
   20171         return false;
   20172     }
   20173 
   20174     /**
   20175      * Dispatch a fling to a nested scrolling parent before it is processed by this view.
   20176      *
   20177      * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
   20178      * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
   20179      * offsets an opportunity for the parent view in a nested fling to fully consume the fling
   20180      * before the child view consumes it. If this method returns <code>true</code>, a nested
   20181      * parent view consumed the fling and this view should not scroll as a result.</p>
   20182      *
   20183      * <p>For a better user experience, only one view in a nested scrolling chain should consume
   20184      * the fling at a time. If a parent view consumed the fling this method will return false.
   20185      * Custom view implementations should account for this in two ways:</p>
   20186      *
   20187      * <ul>
   20188      *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
   20189      *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
   20190      *     position regardless.</li>
   20191      *     <li>If a nested parent does consume the fling, this view should not scroll at all,
   20192      *     even to settle back to a valid idle position.</li>
   20193      * </ul>
   20194      *
   20195      * <p>Views should also not offer fling velocities to nested parent views along an axis
   20196      * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
   20197      * should not offer a horizontal fling velocity to its parents since scrolling along that
   20198      * axis is not permitted and carrying velocity along that motion does not make sense.</p>
   20199      *
   20200      * @param velocityX Horizontal fling velocity in pixels per second
   20201      * @param velocityY Vertical fling velocity in pixels per second
   20202      * @return true if a nested scrolling parent consumed the fling
   20203      */
   20204     public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
   20205         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
   20206             return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
   20207         }
   20208         return false;
   20209     }
   20210 
   20211     /**
   20212      * Gets a scale factor that determines the distance the view should scroll
   20213      * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
   20214      * @return The vertical scroll scale factor.
   20215      * @hide
   20216      */
   20217     protected float getVerticalScrollFactor() {
   20218         if (mVerticalScrollFactor == 0) {
   20219             TypedValue outValue = new TypedValue();
   20220             if (!mContext.getTheme().resolveAttribute(
   20221                     com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
   20222                 throw new IllegalStateException(
   20223                         "Expected theme to define listPreferredItemHeight.");
   20224             }
   20225             mVerticalScrollFactor = outValue.getDimension(
   20226                     mContext.getResources().getDisplayMetrics());
   20227         }
   20228         return mVerticalScrollFactor;
   20229     }
   20230 
   20231     /**
   20232      * Gets a scale factor that determines the distance the view should scroll
   20233      * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
   20234      * @return The horizontal scroll scale factor.
   20235      * @hide
   20236      */
   20237     protected float getHorizontalScrollFactor() {
   20238         // TODO: Should use something else.
   20239         return getVerticalScrollFactor();
   20240     }
   20241 
   20242     /**
   20243      * Return the value specifying the text direction or policy that was set with
   20244      * {@link #setTextDirection(int)}.
   20245      *
   20246      * @return the defined text direction. It can be one of:
   20247      *
   20248      * {@link #TEXT_DIRECTION_INHERIT},
   20249      * {@link #TEXT_DIRECTION_FIRST_STRONG},
   20250      * {@link #TEXT_DIRECTION_ANY_RTL},
   20251      * {@link #TEXT_DIRECTION_LTR},
   20252      * {@link #TEXT_DIRECTION_RTL},
   20253      * {@link #TEXT_DIRECTION_LOCALE},
   20254      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
   20255      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
   20256      *
   20257      * @attr ref android.R.styleable#View_textDirection
   20258      *
   20259      * @hide
   20260      */
   20261     @ViewDebug.ExportedProperty(category = "text", mapping = {
   20262             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
   20263             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
   20264             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
   20265             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
   20266             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
   20267             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
   20268             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
   20269             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
   20270     })
   20271     public int getRawTextDirection() {
   20272         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
   20273     }
   20274 
   20275     /**
   20276      * Set the text direction.
   20277      *
   20278      * @param textDirection the direction to set. Should be one of:
   20279      *
   20280      * {@link #TEXT_DIRECTION_INHERIT},
   20281      * {@link #TEXT_DIRECTION_FIRST_STRONG},
   20282      * {@link #TEXT_DIRECTION_ANY_RTL},
   20283      * {@link #TEXT_DIRECTION_LTR},
   20284      * {@link #TEXT_DIRECTION_RTL},
   20285      * {@link #TEXT_DIRECTION_LOCALE}
   20286      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
   20287      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
   20288      *
   20289      * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
   20290      * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
   20291      * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
   20292      *
   20293      * @attr ref android.R.styleable#View_textDirection
   20294      */
   20295     public void setTextDirection(int textDirection) {
   20296         if (getRawTextDirection() != textDirection) {
   20297             // Reset the current text direction and the resolved one
   20298             mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
   20299             resetResolvedTextDirection();
   20300             // Set the new text direction
   20301             mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
   20302             // Do resolution
   20303             resolveTextDirection();
   20304             // Notify change
   20305             onRtlPropertiesChanged(getLayoutDirection());
   20306             // Refresh
   20307             requestLayout();
   20308             invalidate(true);
   20309         }
   20310     }
   20311 
   20312     /**
   20313      * Return the resolved text direction.
   20314      *
   20315      * @return the resolved text direction. Returns one of:
   20316      *
   20317      * {@link #TEXT_DIRECTION_FIRST_STRONG},
   20318      * {@link #TEXT_DIRECTION_ANY_RTL},
   20319      * {@link #TEXT_DIRECTION_LTR},
   20320      * {@link #TEXT_DIRECTION_RTL},
   20321      * {@link #TEXT_DIRECTION_LOCALE},
   20322      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
   20323      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
   20324      *
   20325      * @attr ref android.R.styleable#View_textDirection
   20326      */
   20327     @ViewDebug.ExportedProperty(category = "text", mapping = {
   20328             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
   20329             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
   20330             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
   20331             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
   20332             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
   20333             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
   20334             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
   20335             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
   20336     })
   20337     public int getTextDirection() {
   20338         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
   20339     }
   20340 
   20341     /**
   20342      * Resolve the text direction.
   20343      *
   20344      * @return true if resolution has been done, false otherwise.
   20345      *
   20346      * @hide
   20347      */
   20348     public boolean resolveTextDirection() {
   20349         // Reset any previous text direction resolution
   20350         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
   20351 
   20352         if (hasRtlSupport()) {
   20353             // Set resolved text direction flag depending on text direction flag
   20354             final int textDirection = getRawTextDirection();
   20355             switch(textDirection) {
   20356                 case TEXT_DIRECTION_INHERIT:
   20357                     if (!canResolveTextDirection()) {
   20358                         // We cannot do the resolution if there is no parent, so use the default one
   20359                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   20360                         // Resolution will need to happen again later
   20361                         return false;
   20362                     }
   20363 
   20364                     // Parent has not yet resolved, so we still return the default
   20365                     try {
   20366                         if (!mParent.isTextDirectionResolved()) {
   20367                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   20368                             // Resolution will need to happen again later
   20369                             return false;
   20370                         }
   20371                     } catch (AbstractMethodError e) {
   20372                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   20373                                 " does not fully implement ViewParent", e);
   20374                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
   20375                                 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   20376                         return true;
   20377                     }
   20378 
   20379                     // Set current resolved direction to the same value as the parent's one
   20380                     int parentResolvedDirection;
   20381                     try {
   20382                         parentResolvedDirection = mParent.getTextDirection();
   20383                     } catch (AbstractMethodError e) {
   20384                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   20385                                 " does not fully implement ViewParent", e);
   20386                         parentResolvedDirection = TEXT_DIRECTION_LTR;
   20387                     }
   20388                     switch (parentResolvedDirection) {
   20389                         case TEXT_DIRECTION_FIRST_STRONG:
   20390                         case TEXT_DIRECTION_ANY_RTL:
   20391                         case TEXT_DIRECTION_LTR:
   20392                         case TEXT_DIRECTION_RTL:
   20393                         case TEXT_DIRECTION_LOCALE:
   20394                         case TEXT_DIRECTION_FIRST_STRONG_LTR:
   20395                         case TEXT_DIRECTION_FIRST_STRONG_RTL:
   20396                             mPrivateFlags2 |=
   20397                                     (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
   20398                             break;
   20399                         default:
   20400                             // Default resolved direction is "first strong" heuristic
   20401                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   20402                     }
   20403                     break;
   20404                 case TEXT_DIRECTION_FIRST_STRONG:
   20405                 case TEXT_DIRECTION_ANY_RTL:
   20406                 case TEXT_DIRECTION_LTR:
   20407                 case TEXT_DIRECTION_RTL:
   20408                 case TEXT_DIRECTION_LOCALE:
   20409                 case TEXT_DIRECTION_FIRST_STRONG_LTR:
   20410                 case TEXT_DIRECTION_FIRST_STRONG_RTL:
   20411                     // Resolved direction is the same as text direction
   20412                     mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
   20413                     break;
   20414                 default:
   20415                     // Default resolved direction is "first strong" heuristic
   20416                     mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   20417             }
   20418         } else {
   20419             // Default resolved direction is "first strong" heuristic
   20420             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   20421         }
   20422 
   20423         // Set to resolved
   20424         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
   20425         return true;
   20426     }
   20427 
   20428     /**
   20429      * Check if text direction resolution can be done.
   20430      *
   20431      * @return true if text direction resolution can be done otherwise return false.
   20432      */
   20433     public boolean canResolveTextDirection() {
   20434         switch (getRawTextDirection()) {
   20435             case TEXT_DIRECTION_INHERIT:
   20436                 if (mParent != null) {
   20437                     try {
   20438                         return mParent.canResolveTextDirection();
   20439                     } catch (AbstractMethodError e) {
   20440                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   20441                                 " does not fully implement ViewParent", e);
   20442                     }
   20443                 }
   20444                 return false;
   20445 
   20446             default:
   20447                 return true;
   20448         }
   20449     }
   20450 
   20451     /**
   20452      * Reset resolved text direction. Text direction will be resolved during a call to
   20453      * {@link #onMeasure(int, int)}.
   20454      *
   20455      * @hide
   20456      */
   20457     public void resetResolvedTextDirection() {
   20458         // Reset any previous text direction resolution
   20459         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
   20460         // Set to default value
   20461         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
   20462     }
   20463 
   20464     /**
   20465      * @return true if text direction is inherited.
   20466      *
   20467      * @hide
   20468      */
   20469     public boolean isTextDirectionInherited() {
   20470         return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
   20471     }
   20472 
   20473     /**
   20474      * @return true if text direction is resolved.
   20475      */
   20476     public boolean isTextDirectionResolved() {
   20477         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
   20478     }
   20479 
   20480     /**
   20481      * Return the value specifying the text alignment or policy that was set with
   20482      * {@link #setTextAlignment(int)}.
   20483      *
   20484      * @return the defined text alignment. It can be one of:
   20485      *
   20486      * {@link #TEXT_ALIGNMENT_INHERIT},
   20487      * {@link #TEXT_ALIGNMENT_GRAVITY},
   20488      * {@link #TEXT_ALIGNMENT_CENTER},
   20489      * {@link #TEXT_ALIGNMENT_TEXT_START},
   20490      * {@link #TEXT_ALIGNMENT_TEXT_END},
   20491      * {@link #TEXT_ALIGNMENT_VIEW_START},
   20492      * {@link #TEXT_ALIGNMENT_VIEW_END}
   20493      *
   20494      * @attr ref android.R.styleable#View_textAlignment
   20495      *
   20496      * @hide
   20497      */
   20498     @ViewDebug.ExportedProperty(category = "text", mapping = {
   20499             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
   20500             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
   20501             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
   20502             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
   20503             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
   20504             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
   20505             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
   20506     })
   20507     @TextAlignment
   20508     public int getRawTextAlignment() {
   20509         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
   20510     }
   20511 
   20512     /**
   20513      * Set the text alignment.
   20514      *
   20515      * @param textAlignment The text alignment to set. Should be one of
   20516      *
   20517      * {@link #TEXT_ALIGNMENT_INHERIT},
   20518      * {@link #TEXT_ALIGNMENT_GRAVITY},
   20519      * {@link #TEXT_ALIGNMENT_CENTER},
   20520      * {@link #TEXT_ALIGNMENT_TEXT_START},
   20521      * {@link #TEXT_ALIGNMENT_TEXT_END},
   20522      * {@link #TEXT_ALIGNMENT_VIEW_START},
   20523      * {@link #TEXT_ALIGNMENT_VIEW_END}
   20524      *
   20525      * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
   20526      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
   20527      * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
   20528      *
   20529      * @attr ref android.R.styleable#View_textAlignment
   20530      */
   20531     public void setTextAlignment(@TextAlignment int textAlignment) {
   20532         if (textAlignment != getRawTextAlignment()) {
   20533             // Reset the current and resolved text alignment
   20534             mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
   20535             resetResolvedTextAlignment();
   20536             // Set the new text alignment
   20537             mPrivateFlags2 |=
   20538                     ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
   20539             // Do resolution
   20540             resolveTextAlignment();
   20541             // Notify change
   20542             onRtlPropertiesChanged(getLayoutDirection());
   20543             // Refresh
   20544             requestLayout();
   20545             invalidate(true);
   20546         }
   20547     }
   20548 
   20549     /**
   20550      * Return the resolved text alignment.
   20551      *
   20552      * @return the resolved text alignment. Returns one of:
   20553      *
   20554      * {@link #TEXT_ALIGNMENT_GRAVITY},
   20555      * {@link #TEXT_ALIGNMENT_CENTER},
   20556      * {@link #TEXT_ALIGNMENT_TEXT_START},
   20557      * {@link #TEXT_ALIGNMENT_TEXT_END},
   20558      * {@link #TEXT_ALIGNMENT_VIEW_START},
   20559      * {@link #TEXT_ALIGNMENT_VIEW_END}
   20560      *
   20561      * @attr ref android.R.styleable#View_textAlignment
   20562      */
   20563     @ViewDebug.ExportedProperty(category = "text", mapping = {
   20564             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
   20565             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
   20566             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
   20567             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
   20568             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
   20569             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
   20570             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
   20571     })
   20572     @TextAlignment
   20573     public int getTextAlignment() {
   20574         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
   20575                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
   20576     }
   20577 
   20578     /**
   20579      * Resolve the text alignment.
   20580      *
   20581      * @return true if resolution has been done, false otherwise.
   20582      *
   20583      * @hide
   20584      */
   20585     public boolean resolveTextAlignment() {
   20586         // Reset any previous text alignment resolution
   20587         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
   20588 
   20589         if (hasRtlSupport()) {
   20590             // Set resolved text alignment flag depending on text alignment flag
   20591             final int textAlignment = getRawTextAlignment();
   20592             switch (textAlignment) {
   20593                 case TEXT_ALIGNMENT_INHERIT:
   20594                     // Check if we can resolve the text alignment
   20595                     if (!canResolveTextAlignment()) {
   20596                         // We cannot do the resolution if there is no parent so use the default
   20597                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   20598                         // Resolution will need to happen again later
   20599                         return false;
   20600                     }
   20601 
   20602                     // Parent has not yet resolved, so we still return the default
   20603                     try {
   20604                         if (!mParent.isTextAlignmentResolved()) {
   20605                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   20606                             // Resolution will need to happen again later
   20607                             return false;
   20608                         }
   20609                     } catch (AbstractMethodError e) {
   20610                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   20611                                 " does not fully implement ViewParent", e);
   20612                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
   20613                                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   20614                         return true;
   20615                     }
   20616 
   20617                     int parentResolvedTextAlignment;
   20618                     try {
   20619                         parentResolvedTextAlignment = mParent.getTextAlignment();
   20620                     } catch (AbstractMethodError e) {
   20621                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   20622                                 " does not fully implement ViewParent", e);
   20623                         parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
   20624                     }
   20625                     switch (parentResolvedTextAlignment) {
   20626                         case TEXT_ALIGNMENT_GRAVITY:
   20627                         case TEXT_ALIGNMENT_TEXT_START:
   20628                         case TEXT_ALIGNMENT_TEXT_END:
   20629                         case TEXT_ALIGNMENT_CENTER:
   20630                         case TEXT_ALIGNMENT_VIEW_START:
   20631                         case TEXT_ALIGNMENT_VIEW_END:
   20632                             // Resolved text alignment is the same as the parent resolved
   20633                             // text alignment
   20634                             mPrivateFlags2 |=
   20635                                     (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
   20636                             break;
   20637                         default:
   20638                             // Use default resolved text alignment
   20639                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   20640                     }
   20641                     break;
   20642                 case TEXT_ALIGNMENT_GRAVITY:
   20643                 case TEXT_ALIGNMENT_TEXT_START:
   20644                 case TEXT_ALIGNMENT_TEXT_END:
   20645                 case TEXT_ALIGNMENT_CENTER:
   20646                 case TEXT_ALIGNMENT_VIEW_START:
   20647                 case TEXT_ALIGNMENT_VIEW_END:
   20648                     // Resolved text alignment is the same as text alignment
   20649                     mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
   20650                     break;
   20651                 default:
   20652                     // Use default resolved text alignment
   20653                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   20654             }
   20655         } else {
   20656             // Use default resolved text alignment
   20657             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   20658         }
   20659 
   20660         // Set the resolved
   20661         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
   20662         return true;
   20663     }
   20664 
   20665     /**
   20666      * Check if text alignment resolution can be done.
   20667      *
   20668      * @return true if text alignment resolution can be done otherwise return false.
   20669      */
   20670     public boolean canResolveTextAlignment() {
   20671         switch (getRawTextAlignment()) {
   20672             case TEXT_DIRECTION_INHERIT:
   20673                 if (mParent != null) {
   20674                     try {
   20675                         return mParent.canResolveTextAlignment();
   20676                     } catch (AbstractMethodError e) {
   20677                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
   20678                                 " does not fully implement ViewParent", e);
   20679                     }
   20680                 }
   20681                 return false;
   20682 
   20683             default:
   20684                 return true;
   20685         }
   20686     }
   20687 
   20688     /**
   20689      * Reset resolved text alignment. Text alignment will be resolved during a call to
   20690      * {@link #onMeasure(int, int)}.
   20691      *
   20692      * @hide
   20693      */
   20694     public void resetResolvedTextAlignment() {
   20695         // Reset any previous text alignment resolution
   20696         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
   20697         // Set to default
   20698         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
   20699     }
   20700 
   20701     /**
   20702      * @return true if text alignment is inherited.
   20703      *
   20704      * @hide
   20705      */
   20706     public boolean isTextAlignmentInherited() {
   20707         return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
   20708     }
   20709 
   20710     /**
   20711      * @return true if text alignment is resolved.
   20712      */
   20713     public boolean isTextAlignmentResolved() {
   20714         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
   20715     }
   20716 
   20717     /**
   20718      * Generate a value suitable for use in {@link #setId(int)}.
   20719      * This value will not collide with ID values generated at build time by aapt for R.id.
   20720      *
   20721      * @return a generated ID value
   20722      */
   20723     public static int generateViewId() {
   20724         for (;;) {
   20725             final int result = sNextGeneratedId.get();
   20726             // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
   20727             int newValue = result + 1;
   20728             if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
   20729             if (sNextGeneratedId.compareAndSet(result, newValue)) {
   20730                 return result;
   20731             }
   20732         }
   20733     }
   20734 
   20735     /**
   20736      * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
   20737      * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
   20738      *                           a normal View or a ViewGroup with
   20739      *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
   20740      * @hide
   20741      */
   20742     public void captureTransitioningViews(List<View> transitioningViews) {
   20743         if (getVisibility() == View.VISIBLE) {
   20744             transitioningViews.add(this);
   20745         }
   20746     }
   20747 
   20748     /**
   20749      * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
   20750      * @param namedElements Will contain all Views in the hierarchy having a transitionName.
   20751      * @hide
   20752      */
   20753     public void findNamedViews(Map<String, View> namedElements) {
   20754         if (getVisibility() == VISIBLE || mGhostView != null) {
   20755             String transitionName = getTransitionName();
   20756             if (transitionName != null) {
   20757                 namedElements.put(transitionName, this);
   20758             }
   20759         }
   20760     }
   20761 
   20762     //
   20763     // Properties
   20764     //
   20765     /**
   20766      * A Property wrapper around the <code>alpha</code> functionality handled by the
   20767      * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
   20768      */
   20769     public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
   20770         @Override
   20771         public void setValue(View object, float value) {
   20772             object.setAlpha(value);
   20773         }
   20774 
   20775         @Override
   20776         public Float get(View object) {
   20777             return object.getAlpha();
   20778         }
   20779     };
   20780 
   20781     /**
   20782      * A Property wrapper around the <code>translationX</code> functionality handled by the
   20783      * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
   20784      */
   20785     public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
   20786         @Override
   20787         public void setValue(View object, float value) {
   20788             object.setTranslationX(value);
   20789         }
   20790 
   20791                 @Override
   20792         public Float get(View object) {
   20793             return object.getTranslationX();
   20794         }
   20795     };
   20796 
   20797     /**
   20798      * A Property wrapper around the <code>translationY</code> functionality handled by the
   20799      * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
   20800      */
   20801     public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
   20802         @Override
   20803         public void setValue(View object, float value) {
   20804             object.setTranslationY(value);
   20805         }
   20806 
   20807         @Override
   20808         public Float get(View object) {
   20809             return object.getTranslationY();
   20810         }
   20811     };
   20812 
   20813     /**
   20814      * A Property wrapper around the <code>translationZ</code> functionality handled by the
   20815      * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
   20816      */
   20817     public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
   20818         @Override
   20819         public void setValue(View object, float value) {
   20820             object.setTranslationZ(value);
   20821         }
   20822 
   20823         @Override
   20824         public Float get(View object) {
   20825             return object.getTranslationZ();
   20826         }
   20827     };
   20828 
   20829     /**
   20830      * A Property wrapper around the <code>x</code> functionality handled by the
   20831      * {@link View#setX(float)} and {@link View#getX()} methods.
   20832      */
   20833     public static final Property<View, Float> X = new FloatProperty<View>("x") {
   20834         @Override
   20835         public void setValue(View object, float value) {
   20836             object.setX(value);
   20837         }
   20838 
   20839         @Override
   20840         public Float get(View object) {
   20841             return object.getX();
   20842         }
   20843     };
   20844 
   20845     /**
   20846      * A Property wrapper around the <code>y</code> functionality handled by the
   20847      * {@link View#setY(float)} and {@link View#getY()} methods.
   20848      */
   20849     public static final Property<View, Float> Y = new FloatProperty<View>("y") {
   20850         @Override
   20851         public void setValue(View object, float value) {
   20852             object.setY(value);
   20853         }
   20854 
   20855         @Override
   20856         public Float get(View object) {
   20857             return object.getY();
   20858         }
   20859     };
   20860 
   20861     /**
   20862      * A Property wrapper around the <code>z</code> functionality handled by the
   20863      * {@link View#setZ(float)} and {@link View#getZ()} methods.
   20864      */
   20865     public static final Property<View, Float> Z = new FloatProperty<View>("z") {
   20866         @Override
   20867         public void setValue(View object, float value) {
   20868             object.setZ(value);
   20869         }
   20870 
   20871         @Override
   20872         public Float get(View object) {
   20873             return object.getZ();
   20874         }
   20875     };
   20876 
   20877     /**
   20878      * A Property wrapper around the <code>rotation</code> functionality handled by the
   20879      * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
   20880      */
   20881     public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
   20882         @Override
   20883         public void setValue(View object, float value) {
   20884             object.setRotation(value);
   20885         }
   20886 
   20887         @Override
   20888         public Float get(View object) {
   20889             return object.getRotation();
   20890         }
   20891     };
   20892 
   20893     /**
   20894      * A Property wrapper around the <code>rotationX</code> functionality handled by the
   20895      * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
   20896      */
   20897     public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
   20898         @Override
   20899         public void setValue(View object, float value) {
   20900             object.setRotationX(value);
   20901         }
   20902 
   20903         @Override
   20904         public Float get(View object) {
   20905             return object.getRotationX();
   20906         }
   20907     };
   20908 
   20909     /**
   20910      * A Property wrapper around the <code>rotationY</code> functionality handled by the
   20911      * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
   20912      */
   20913     public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
   20914         @Override
   20915         public void setValue(View object, float value) {
   20916             object.setRotationY(value);
   20917         }
   20918 
   20919         @Override
   20920         public Float get(View object) {
   20921             return object.getRotationY();
   20922         }
   20923     };
   20924 
   20925     /**
   20926      * A Property wrapper around the <code>scaleX</code> functionality handled by the
   20927      * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
   20928      */
   20929     public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
   20930         @Override
   20931         public void setValue(View object, float value) {
   20932             object.setScaleX(value);
   20933         }
   20934 
   20935         @Override
   20936         public Float get(View object) {
   20937             return object.getScaleX();
   20938         }
   20939     };
   20940 
   20941     /**
   20942      * A Property wrapper around the <code>scaleY</code> functionality handled by the
   20943      * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
   20944      */
   20945     public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
   20946         @Override
   20947         public void setValue(View object, float value) {
   20948             object.setScaleY(value);
   20949         }
   20950 
   20951         @Override
   20952         public Float get(View object) {
   20953             return object.getScaleY();
   20954         }
   20955     };
   20956 
   20957     /**
   20958      * A MeasureSpec encapsulates the layout requirements passed from parent to child.
   20959      * Each MeasureSpec represents a requirement for either the width or the height.
   20960      * A MeasureSpec is comprised of a size and a mode. There are three possible
   20961      * modes:
   20962      * <dl>
   20963      * <dt>UNSPECIFIED</dt>
   20964      * <dd>
   20965      * The parent has not imposed any constraint on the child. It can be whatever size
   20966      * it wants.
   20967      * </dd>
   20968      *
   20969      * <dt>EXACTLY</dt>
   20970      * <dd>
   20971      * The parent has determined an exact size for the child. The child is going to be
   20972      * given those bounds regardless of how big it wants to be.
   20973      * </dd>
   20974      *
   20975      * <dt>AT_MOST</dt>
   20976      * <dd>
   20977      * The child can be as large as it wants up to the specified size.
   20978      * </dd>
   20979      * </dl>
   20980      *
   20981      * MeasureSpecs are implemented as ints to reduce object allocation. This class
   20982      * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
   20983      */
   20984     public static class MeasureSpec {
   20985         private static final int MODE_SHIFT = 30;
   20986         private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
   20987 
   20988         /**
   20989          * Measure specification mode: The parent has not imposed any constraint
   20990          * on the child. It can be whatever size it wants.
   20991          */
   20992         public static final int UNSPECIFIED = 0 << MODE_SHIFT;
   20993 
   20994         /**
   20995          * Measure specification mode: The parent has determined an exact size
   20996          * for the child. The child is going to be given those bounds regardless
   20997          * of how big it wants to be.
   20998          */
   20999         public static final int EXACTLY     = 1 << MODE_SHIFT;
   21000 
   21001         /**
   21002          * Measure specification mode: The child can be as large as it wants up
   21003          * to the specified size.
   21004          */
   21005         public static final int AT_MOST     = 2 << MODE_SHIFT;
   21006 
   21007         /**
   21008          * Creates a measure specification based on the supplied size and mode.
   21009          *
   21010          * The mode must always be one of the following:
   21011          * <ul>
   21012          *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
   21013          *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
   21014          *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
   21015          * </ul>
   21016          *
   21017          * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
   21018          * implementation was such that the order of arguments did not matter
   21019          * and overflow in either value could impact the resulting MeasureSpec.
   21020          * {@link android.widget.RelativeLayout} was affected by this bug.
   21021          * Apps targeting API levels greater than 17 will get the fixed, more strict
   21022          * behavior.</p>
   21023          *
   21024          * @param size the size of the measure specification
   21025          * @param mode the mode of the measure specification
   21026          * @return the measure specification based on size and mode
   21027          */
   21028         public static int makeMeasureSpec(int size, int mode) {
   21029             if (sUseBrokenMakeMeasureSpec) {
   21030                 return size + mode;
   21031             } else {
   21032                 return (size & ~MODE_MASK) | (mode & MODE_MASK);
   21033             }
   21034         }
   21035 
   21036         /**
   21037          * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
   21038          * will automatically get a size of 0. Older apps expect this.
   21039          *
   21040          * @hide internal use only for compatibility with system widgets and older apps
   21041          */
   21042         public static int makeSafeMeasureSpec(int size, int mode) {
   21043             if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
   21044                 return 0;
   21045             }
   21046             return makeMeasureSpec(size, mode);
   21047         }
   21048 
   21049         /**
   21050          * Extracts the mode from the supplied measure specification.
   21051          *
   21052          * @param measureSpec the measure specification to extract the mode from
   21053          * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
   21054          *         {@link android.view.View.MeasureSpec#AT_MOST} or
   21055          *         {@link android.view.View.MeasureSpec#EXACTLY}
   21056          */
   21057         public static int getMode(int measureSpec) {
   21058             return (measureSpec & MODE_MASK);
   21059         }
   21060 
   21061         /**
   21062          * Extracts the size from the supplied measure specification.
   21063          *
   21064          * @param measureSpec the measure specification to extract the size from
   21065          * @return the size in pixels defined in the supplied measure specification
   21066          */
   21067         public static int getSize(int measureSpec) {
   21068             return (measureSpec & ~MODE_MASK);
   21069         }
   21070 
   21071         static int adjust(int measureSpec, int delta) {
   21072             final int mode = getMode(measureSpec);
   21073             int size = getSize(measureSpec);
   21074             if (mode == UNSPECIFIED) {
   21075                 // No need to adjust size for UNSPECIFIED mode.
   21076                 return makeMeasureSpec(size, UNSPECIFIED);
   21077             }
   21078             size += delta;
   21079             if (size < 0) {
   21080                 Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
   21081                         ") spec: " + toString(measureSpec) + " delta: " + delta);
   21082                 size = 0;
   21083             }
   21084             return makeMeasureSpec(size, mode);
   21085         }
   21086 
   21087         /**
   21088          * Returns a String representation of the specified measure
   21089          * specification.
   21090          *
   21091          * @param measureSpec the measure specification to convert to a String
   21092          * @return a String with the following format: "MeasureSpec: MODE SIZE"
   21093          */
   21094         public static String toString(int measureSpec) {
   21095             int mode = getMode(measureSpec);
   21096             int size = getSize(measureSpec);
   21097 
   21098             StringBuilder sb = new StringBuilder("MeasureSpec: ");
   21099 
   21100             if (mode == UNSPECIFIED)
   21101                 sb.append("UNSPECIFIED ");
   21102             else if (mode == EXACTLY)
   21103                 sb.append("EXACTLY ");
   21104             else if (mode == AT_MOST)
   21105                 sb.append("AT_MOST ");
   21106             else
   21107                 sb.append(mode).append(" ");
   21108 
   21109             sb.append(size);
   21110             return sb.toString();
   21111         }
   21112     }
   21113 
   21114     private final class CheckForLongPress implements Runnable {
   21115         private int mOriginalWindowAttachCount;
   21116 
   21117         @Override
   21118         public void run() {
   21119             if (isPressed() && (mParent != null)
   21120                     && mOriginalWindowAttachCount == mWindowAttachCount) {
   21121                 if (performLongClick()) {
   21122                     mHasPerformedLongPress = true;
   21123                 }
   21124             }
   21125         }
   21126 
   21127         public void rememberWindowAttachCount() {
   21128             mOriginalWindowAttachCount = mWindowAttachCount;
   21129         }
   21130     }
   21131 
   21132     private final class CheckForTap implements Runnable {
   21133         public float x;
   21134         public float y;
   21135 
   21136         @Override
   21137         public void run() {
   21138             mPrivateFlags &= ~PFLAG_PREPRESSED;
   21139             setPressed(true, x, y);
   21140             checkForLongClick(ViewConfiguration.getTapTimeout());
   21141         }
   21142     }
   21143 
   21144     private final class PerformClick implements Runnable {
   21145         @Override
   21146         public void run() {
   21147             performClick();
   21148         }
   21149     }
   21150 
   21151     /** @hide */
   21152     public void hackTurnOffWindowResizeAnim(boolean off) {
   21153         mAttachInfo.mTurnOffWindowResizeAnim = off;
   21154     }
   21155 
   21156     /**
   21157      * This method returns a ViewPropertyAnimator object, which can be used to animate
   21158      * specific properties on this View.
   21159      *
   21160      * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
   21161      */
   21162     public ViewPropertyAnimator animate() {
   21163         if (mAnimator == null) {
   21164             mAnimator = new ViewPropertyAnimator(this);
   21165         }
   21166         return mAnimator;
   21167     }
   21168 
   21169     /**
   21170      * Sets the name of the View to be used to identify Views in Transitions.
   21171      * Names should be unique in the View hierarchy.
   21172      *
   21173      * @param transitionName The name of the View to uniquely identify it for Transitions.
   21174      */
   21175     public final void setTransitionName(String transitionName) {
   21176         mTransitionName = transitionName;
   21177     }
   21178 
   21179     /**
   21180      * Returns the name of the View to be used to identify Views in Transitions.
   21181      * Names should be unique in the View hierarchy.
   21182      *
   21183      * <p>This returns null if the View has not been given a name.</p>
   21184      *
   21185      * @return The name used of the View to be used to identify Views in Transitions or null
   21186      * if no name has been given.
   21187      */
   21188     @ViewDebug.ExportedProperty
   21189     public String getTransitionName() {
   21190         return mTransitionName;
   21191     }
   21192 
   21193     /**
   21194      * Interface definition for a callback to be invoked when a hardware key event is
   21195      * dispatched to this view. The callback will be invoked before the key event is
   21196      * given to the view. This is only useful for hardware keyboards; a software input
   21197      * method has no obligation to trigger this listener.
   21198      */
   21199     public interface OnKeyListener {
   21200         /**
   21201          * Called when a hardware key is dispatched to a view. This allows listeners to
   21202          * get a chance to respond before the target view.
   21203          * <p>Key presses in software keyboards will generally NOT trigger this method,
   21204          * although some may elect to do so in some situations. Do not assume a
   21205          * software input method has to be key-based; even if it is, it may use key presses
   21206          * in a different way than you expect, so there is no way to reliably catch soft
   21207          * input key presses.
   21208          *
   21209          * @param v The view the key has been dispatched to.
   21210          * @param keyCode The code for the physical key that was pressed
   21211          * @param event The KeyEvent object containing full information about
   21212          *        the event.
   21213          * @return True if the listener has consumed the event, false otherwise.
   21214          */
   21215         boolean onKey(View v, int keyCode, KeyEvent event);
   21216     }
   21217 
   21218     /**
   21219      * Interface definition for a callback to be invoked when a touch event is
   21220      * dispatched to this view. The callback will be invoked before the touch
   21221      * event is given to the view.
   21222      */
   21223     public interface OnTouchListener {
   21224         /**
   21225          * Called when a touch event is dispatched to a view. This allows listeners to
   21226          * get a chance to respond before the target view.
   21227          *
   21228          * @param v The view the touch event has been dispatched to.
   21229          * @param event The MotionEvent object containing full information about
   21230          *        the event.
   21231          * @return True if the listener has consumed the event, false otherwise.
   21232          */
   21233         boolean onTouch(View v, MotionEvent event);
   21234     }
   21235 
   21236     /**
   21237      * Interface definition for a callback to be invoked when a hover event is
   21238      * dispatched to this view. The callback will be invoked before the hover
   21239      * event is given to the view.
   21240      */
   21241     public interface OnHoverListener {
   21242         /**
   21243          * Called when a hover event is dispatched to a view. This allows listeners to
   21244          * get a chance to respond before the target view.
   21245          *
   21246          * @param v The view the hover event has been dispatched to.
   21247          * @param event The MotionEvent object containing full information about
   21248          *        the event.
   21249          * @return True if the listener has consumed the event, false otherwise.
   21250          */
   21251         boolean onHover(View v, MotionEvent event);
   21252     }
   21253 
   21254     /**
   21255      * Interface definition for a callback to be invoked when a generic motion event is
   21256      * dispatched to this view. The callback will be invoked before the generic motion
   21257      * event is given to the view.
   21258      */
   21259     public interface OnGenericMotionListener {
   21260         /**
   21261          * Called when a generic motion event is dispatched to a view. This allows listeners to
   21262          * get a chance to respond before the target view.
   21263          *
   21264          * @param v The view the generic motion event has been dispatched to.
   21265          * @param event The MotionEvent object containing full information about
   21266          *        the event.
   21267          * @return True if the listener has consumed the event, false otherwise.
   21268          */
   21269         boolean onGenericMotion(View v, MotionEvent event);
   21270     }
   21271 
   21272     /**
   21273      * Interface definition for a callback to be invoked when a view has been clicked and held.
   21274      */
   21275     public interface OnLongClickListener {
   21276         /**
   21277          * Called when a view has been clicked and held.
   21278          *
   21279          * @param v The view that was clicked and held.
   21280          *
   21281          * @return true if the callback consumed the long click, false otherwise.
   21282          */
   21283         boolean onLongClick(View v);
   21284     }
   21285 
   21286     /**
   21287      * Interface definition for a callback to be invoked when a drag is being dispatched
   21288      * to this view.  The callback will be invoked before the hosting view's own
   21289      * onDrag(event) method.  If the listener wants to fall back to the hosting view's
   21290      * onDrag(event) behavior, it should return 'false' from this callback.
   21291      *
   21292      * <div class="special reference">
   21293      * <h3>Developer Guides</h3>
   21294      * <p>For a guide to implementing drag and drop features, read the
   21295      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
   21296      * </div>
   21297      */
   21298     public interface OnDragListener {
   21299         /**
   21300          * Called when a drag event is dispatched to a view. This allows listeners
   21301          * to get a chance to override base View behavior.
   21302          *
   21303          * @param v The View that received the drag event.
   21304          * @param event The {@link android.view.DragEvent} object for the drag event.
   21305          * @return {@code true} if the drag event was handled successfully, or {@code false}
   21306          * if the drag event was not handled. Note that {@code false} will trigger the View
   21307          * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
   21308          */
   21309         boolean onDrag(View v, DragEvent event);
   21310     }
   21311 
   21312     /**
   21313      * Interface definition for a callback to be invoked when the focus state of
   21314      * a view changed.
   21315      */
   21316     public interface OnFocusChangeListener {
   21317         /**
   21318          * Called when the focus state of a view has changed.
   21319          *
   21320          * @param v The view whose state has changed.
   21321          * @param hasFocus The new focus state of v.
   21322          */
   21323         void onFocusChange(View v, boolean hasFocus);
   21324     }
   21325 
   21326     /**
   21327      * Interface definition for a callback to be invoked when a view is clicked.
   21328      */
   21329     public interface OnClickListener {
   21330         /**
   21331          * Called when a view has been clicked.
   21332          *
   21333          * @param v The view that was clicked.
   21334          */
   21335         void onClick(View v);
   21336     }
   21337 
   21338     /**
   21339      * Interface definition for a callback to be invoked when a view is context clicked.
   21340      */
   21341     public interface OnContextClickListener {
   21342         /**
   21343          * Called when a view is context clicked.
   21344          *
   21345          * @param v The view that has been context clicked.
   21346          * @return true if the callback consumed the context click, false otherwise.
   21347          */
   21348         boolean onContextClick(View v);
   21349     }
   21350 
   21351     /**
   21352      * Interface definition for a callback to be invoked when the context menu
   21353      * for this view is being built.
   21354      */
   21355     public interface OnCreateContextMenuListener {
   21356         /**
   21357          * Called when the context menu for this view is being built. It is not
   21358          * safe to hold onto the menu after this method returns.
   21359          *
   21360          * @param menu The context menu that is being built
   21361          * @param v The view for which the context menu is being built
   21362          * @param menuInfo Extra information about the item for which the
   21363          *            context menu should be shown. This information will vary
   21364          *            depending on the class of v.
   21365          */
   21366         void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
   21367     }
   21368 
   21369     /**
   21370      * Interface definition for a callback to be invoked when the status bar changes
   21371      * visibility.  This reports <strong>global</strong> changes to the system UI
   21372      * state, not what the application is requesting.
   21373      *
   21374      * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
   21375      */
   21376     public interface OnSystemUiVisibilityChangeListener {
   21377         /**
   21378          * Called when the status bar changes visibility because of a call to
   21379          * {@link View#setSystemUiVisibility(int)}.
   21380          *
   21381          * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
   21382          * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
   21383          * This tells you the <strong>global</strong> state of these UI visibility
   21384          * flags, not what your app is currently applying.
   21385          */
   21386         public void onSystemUiVisibilityChange(int visibility);
   21387     }
   21388 
   21389     /**
   21390      * Interface definition for a callback to be invoked when this view is attached
   21391      * or detached from its window.
   21392      */
   21393     public interface OnAttachStateChangeListener {
   21394         /**
   21395          * Called when the view is attached to a window.
   21396          * @param v The view that was attached
   21397          */
   21398         public void onViewAttachedToWindow(View v);
   21399         /**
   21400          * Called when the view is detached from a window.
   21401          * @param v The view that was detached
   21402          */
   21403         public void onViewDetachedFromWindow(View v);
   21404     }
   21405 
   21406     /**
   21407      * Listener for applying window insets on a view in a custom way.
   21408      *
   21409      * <p>Apps may choose to implement this interface if they want to apply custom policy
   21410      * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
   21411      * is set, its
   21412      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
   21413      * method will be called instead of the View's own
   21414      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
   21415      * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
   21416      * the View's normal behavior as part of its own.</p>
   21417      */
   21418     public interface OnApplyWindowInsetsListener {
   21419         /**
   21420          * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
   21421          * on a View, this listener method will be called instead of the view's own
   21422          * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
   21423          *
   21424          * @param v The view applying window insets
   21425          * @param insets The insets to apply
   21426          * @return The insets supplied, minus any insets that were consumed
   21427          */
   21428         public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
   21429     }
   21430 
   21431     private final class UnsetPressedState implements Runnable {
   21432         @Override
   21433         public void run() {
   21434             setPressed(false);
   21435         }
   21436     }
   21437 
   21438     /**
   21439      * Base class for derived classes that want to save and restore their own
   21440      * state in {@link android.view.View#onSaveInstanceState()}.
   21441      */
   21442     public static class BaseSavedState extends AbsSavedState {
   21443         String mStartActivityRequestWhoSaved;
   21444 
   21445         /**
   21446          * Constructor used when reading from a parcel. Reads the state of the superclass.
   21447          *
   21448          * @param source
   21449          */
   21450         public BaseSavedState(Parcel source) {
   21451             super(source);
   21452             mStartActivityRequestWhoSaved = source.readString();
   21453         }
   21454 
   21455         /**
   21456          * Constructor called by derived classes when creating their SavedState objects
   21457          *
   21458          * @param superState The state of the superclass of this view
   21459          */
   21460         public BaseSavedState(Parcelable superState) {
   21461             super(superState);
   21462         }
   21463 
   21464         @Override
   21465         public void writeToParcel(Parcel out, int flags) {
   21466             super.writeToParcel(out, flags);
   21467             out.writeString(mStartActivityRequestWhoSaved);
   21468         }
   21469 
   21470         public static final Parcelable.Creator<BaseSavedState> CREATOR =
   21471                 new Parcelable.Creator<BaseSavedState>() {
   21472             public BaseSavedState createFromParcel(Parcel in) {
   21473                 return new BaseSavedState(in);
   21474             }
   21475 
   21476             public BaseSavedState[] newArray(int size) {
   21477                 return new BaseSavedState[size];
   21478             }
   21479         };
   21480     }
   21481 
   21482     /**
   21483      * A set of information given to a view when it is attached to its parent
   21484      * window.
   21485      */
   21486     final static class AttachInfo {
   21487         interface Callbacks {
   21488             void playSoundEffect(int effectId);
   21489             boolean performHapticFeedback(int effectId, boolean always);
   21490         }
   21491 
   21492         /**
   21493          * InvalidateInfo is used to post invalidate(int, int, int, int) messages
   21494          * to a Handler. This class contains the target (View) to invalidate and
   21495          * the coordinates of the dirty rectangle.
   21496          *
   21497          * For performance purposes, this class also implements a pool of up to
   21498          * POOL_LIMIT objects that get reused. This reduces memory allocations
   21499          * whenever possible.
   21500          */
   21501         static class InvalidateInfo {
   21502             private static final int POOL_LIMIT = 10;
   21503 
   21504             private static final SynchronizedPool<InvalidateInfo> sPool =
   21505                     new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
   21506 
   21507             View target;
   21508 
   21509             int left;
   21510             int top;
   21511             int right;
   21512             int bottom;
   21513 
   21514             public static InvalidateInfo obtain() {
   21515                 InvalidateInfo instance = sPool.acquire();
   21516                 return (instance != null) ? instance : new InvalidateInfo();
   21517             }
   21518 
   21519             public void recycle() {
   21520                 target = null;
   21521                 sPool.release(this);
   21522             }
   21523         }
   21524 
   21525         final IWindowSession mSession;
   21526 
   21527         final IWindow mWindow;
   21528 
   21529         final IBinder mWindowToken;
   21530 
   21531         final Display mDisplay;
   21532 
   21533         final Callbacks mRootCallbacks;
   21534 
   21535         IWindowId mIWindowId;
   21536         WindowId mWindowId;
   21537 
   21538         /**
   21539          * The top view of the hierarchy.
   21540          */
   21541         View mRootView;
   21542 
   21543         IBinder mPanelParentWindowToken;
   21544 
   21545         boolean mHardwareAccelerated;
   21546         boolean mHardwareAccelerationRequested;
   21547         HardwareRenderer mHardwareRenderer;
   21548         List<RenderNode> mPendingAnimatingRenderNodes;
   21549 
   21550         /**
   21551          * The state of the display to which the window is attached, as reported
   21552          * by {@link Display#getState()}.  Note that the display state constants
   21553          * declared by {@link Display} do not exactly line up with the screen state
   21554          * constants declared by {@link View} (there are more display states than
   21555          * screen states).
   21556          */
   21557         int mDisplayState = Display.STATE_UNKNOWN;
   21558 
   21559         /**
   21560          * Scale factor used by the compatibility mode
   21561          */
   21562         float mApplicationScale;
   21563 
   21564         /**
   21565          * Indicates whether the application is in compatibility mode
   21566          */
   21567         boolean mScalingRequired;
   21568 
   21569         /**
   21570          * If set, ViewRootImpl doesn't use its lame animation for when the window resizes.
   21571          */
   21572         boolean mTurnOffWindowResizeAnim;
   21573 
   21574         /**
   21575          * Left position of this view's window
   21576          */
   21577         int mWindowLeft;
   21578 
   21579         /**
   21580          * Top position of this view's window
   21581          */
   21582         int mWindowTop;
   21583 
   21584         /**
   21585          * Indicates whether views need to use 32-bit drawing caches
   21586          */
   21587         boolean mUse32BitDrawingCache;
   21588 
   21589         /**
   21590          * For windows that are full-screen but using insets to layout inside
   21591          * of the screen areas, these are the current insets to appear inside
   21592          * the overscan area of the display.
   21593          */
   21594         final Rect mOverscanInsets = new Rect();
   21595 
   21596         /**
   21597          * For windows that are full-screen but using insets to layout inside
   21598          * of the screen decorations, these are the current insets for the
   21599          * content of the window.
   21600          */
   21601         final Rect mContentInsets = new Rect();
   21602 
   21603         /**
   21604          * For windows that are full-screen but using insets to layout inside
   21605          * of the screen decorations, these are the current insets for the
   21606          * actual visible parts of the window.
   21607          */
   21608         final Rect mVisibleInsets = new Rect();
   21609 
   21610         /**
   21611          * For windows that are full-screen but using insets to layout inside
   21612          * of the screen decorations, these are the current insets for the
   21613          * stable system windows.
   21614          */
   21615         final Rect mStableInsets = new Rect();
   21616 
   21617         /**
   21618          * For windows that include areas that are not covered by real surface these are the outsets
   21619          * for real surface.
   21620          */
   21621         final Rect mOutsets = new Rect();
   21622 
   21623         /**
   21624          * The internal insets given by this window.  This value is
   21625          * supplied by the client (through
   21626          * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
   21627          * be given to the window manager when changed to be used in laying
   21628          * out windows behind it.
   21629          */
   21630         final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
   21631                 = new ViewTreeObserver.InternalInsetsInfo();
   21632 
   21633         /**
   21634          * Set to true when mGivenInternalInsets is non-empty.
   21635          */
   21636         boolean mHasNonEmptyGivenInternalInsets;
   21637 
   21638         /**
   21639          * All views in the window's hierarchy that serve as scroll containers,
   21640          * used to determine if the window can be resized or must be panned
   21641          * to adjust for a soft input area.
   21642          */
   21643         final ArrayList<View> mScrollContainers = new ArrayList<View>();
   21644 
   21645         final KeyEvent.DispatcherState mKeyDispatchState
   21646                 = new KeyEvent.DispatcherState();
   21647 
   21648         /**
   21649          * Indicates whether the view's window currently has the focus.
   21650          */
   21651         boolean mHasWindowFocus;
   21652 
   21653         /**
   21654          * The current visibility of the window.
   21655          */
   21656         int mWindowVisibility;
   21657 
   21658         /**
   21659          * Indicates the time at which drawing started to occur.
   21660          */
   21661         long mDrawingTime;
   21662 
   21663         /**
   21664          * Indicates whether or not ignoring the DIRTY_MASK flags.
   21665          */
   21666         boolean mIgnoreDirtyState;
   21667 
   21668         /**
   21669          * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
   21670          * to avoid clearing that flag prematurely.
   21671          */
   21672         boolean mSetIgnoreDirtyState = false;
   21673 
   21674         /**
   21675          * Indicates whether the view's window is currently in touch mode.
   21676          */
   21677         boolean mInTouchMode;
   21678 
   21679         /**
   21680          * Indicates whether the view has requested unbuffered input dispatching for the current
   21681          * event stream.
   21682          */
   21683         boolean mUnbufferedDispatchRequested;
   21684 
   21685         /**
   21686          * Indicates that ViewAncestor should trigger a global layout change
   21687          * the next time it performs a traversal
   21688          */
   21689         boolean mRecomputeGlobalAttributes;
   21690 
   21691         /**
   21692          * Always report new attributes at next traversal.
   21693          */
   21694         boolean mForceReportNewAttributes;
   21695 
   21696         /**
   21697          * Set during a traveral if any views want to keep the screen on.
   21698          */
   21699         boolean mKeepScreenOn;
   21700 
   21701         /**
   21702          * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
   21703          */
   21704         int mSystemUiVisibility;
   21705 
   21706         /**
   21707          * Hack to force certain system UI visibility flags to be cleared.
   21708          */
   21709         int mDisabledSystemUiVisibility;
   21710 
   21711         /**
   21712          * Last global system UI visibility reported by the window manager.
   21713          */
   21714         int mGlobalSystemUiVisibility;
   21715 
   21716         /**
   21717          * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
   21718          * attached.
   21719          */
   21720         boolean mHasSystemUiListeners;
   21721 
   21722         /**
   21723          * Set if the window has requested to extend into the overscan region
   21724          * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
   21725          */
   21726         boolean mOverscanRequested;
   21727 
   21728         /**
   21729          * Set if the visibility of any views has changed.
   21730          */
   21731         boolean mViewVisibilityChanged;
   21732 
   21733         /**
   21734          * Set to true if a view has been scrolled.
   21735          */
   21736         boolean mViewScrollChanged;
   21737 
   21738         /**
   21739          * Set to true if high contrast mode enabled
   21740          */
   21741         boolean mHighContrastText;
   21742 
   21743         /**
   21744          * Global to the view hierarchy used as a temporary for dealing with
   21745          * x/y points in the transparent region computations.
   21746          */
   21747         final int[] mTransparentLocation = new int[2];
   21748 
   21749         /**
   21750          * Global to the view hierarchy used as a temporary for dealing with
   21751          * x/y points in the ViewGroup.invalidateChild implementation.
   21752          */
   21753         final int[] mInvalidateChildLocation = new int[2];
   21754 
   21755         /**
   21756          * Global to the view hierarchy used as a temporary for dealng with
   21757          * computing absolute on-screen location.
   21758          */
   21759         final int[] mTmpLocation = new int[2];
   21760 
   21761         /**
   21762          * Global to the view hierarchy used as a temporary for dealing with
   21763          * x/y location when view is transformed.
   21764          */
   21765         final float[] mTmpTransformLocation = new float[2];
   21766 
   21767         /**
   21768          * The view tree observer used to dispatch global events like
   21769          * layout, pre-draw, touch mode change, etc.
   21770          */
   21771         final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
   21772 
   21773         /**
   21774          * A Canvas used by the view hierarchy to perform bitmap caching.
   21775          */
   21776         Canvas mCanvas;
   21777 
   21778         /**
   21779          * The view root impl.
   21780          */
   21781         final ViewRootImpl mViewRootImpl;
   21782 
   21783         /**
   21784          * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
   21785          * handler can be used to pump events in the UI events queue.
   21786          */
   21787         final Handler mHandler;
   21788 
   21789         /**
   21790          * Temporary for use in computing invalidate rectangles while
   21791          * calling up the hierarchy.
   21792          */
   21793         final Rect mTmpInvalRect = new Rect();
   21794 
   21795         /**
   21796          * Temporary for use in computing hit areas with transformed views
   21797          */
   21798         final RectF mTmpTransformRect = new RectF();
   21799 
   21800         /**
   21801          * Temporary for use in computing hit areas with transformed views
   21802          */
   21803         final RectF mTmpTransformRect1 = new RectF();
   21804 
   21805         /**
   21806          * Temporary list of rectanges.
   21807          */
   21808         final List<RectF> mTmpRectList = new ArrayList<>();
   21809 
   21810         /**
   21811          * Temporary for use in transforming invalidation rect
   21812          */
   21813         final Matrix mTmpMatrix = new Matrix();
   21814 
   21815         /**
   21816          * Temporary for use in transforming invalidation rect
   21817          */
   21818         final Transformation mTmpTransformation = new Transformation();
   21819 
   21820         /**
   21821          * Temporary for use in querying outlines from OutlineProviders
   21822          */
   21823         final Outline mTmpOutline = new Outline();
   21824 
   21825         /**
   21826          * Temporary list for use in collecting focusable descendents of a view.
   21827          */
   21828         final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
   21829 
   21830         /**
   21831          * The id of the window for accessibility purposes.
   21832          */
   21833         int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
   21834 
   21835         /**
   21836          * Flags related to accessibility processing.
   21837          *
   21838          * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
   21839          * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
   21840          */
   21841         int mAccessibilityFetchFlags;
   21842 
   21843         /**
   21844          * The drawable for highlighting accessibility focus.
   21845          */
   21846         Drawable mAccessibilityFocusDrawable;
   21847 
   21848         /**
   21849          * Show where the margins, bounds and layout bounds are for each view.
   21850          */
   21851         boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
   21852 
   21853         /**
   21854          * Point used to compute visible regions.
   21855          */
   21856         final Point mPoint = new Point();
   21857 
   21858         /**
   21859          * Used to track which View originated a requestLayout() call, used when
   21860          * requestLayout() is called during layout.
   21861          */
   21862         View mViewRequestingLayout;
   21863 
   21864         /**
   21865          * Creates a new set of attachment information with the specified
   21866          * events handler and thread.
   21867          *
   21868          * @param handler the events handler the view must use
   21869          */
   21870         AttachInfo(IWindowSession session, IWindow window, Display display,
   21871                 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
   21872             mSession = session;
   21873             mWindow = window;
   21874             mWindowToken = window.asBinder();
   21875             mDisplay = display;
   21876             mViewRootImpl = viewRootImpl;
   21877             mHandler = handler;
   21878             mRootCallbacks = effectPlayer;
   21879         }
   21880     }
   21881 
   21882     /**
   21883      * <p>ScrollabilityCache holds various fields used by a View when scrolling
   21884      * is supported. This avoids keeping too many unused fields in most
   21885      * instances of View.</p>
   21886      */
   21887     private static class ScrollabilityCache implements Runnable {
   21888 
   21889         /**
   21890          * Scrollbars are not visible
   21891          */
   21892         public static final int OFF = 0;
   21893 
   21894         /**
   21895          * Scrollbars are visible
   21896          */
   21897         public static final int ON = 1;
   21898 
   21899         /**
   21900          * Scrollbars are fading away
   21901          */
   21902         public static final int FADING = 2;
   21903 
   21904         public boolean fadeScrollBars;
   21905 
   21906         public int fadingEdgeLength;
   21907         public int scrollBarDefaultDelayBeforeFade;
   21908         public int scrollBarFadeDuration;
   21909 
   21910         public int scrollBarSize;
   21911         public ScrollBarDrawable scrollBar;
   21912         public float[] interpolatorValues;
   21913         public View host;
   21914 
   21915         public final Paint paint;
   21916         public final Matrix matrix;
   21917         public Shader shader;
   21918 
   21919         public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
   21920 
   21921         private static final float[] OPAQUE = { 255 };
   21922         private static final float[] TRANSPARENT = { 0.0f };
   21923 
   21924         /**
   21925          * When fading should start. This time moves into the future every time
   21926          * a new scroll happens. Measured based on SystemClock.uptimeMillis()
   21927          */
   21928         public long fadeStartTime;
   21929 
   21930 
   21931         /**
   21932          * The current state of the scrollbars: ON, OFF, or FADING
   21933          */
   21934         public int state = OFF;
   21935 
   21936         private int mLastColor;
   21937 
   21938         public ScrollabilityCache(ViewConfiguration configuration, View host) {
   21939             fadingEdgeLength = configuration.getScaledFadingEdgeLength();
   21940             scrollBarSize = configuration.getScaledScrollBarSize();
   21941             scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
   21942             scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
   21943 
   21944             paint = new Paint();
   21945             matrix = new Matrix();
   21946             // use use a height of 1, and then wack the matrix each time we
   21947             // actually use it.
   21948             shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
   21949             paint.setShader(shader);
   21950             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
   21951 
   21952             this.host = host;
   21953         }
   21954 
   21955         public void setFadeColor(int color) {
   21956             if (color != mLastColor) {
   21957                 mLastColor = color;
   21958 
   21959                 if (color != 0) {
   21960                     shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
   21961                             color & 0x00FFFFFF, Shader.TileMode.CLAMP);
   21962                     paint.setShader(shader);
   21963                     // Restore the default transfer mode (src_over)
   21964                     paint.setXfermode(null);
   21965                 } else {
   21966                     shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
   21967                     paint.setShader(shader);
   21968                     paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
   21969                 }
   21970             }
   21971         }
   21972 
   21973         public void run() {
   21974             long now = AnimationUtils.currentAnimationTimeMillis();
   21975             if (now >= fadeStartTime) {
   21976 
   21977                 // the animation fades the scrollbars out by changing
   21978                 // the opacity (alpha) from fully opaque to fully
   21979                 // transparent
   21980                 int nextFrame = (int) now;
   21981                 int framesCount = 0;
   21982 
   21983                 Interpolator interpolator = scrollBarInterpolator;
   21984 
   21985                 // Start opaque
   21986                 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
   21987 
   21988                 // End transparent
   21989                 nextFrame += scrollBarFadeDuration;
   21990                 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
   21991 
   21992                 state = FADING;
   21993 
   21994                 // Kick off the fade animation
   21995                 host.invalidate(true);
   21996             }
   21997         }
   21998     }
   21999 
   22000     /**
   22001      * Resuable callback for sending
   22002      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
   22003      */
   22004     private class SendViewScrolledAccessibilityEvent implements Runnable {
   22005         public volatile boolean mIsPending;
   22006 
   22007         public void run() {
   22008             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
   22009             mIsPending = false;
   22010         }
   22011     }
   22012 
   22013     /**
   22014      * <p>
   22015      * This class represents a delegate that can be registered in a {@link View}
   22016      * to enhance accessibility support via composition rather via inheritance.
   22017      * It is specifically targeted to widget developers that extend basic View
   22018      * classes i.e. classes in package android.view, that would like their
   22019      * applications to be backwards compatible.
   22020      * </p>
   22021      * <div class="special reference">
   22022      * <h3>Developer Guides</h3>
   22023      * <p>For more information about making applications accessible, read the
   22024      * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
   22025      * developer guide.</p>
   22026      * </div>
   22027      * <p>
   22028      * A scenario in which a developer would like to use an accessibility delegate
   22029      * is overriding a method introduced in a later API version then the minimal API
   22030      * version supported by the application. For example, the method
   22031      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
   22032      * in API version 4 when the accessibility APIs were first introduced. If a
   22033      * developer would like his application to run on API version 4 devices (assuming
   22034      * all other APIs used by the application are version 4 or lower) and take advantage
   22035      * of this method, instead of overriding the method which would break the application's
   22036      * backwards compatibility, he can override the corresponding method in this
   22037      * delegate and register the delegate in the target View if the API version of
   22038      * the system is high enough i.e. the API version is same or higher to the API
   22039      * version that introduced
   22040      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
   22041      * </p>
   22042      * <p>
   22043      * Here is an example implementation:
   22044      * </p>
   22045      * <code><pre><p>
   22046      * if (Build.VERSION.SDK_INT >= 14) {
   22047      *     // If the API version is equal of higher than the version in
   22048      *     // which onInitializeAccessibilityNodeInfo was introduced we
   22049      *     // register a delegate with a customized implementation.
   22050      *     View view = findViewById(R.id.view_id);
   22051      *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
   22052      *         public void onInitializeAccessibilityNodeInfo(View host,
   22053      *                 AccessibilityNodeInfo info) {
   22054      *             // Let the default implementation populate the info.
   22055      *             super.onInitializeAccessibilityNodeInfo(host, info);
   22056      *             // Set some other information.
   22057      *             info.setEnabled(host.isEnabled());
   22058      *         }
   22059      *     });
   22060      * }
   22061      * </code></pre></p>
   22062      * <p>
   22063      * This delegate contains methods that correspond to the accessibility methods
   22064      * in View. If a delegate has been specified the implementation in View hands
   22065      * off handling to the corresponding method in this delegate. The default
   22066      * implementation the delegate methods behaves exactly as the corresponding
   22067      * method in View for the case of no accessibility delegate been set. Hence,
   22068      * to customize the behavior of a View method, clients can override only the
   22069      * corresponding delegate method without altering the behavior of the rest
   22070      * accessibility related methods of the host view.
   22071      * </p>
   22072      */
   22073     public static class AccessibilityDelegate {
   22074 
   22075         /**
   22076          * Sends an accessibility event of the given type. If accessibility is not
   22077          * enabled this method has no effect.
   22078          * <p>
   22079          * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
   22080          *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
   22081          * been set.
   22082          * </p>
   22083          *
   22084          * @param host The View hosting the delegate.
   22085          * @param eventType The type of the event to send.
   22086          *
   22087          * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
   22088          */
   22089         public void sendAccessibilityEvent(View host, int eventType) {
   22090             host.sendAccessibilityEventInternal(eventType);
   22091         }
   22092 
   22093         /**
   22094          * Performs the specified accessibility action on the view. For
   22095          * possible accessibility actions look at {@link AccessibilityNodeInfo}.
   22096          * <p>
   22097          * The default implementation behaves as
   22098          * {@link View#performAccessibilityAction(int, Bundle)
   22099          *  View#performAccessibilityAction(int, Bundle)} for the case of
   22100          *  no accessibility delegate been set.
   22101          * </p>
   22102          *
   22103          * @param action The action to perform.
   22104          * @return Whether the action was performed.
   22105          *
   22106          * @see View#performAccessibilityAction(int, Bundle)
   22107          *      View#performAccessibilityAction(int, Bundle)
   22108          */
   22109         public boolean performAccessibilityAction(View host, int action, Bundle args) {
   22110             return host.performAccessibilityActionInternal(action, args);
   22111         }
   22112 
   22113         /**
   22114          * Sends an accessibility event. This method behaves exactly as
   22115          * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
   22116          * empty {@link AccessibilityEvent} and does not perform a check whether
   22117          * accessibility is enabled.
   22118          * <p>
   22119          * The default implementation behaves as
   22120          * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
   22121          *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
   22122          * the case of no accessibility delegate been set.
   22123          * </p>
   22124          *
   22125          * @param host The View hosting the delegate.
   22126          * @param event The event to send.
   22127          *
   22128          * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
   22129          *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
   22130          */
   22131         public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
   22132             host.sendAccessibilityEventUncheckedInternal(event);
   22133         }
   22134 
   22135         /**
   22136          * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
   22137          * to its children for adding their text content to the event.
   22138          * <p>
   22139          * The default implementation behaves as
   22140          * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   22141          *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
   22142          * the case of no accessibility delegate been set.
   22143          * </p>
   22144          *
   22145          * @param host The View hosting the delegate.
   22146          * @param event The event.
   22147          * @return True if the event population was completed.
   22148          *
   22149          * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   22150          *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
   22151          */
   22152         public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
   22153             return host.dispatchPopulateAccessibilityEventInternal(event);
   22154         }
   22155 
   22156         /**
   22157          * Gives a chance to the host View to populate the accessibility event with its
   22158          * text content.
   22159          * <p>
   22160          * The default implementation behaves as
   22161          * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
   22162          *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
   22163          * the case of no accessibility delegate been set.
   22164          * </p>
   22165          *
   22166          * @param host The View hosting the delegate.
   22167          * @param event The accessibility event which to populate.
   22168          *
   22169          * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
   22170          *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
   22171          */
   22172         public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
   22173             host.onPopulateAccessibilityEventInternal(event);
   22174         }
   22175 
   22176         /**
   22177          * Initializes an {@link AccessibilityEvent} with information about the
   22178          * the host View which is the event source.
   22179          * <p>
   22180          * The default implementation behaves as
   22181          * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
   22182          *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
   22183          * the case of no accessibility delegate been set.
   22184          * </p>
   22185          *
   22186          * @param host The View hosting the delegate.
   22187          * @param event The event to initialize.
   22188          *
   22189          * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
   22190          *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
   22191          */
   22192         public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
   22193             host.onInitializeAccessibilityEventInternal(event);
   22194         }
   22195 
   22196         /**
   22197          * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
   22198          * <p>
   22199          * The default implementation behaves as
   22200          * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
   22201          *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
   22202          * the case of no accessibility delegate been set.
   22203          * </p>
   22204          *
   22205          * @param host The View hosting the delegate.
   22206          * @param info The instance to initialize.
   22207          *
   22208          * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
   22209          *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
   22210          */
   22211         public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
   22212             host.onInitializeAccessibilityNodeInfoInternal(info);
   22213         }
   22214 
   22215         /**
   22216          * Called when a child of the host View has requested sending an
   22217          * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
   22218          * to augment the event.
   22219          * <p>
   22220          * The default implementation behaves as
   22221          * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
   22222          *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
   22223          * the case of no accessibility delegate been set.
   22224          * </p>
   22225          *
   22226          * @param host The View hosting the delegate.
   22227          * @param child The child which requests sending the event.
   22228          * @param event The event to be sent.
   22229          * @return True if the event should be sent
   22230          *
   22231          * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
   22232          *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
   22233          */
   22234         public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
   22235                 AccessibilityEvent event) {
   22236             return host.onRequestSendAccessibilityEventInternal(child, event);
   22237         }
   22238 
   22239         /**
   22240          * Gets the provider for managing a virtual view hierarchy rooted at this View
   22241          * and reported to {@link android.accessibilityservice.AccessibilityService}s
   22242          * that explore the window content.
   22243          * <p>
   22244          * The default implementation behaves as
   22245          * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
   22246          * the case of no accessibility delegate been set.
   22247          * </p>
   22248          *
   22249          * @return The provider.
   22250          *
   22251          * @see AccessibilityNodeProvider
   22252          */
   22253         public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
   22254             return null;
   22255         }
   22256 
   22257         /**
   22258          * Returns an {@link AccessibilityNodeInfo} representing the host view from the
   22259          * point of view of an {@link android.accessibilityservice.AccessibilityService}.
   22260          * This method is responsible for obtaining an accessibility node info from a
   22261          * pool of reusable instances and calling
   22262          * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
   22263          * view to initialize the former.
   22264          * <p>
   22265          * <strong>Note:</strong> The client is responsible for recycling the obtained
   22266          * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
   22267          * creation.
   22268          * </p>
   22269          * <p>
   22270          * The default implementation behaves as
   22271          * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
   22272          * the case of no accessibility delegate been set.
   22273          * </p>
   22274          * @return A populated {@link AccessibilityNodeInfo}.
   22275          *
   22276          * @see AccessibilityNodeInfo
   22277          *
   22278          * @hide
   22279          */
   22280         public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
   22281             return host.createAccessibilityNodeInfoInternal();
   22282         }
   22283     }
   22284 
   22285     private class MatchIdPredicate implements Predicate<View> {
   22286         public int mId;
   22287 
   22288         @Override
   22289         public boolean apply(View view) {
   22290             return (view.mID == mId);
   22291         }
   22292     }
   22293 
   22294     private class MatchLabelForPredicate implements Predicate<View> {
   22295         private int mLabeledId;
   22296 
   22297         @Override
   22298         public boolean apply(View view) {
   22299             return (view.mLabelForId == mLabeledId);
   22300         }
   22301     }
   22302 
   22303     private class SendViewStateChangedAccessibilityEvent implements Runnable {
   22304         private int mChangeTypes = 0;
   22305         private boolean mPosted;
   22306         private boolean mPostedWithDelay;
   22307         private long mLastEventTimeMillis;
   22308 
   22309         @Override
   22310         public void run() {
   22311             mPosted = false;
   22312             mPostedWithDelay = false;
   22313             mLastEventTimeMillis = SystemClock.uptimeMillis();
   22314             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
   22315                 final AccessibilityEvent event = AccessibilityEvent.obtain();
   22316                 event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
   22317                 event.setContentChangeTypes(mChangeTypes);
   22318                 sendAccessibilityEventUnchecked(event);
   22319             }
   22320             mChangeTypes = 0;
   22321         }
   22322 
   22323         public void runOrPost(int changeType) {
   22324             mChangeTypes |= changeType;
   22325 
   22326             // If this is a live region or the child of a live region, collect
   22327             // all events from this frame and send them on the next frame.
   22328             if (inLiveRegion()) {
   22329                 // If we're already posted with a delay, remove that.
   22330                 if (mPostedWithDelay) {
   22331                     removeCallbacks(this);
   22332                     mPostedWithDelay = false;
   22333                 }
   22334                 // Only post if we're not already posted.
   22335                 if (!mPosted) {
   22336                     post(this);
   22337                     mPosted = true;
   22338                 }
   22339                 return;
   22340             }
   22341 
   22342             if (mPosted) {
   22343                 return;
   22344             }
   22345 
   22346             final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
   22347             final long minEventIntevalMillis =
   22348                     ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
   22349             if (timeSinceLastMillis >= minEventIntevalMillis) {
   22350                 removeCallbacks(this);
   22351                 run();
   22352             } else {
   22353                 postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
   22354                 mPostedWithDelay = true;
   22355             }
   22356         }
   22357     }
   22358 
   22359     private boolean inLiveRegion() {
   22360         if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
   22361             return true;
   22362         }
   22363 
   22364         ViewParent parent = getParent();
   22365         while (parent instanceof View) {
   22366             if (((View) parent).getAccessibilityLiveRegion()
   22367                     != View.ACCESSIBILITY_LIVE_REGION_NONE) {
   22368                 return true;
   22369             }
   22370             parent = parent.getParent();
   22371         }
   22372 
   22373         return false;
   22374     }
   22375 
   22376     /**
   22377      * Dump all private flags in readable format, useful for documentation and
   22378      * sanity checking.
   22379      */
   22380     private static void dumpFlags() {
   22381         final HashMap<String, String> found = Maps.newHashMap();
   22382         try {
   22383             for (Field field : View.class.getDeclaredFields()) {
   22384                 final int modifiers = field.getModifiers();
   22385                 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
   22386                     if (field.getType().equals(int.class)) {
   22387                         final int value = field.getInt(null);
   22388                         dumpFlag(found, field.getName(), value);
   22389                     } else if (field.getType().equals(int[].class)) {
   22390                         final int[] values = (int[]) field.get(null);
   22391                         for (int i = 0; i < values.length; i++) {
   22392                             dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
   22393                         }
   22394                     }
   22395                 }
   22396             }
   22397         } catch (IllegalAccessException e) {
   22398             throw new RuntimeException(e);
   22399         }
   22400 
   22401         final ArrayList<String> keys = Lists.newArrayList();
   22402         keys.addAll(found.keySet());
   22403         Collections.sort(keys);
   22404         for (String key : keys) {
   22405             Log.d(VIEW_LOG_TAG, found.get(key));
   22406         }
   22407     }
   22408 
   22409     private static void dumpFlag(HashMap<String, String> found, String name, int value) {
   22410         // Sort flags by prefix, then by bits, always keeping unique keys
   22411         final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
   22412         final int prefix = name.indexOf('_');
   22413         final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
   22414         final String output = bits + " " + name;
   22415         found.put(key, output);
   22416     }
   22417 
   22418     /** {@hide} */
   22419     public void encode(@NonNull ViewHierarchyEncoder stream) {
   22420         stream.beginObject(this);
   22421         encodeProperties(stream);
   22422         stream.endObject();
   22423     }
   22424 
   22425     /** {@hide} */
   22426     @CallSuper
   22427     protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
   22428         Object resolveId = ViewDebug.resolveId(getContext(), mID);
   22429         if (resolveId instanceof String) {
   22430             stream.addProperty("id", (String) resolveId);
   22431         } else {
   22432             stream.addProperty("id", mID);
   22433         }
   22434 
   22435         stream.addProperty("misc:transformation.alpha",
   22436                 mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
   22437         stream.addProperty("misc:transitionName", getTransitionName());
   22438 
   22439         // layout
   22440         stream.addProperty("layout:left", mLeft);
   22441         stream.addProperty("layout:right", mRight);
   22442         stream.addProperty("layout:top", mTop);
   22443         stream.addProperty("layout:bottom", mBottom);
   22444         stream.addProperty("layout:width", getWidth());
   22445         stream.addProperty("layout:height", getHeight());
   22446         stream.addProperty("layout:layoutDirection", getLayoutDirection());
   22447         stream.addProperty("layout:layoutRtl", isLayoutRtl());
   22448         stream.addProperty("layout:hasTransientState", hasTransientState());
   22449         stream.addProperty("layout:baseline", getBaseline());
   22450 
   22451         // layout params
   22452         ViewGroup.LayoutParams layoutParams = getLayoutParams();
   22453         if (layoutParams != null) {
   22454             stream.addPropertyKey("layoutParams");
   22455             layoutParams.encode(stream);
   22456         }
   22457 
   22458         // scrolling
   22459         stream.addProperty("scrolling:scrollX", mScrollX);
   22460         stream.addProperty("scrolling:scrollY", mScrollY);
   22461 
   22462         // padding
   22463         stream.addProperty("padding:paddingLeft", mPaddingLeft);
   22464         stream.addProperty("padding:paddingRight", mPaddingRight);
   22465         stream.addProperty("padding:paddingTop", mPaddingTop);
   22466         stream.addProperty("padding:paddingBottom", mPaddingBottom);
   22467         stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
   22468         stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
   22469         stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
   22470         stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
   22471         stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
   22472 
   22473         // measurement
   22474         stream.addProperty("measurement:minHeight", mMinHeight);
   22475         stream.addProperty("measurement:minWidth", mMinWidth);
   22476         stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
   22477         stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
   22478 
   22479         // drawing
   22480         stream.addProperty("drawing:elevation", getElevation());
   22481         stream.addProperty("drawing:translationX", getTranslationX());
   22482         stream.addProperty("drawing:translationY", getTranslationY());
   22483         stream.addProperty("drawing:translationZ", getTranslationZ());
   22484         stream.addProperty("drawing:rotation", getRotation());
   22485         stream.addProperty("drawing:rotationX", getRotationX());
   22486         stream.addProperty("drawing:rotationY", getRotationY());
   22487         stream.addProperty("drawing:scaleX", getScaleX());
   22488         stream.addProperty("drawing:scaleY", getScaleY());
   22489         stream.addProperty("drawing:pivotX", getPivotX());
   22490         stream.addProperty("drawing:pivotY", getPivotY());
   22491         stream.addProperty("drawing:opaque", isOpaque());
   22492         stream.addProperty("drawing:alpha", getAlpha());
   22493         stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
   22494         stream.addProperty("drawing:shadow", hasShadow());
   22495         stream.addProperty("drawing:solidColor", getSolidColor());
   22496         stream.addProperty("drawing:layerType", mLayerType);
   22497         stream.addProperty("drawing:willNotDraw", willNotDraw());
   22498         stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
   22499         stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
   22500         stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
   22501         stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
   22502 
   22503         // focus
   22504         stream.addProperty("focus:hasFocus", hasFocus());
   22505         stream.addProperty("focus:isFocused", isFocused());
   22506         stream.addProperty("focus:isFocusable", isFocusable());
   22507         stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
   22508 
   22509         stream.addProperty("misc:clickable", isClickable());
   22510         stream.addProperty("misc:pressed", isPressed());
   22511         stream.addProperty("misc:selected", isSelected());
   22512         stream.addProperty("misc:touchMode", isInTouchMode());
   22513         stream.addProperty("misc:hovered", isHovered());
   22514         stream.addProperty("misc:activated", isActivated());
   22515 
   22516         stream.addProperty("misc:visibility", getVisibility());
   22517         stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
   22518         stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
   22519 
   22520         stream.addProperty("misc:enabled", isEnabled());
   22521         stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
   22522         stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
   22523 
   22524         // theme attributes
   22525         Resources.Theme theme = getContext().getTheme();
   22526         if (theme != null) {
   22527             stream.addPropertyKey("theme");
   22528             theme.encode(stream);
   22529         }
   22530 
   22531         // view attribute information
   22532         int n = mAttributes != null ? mAttributes.length : 0;
   22533         stream.addProperty("meta:__attrCount__", n/2);
   22534         for (int i = 0; i < n; i += 2) {
   22535             stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
   22536         }
   22537 
   22538         stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
   22539 
   22540         // text
   22541         stream.addProperty("text:textDirection", getTextDirection());
   22542         stream.addProperty("text:textAlignment", getTextAlignment());
   22543 
   22544         // accessibility
   22545         CharSequence contentDescription = getContentDescription();
   22546         stream.addProperty("accessibility:contentDescription",
   22547                 contentDescription == null ? "" : contentDescription.toString());
   22548         stream.addProperty("accessibility:labelFor", getLabelFor());
   22549         stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
   22550     }
   22551 }
   22552