• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.view;
18 
19 import static android.content.res.Resources.ID_NULL;
20 import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS;
21 import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS;
22 import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP;
23 import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION;
24 import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
25 import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED;
26 
27 import static java.lang.Math.max;
28 
29 import android.animation.AnimatorInflater;
30 import android.animation.StateListAnimator;
31 import android.annotation.AttrRes;
32 import android.annotation.CallSuper;
33 import android.annotation.ColorInt;
34 import android.annotation.DrawableRes;
35 import android.annotation.FloatRange;
36 import android.annotation.IdRes;
37 import android.annotation.IntDef;
38 import android.annotation.IntRange;
39 import android.annotation.LayoutRes;
40 import android.annotation.NonNull;
41 import android.annotation.Nullable;
42 import android.annotation.Size;
43 import android.annotation.StyleRes;
44 import android.annotation.TestApi;
45 import android.annotation.UiThread;
46 import android.annotation.UnsupportedAppUsage;
47 import android.content.AutofillOptions;
48 import android.content.ClipData;
49 import android.content.Context;
50 import android.content.ContextWrapper;
51 import android.content.Intent;
52 import android.content.res.ColorStateList;
53 import android.content.res.Configuration;
54 import android.content.res.Resources;
55 import android.content.res.TypedArray;
56 import android.graphics.Bitmap;
57 import android.graphics.BlendMode;
58 import android.graphics.Canvas;
59 import android.graphics.Color;
60 import android.graphics.Insets;
61 import android.graphics.Interpolator;
62 import android.graphics.LinearGradient;
63 import android.graphics.Matrix;
64 import android.graphics.Outline;
65 import android.graphics.Paint;
66 import android.graphics.PixelFormat;
67 import android.graphics.Point;
68 import android.graphics.PorterDuff;
69 import android.graphics.PorterDuffXfermode;
70 import android.graphics.RecordingCanvas;
71 import android.graphics.Rect;
72 import android.graphics.RectF;
73 import android.graphics.Region;
74 import android.graphics.RenderNode;
75 import android.graphics.Shader;
76 import android.graphics.drawable.ColorDrawable;
77 import android.graphics.drawable.Drawable;
78 import android.hardware.display.DisplayManagerGlobal;
79 import android.net.Uri;
80 import android.os.Build;
81 import android.os.Bundle;
82 import android.os.Handler;
83 import android.os.IBinder;
84 import android.os.Message;
85 import android.os.Parcel;
86 import android.os.Parcelable;
87 import android.os.RemoteException;
88 import android.os.SystemClock;
89 import android.os.Trace;
90 import android.sysprop.DisplayProperties;
91 import android.text.InputType;
92 import android.text.TextUtils;
93 import android.util.AttributeSet;
94 import android.util.FloatProperty;
95 import android.util.LayoutDirection;
96 import android.util.Log;
97 import android.util.LongSparseLongArray;
98 import android.util.Pools.SynchronizedPool;
99 import android.util.Property;
100 import android.util.SparseArray;
101 import android.util.SparseIntArray;
102 import android.util.StateSet;
103 import android.util.StatsLog;
104 import android.util.SuperNotCalledException;
105 import android.util.TypedValue;
106 import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
107 import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
108 import android.view.AccessibilityIterators.TextSegmentIterator;
109 import android.view.AccessibilityIterators.WordTextSegmentIterator;
110 import android.view.ContextMenu.ContextMenuInfo;
111 import android.view.WindowInsetsAnimationListener.InsetsAnimation;
112 import android.view.accessibility.AccessibilityEvent;
113 import android.view.accessibility.AccessibilityEventSource;
114 import android.view.accessibility.AccessibilityManager;
115 import android.view.accessibility.AccessibilityNodeIdManager;
116 import android.view.accessibility.AccessibilityNodeInfo;
117 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
118 import android.view.accessibility.AccessibilityNodeProvider;
119 import android.view.accessibility.AccessibilityWindowInfo;
120 import android.view.animation.Animation;
121 import android.view.animation.AnimationUtils;
122 import android.view.animation.Transformation;
123 import android.view.autofill.AutofillId;
124 import android.view.autofill.AutofillManager;
125 import android.view.autofill.AutofillValue;
126 import android.view.contentcapture.ContentCaptureContext;
127 import android.view.contentcapture.ContentCaptureManager;
128 import android.view.contentcapture.ContentCaptureSession;
129 import android.view.inputmethod.EditorInfo;
130 import android.view.inputmethod.InputConnection;
131 import android.view.inputmethod.InputMethodManager;
132 import android.view.inspector.InspectableProperty;
133 import android.view.inspector.InspectableProperty.EnumEntry;
134 import android.view.inspector.InspectableProperty.FlagEntry;
135 import android.widget.Checkable;
136 import android.widget.FrameLayout;
137 import android.widget.ScrollBarDrawable;
138 
139 import com.android.internal.R;
140 import com.android.internal.view.TooltipPopup;
141 import com.android.internal.view.menu.MenuBuilder;
142 import com.android.internal.widget.ScrollBarUtils;
143 
144 import com.google.android.collect.Lists;
145 import com.google.android.collect.Maps;
146 
147 import java.lang.annotation.Retention;
148 import java.lang.annotation.RetentionPolicy;
149 import java.lang.ref.WeakReference;
150 import java.lang.reflect.Field;
151 import java.lang.reflect.InvocationTargetException;
152 import java.lang.reflect.Method;
153 import java.lang.reflect.Modifier;
154 import java.util.ArrayList;
155 import java.util.Arrays;
156 import java.util.Calendar;
157 import java.util.Collection;
158 import java.util.Collections;
159 import java.util.HashMap;
160 import java.util.List;
161 import java.util.Locale;
162 import java.util.Map;
163 import java.util.concurrent.CopyOnWriteArrayList;
164 import java.util.concurrent.atomic.AtomicInteger;
165 import java.util.function.Predicate;
166 
167 /**
168  * <p>
169  * This class represents the basic building block for user interface components. A View
170  * occupies a rectangular area on the screen and is responsible for drawing and
171  * event handling. View is the base class for <em>widgets</em>, which are
172  * used to create interactive UI components (buttons, text fields, etc.). The
173  * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
174  * are invisible containers that hold other Views (or other ViewGroups) and define
175  * their layout properties.
176  * </p>
177  *
178  * <div class="special reference">
179  * <h3>Developer Guides</h3>
180  * <p>For information about using this class to develop your application's user interface,
181  * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
182  * </div>
183  *
184  * <a name="Using"></a>
185  * <h3>Using Views</h3>
186  * <p>
187  * All of the views in a window are arranged in a single tree. You can add views
188  * either from code or by specifying a tree of views in one or more XML layout
189  * files. There are many specialized subclasses of views that act as controls or
190  * are capable of displaying text, images, or other content.
191  * </p>
192  * <p>
193  * Once you have created a tree of views, there are typically a few types of
194  * common operations you may wish to perform:
195  * <ul>
196  * <li><strong>Set properties:</strong> for example setting the text of a
197  * {@link android.widget.TextView}. The available properties and the methods
198  * that set them will vary among the different subclasses of views. Note that
199  * properties that are known at build time can be set in the XML layout
200  * files.</li>
201  * <li><strong>Set focus:</strong> The framework will handle moving focus in
202  * response to user input. To force focus to a specific view, call
203  * {@link #requestFocus}.</li>
204  * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
205  * that will be notified when something interesting happens to the view. For
206  * example, all views will let you set a listener to be notified when the view
207  * gains or loses focus. You can register such a listener using
208  * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
209  * Other view subclasses offer more specialized listeners. For example, a Button
210  * exposes a listener to notify clients when the button is clicked.</li>
211  * <li><strong>Set visibility:</strong> You can hide or show views using
212  * {@link #setVisibility(int)}.</li>
213  * </ul>
214  * </p>
215  * <p><em>
216  * Note: The Android framework is responsible for measuring, laying out and
217  * drawing views. You should not call methods that perform these actions on
218  * views yourself unless you are actually implementing a
219  * {@link android.view.ViewGroup}.
220  * </em></p>
221  *
222  * <a name="Lifecycle"></a>
223  * <h3>Implementing a Custom View</h3>
224  *
225  * <p>
226  * To implement a custom view, you will usually begin by providing overrides for
227  * some of the standard methods that the framework calls on all views. You do
228  * not need to override all of these methods. In fact, you can start by just
229  * overriding {@link #onDraw(android.graphics.Canvas)}.
230  * <table border="2" width="85%" align="center" cellpadding="5">
231  *     <thead>
232  *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
233  *     </thead>
234  *
235  *     <tbody>
236  *     <tr>
237  *         <td rowspan="2">Creation</td>
238  *         <td>Constructors</td>
239  *         <td>There is a form of the constructor that are called when the view
240  *         is created from code and a form that is called when the view is
241  *         inflated from a layout file. The second form should parse and apply
242  *         any attributes defined in the layout file.
243  *         </td>
244  *     </tr>
245  *     <tr>
246  *         <td><code>{@link #onFinishInflate()}</code></td>
247  *         <td>Called after a view and all of its children has been inflated
248  *         from XML.</td>
249  *     </tr>
250  *
251  *     <tr>
252  *         <td rowspan="3">Layout</td>
253  *         <td><code>{@link #onMeasure(int, int)}</code></td>
254  *         <td>Called to determine the size requirements for this view and all
255  *         of its children.
256  *         </td>
257  *     </tr>
258  *     <tr>
259  *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
260  *         <td>Called when this view should assign a size and position to all
261  *         of its children.
262  *         </td>
263  *     </tr>
264  *     <tr>
265  *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
266  *         <td>Called when the size of this view has changed.
267  *         </td>
268  *     </tr>
269  *
270  *     <tr>
271  *         <td>Drawing</td>
272  *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
273  *         <td>Called when the view should render its content.
274  *         </td>
275  *     </tr>
276  *
277  *     <tr>
278  *         <td rowspan="4">Event processing</td>
279  *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
280  *         <td>Called when a new hardware key event occurs.
281  *         </td>
282  *     </tr>
283  *     <tr>
284  *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
285  *         <td>Called when a hardware key up event occurs.
286  *         </td>
287  *     </tr>
288  *     <tr>
289  *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
290  *         <td>Called when a trackball motion event occurs.
291  *         </td>
292  *     </tr>
293  *     <tr>
294  *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
295  *         <td>Called when a touch screen motion event occurs.
296  *         </td>
297  *     </tr>
298  *
299  *     <tr>
300  *         <td rowspan="2">Focus</td>
301  *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
302  *         <td>Called when the view gains or loses focus.
303  *         </td>
304  *     </tr>
305  *
306  *     <tr>
307  *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
308  *         <td>Called when the window containing the view gains or loses focus.
309  *         </td>
310  *     </tr>
311  *
312  *     <tr>
313  *         <td rowspan="3">Attaching</td>
314  *         <td><code>{@link #onAttachedToWindow()}</code></td>
315  *         <td>Called when the view is attached to a window.
316  *         </td>
317  *     </tr>
318  *
319  *     <tr>
320  *         <td><code>{@link #onDetachedFromWindow}</code></td>
321  *         <td>Called when the view is detached from its window.
322  *         </td>
323  *     </tr>
324  *
325  *     <tr>
326  *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
327  *         <td>Called when the visibility of the window containing the view
328  *         has changed.
329  *         </td>
330  *     </tr>
331  *     </tbody>
332  *
333  * </table>
334  * </p>
335  *
336  * <a name="IDs"></a>
337  * <h3>IDs</h3>
338  * Views may have an integer id associated with them. These ids are typically
339  * assigned in the layout XML files, and are used to find specific views within
340  * the view tree. A common pattern is to:
341  * <ul>
342  * <li>Define a Button in the layout file and assign it a unique ID.
343  * <pre>
344  * &lt;Button
345  *     android:id="@+id/my_button"
346  *     android:layout_width="wrap_content"
347  *     android:layout_height="wrap_content"
348  *     android:text="@string/my_button_text"/&gt;
349  * </pre></li>
350  * <li>From the onCreate method of an Activity, find the Button
351  * <pre class="prettyprint">
352  *      Button myButton = findViewById(R.id.my_button);
353  * </pre></li>
354  * </ul>
355  * <p>
356  * View IDs need not be unique throughout the tree, but it is good practice to
357  * ensure that they are at least unique within the part of the tree you are
358  * searching.
359  * </p>
360  *
361  * <a name="Position"></a>
362  * <h3>Position</h3>
363  * <p>
364  * The geometry of a view is that of a rectangle. A view has a location,
365  * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
366  * two dimensions, expressed as a width and a height. The unit for location
367  * and dimensions is the pixel.
368  * </p>
369  *
370  * <p>
371  * It is possible to retrieve the location of a view by invoking the methods
372  * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
373  * coordinate of the rectangle representing the view. The latter returns the
374  * top, or Y, coordinate of the rectangle representing the view. These methods
375  * both return the location of the view relative to its parent. For instance,
376  * when getLeft() returns 20, that means the view is located 20 pixels to the
377  * right of the left edge of its direct parent.
378  * </p>
379  *
380  * <p>
381  * In addition, several convenience methods are offered to avoid unnecessary
382  * computations, namely {@link #getRight()} and {@link #getBottom()}.
383  * These methods return the coordinates of the right and bottom edges of the
384  * rectangle representing the view. For instance, calling {@link #getRight()}
385  * is similar to the following computation: <code>getLeft() + getWidth()</code>
386  * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
387  * </p>
388  *
389  * <a name="SizePaddingMargins"></a>
390  * <h3>Size, padding and margins</h3>
391  * <p>
392  * The size of a view is expressed with a width and a height. A view actually
393  * possess two pairs of width and height values.
394  * </p>
395  *
396  * <p>
397  * The first pair is known as <em>measured width</em> and
398  * <em>measured height</em>. These dimensions define how big a view wants to be
399  * within its parent (see <a href="#Layout">Layout</a> for more details.) The
400  * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
401  * and {@link #getMeasuredHeight()}.
402  * </p>
403  *
404  * <p>
405  * The second pair is simply known as <em>width</em> and <em>height</em>, or
406  * sometimes <em>drawing width</em> and <em>drawing height</em>. These
407  * dimensions define the actual size of the view on screen, at drawing time and
408  * after layout. These values may, but do not have to, be different from the
409  * measured width and height. The width and height can be obtained by calling
410  * {@link #getWidth()} and {@link #getHeight()}.
411  * </p>
412  *
413  * <p>
414  * To measure its dimensions, a view takes into account its padding. The padding
415  * is expressed in pixels for the left, top, right and bottom parts of the view.
416  * Padding can be used to offset the content of the view by a specific amount of
417  * pixels. For instance, a left padding of 2 will push the view's content by
418  * 2 pixels to the right of the left edge. Padding can be set using the
419  * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
420  * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
421  * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
422  * {@link #getPaddingEnd()}.
423  * </p>
424  *
425  * <p>
426  * Even though a view can define a padding, it does not provide any support for
427  * margins. However, view groups provide such a support. Refer to
428  * {@link android.view.ViewGroup} and
429  * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
430  * </p>
431  *
432  * <a name="Layout"></a>
433  * <h3>Layout</h3>
434  * <p>
435  * Layout is a two pass process: a measure pass and a layout pass. The measuring
436  * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
437  * of the view tree. Each view pushes dimension specifications down the tree
438  * during the recursion. At the end of the measure pass, every view has stored
439  * its measurements. The second pass happens in
440  * {@link #layout(int,int,int,int)} and is also top-down. During
441  * this pass each parent is responsible for positioning all of its children
442  * using the sizes computed in the measure pass.
443  * </p>
444  *
445  * <p>
446  * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
447  * {@link #getMeasuredHeight()} values must be set, along with those for all of
448  * that view's descendants. A view's measured width and measured height values
449  * must respect the constraints imposed by the view's parents. This guarantees
450  * that at the end of the measure pass, all parents accept all of their
451  * children's measurements. A parent view may call measure() more than once on
452  * its children. For example, the parent may measure each child once with
453  * unspecified dimensions to find out how big they want to be, then call
454  * measure() on them again with actual numbers if the sum of all the children's
455  * unconstrained sizes is too big or too small.
456  * </p>
457  *
458  * <p>
459  * The measure pass uses two classes to communicate dimensions. The
460  * {@link MeasureSpec} class is used by views to tell their parents how they
461  * want to be measured and positioned. The base LayoutParams class just
462  * describes how big the view wants to be for both width and height. For each
463  * dimension, it can specify one of:
464  * <ul>
465  * <li> an exact number
466  * <li>MATCH_PARENT, which means the view wants to be as big as its parent
467  * (minus padding)
468  * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
469  * enclose its content (plus padding).
470  * </ul>
471  * There are subclasses of LayoutParams for different subclasses of ViewGroup.
472  * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
473  * an X and Y value.
474  * </p>
475  *
476  * <p>
477  * MeasureSpecs are used to push requirements down the tree from parent to
478  * child. A MeasureSpec can be in one of three modes:
479  * <ul>
480  * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
481  * of a child view. For example, a LinearLayout may call measure() on its child
482  * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
483  * tall the child view wants to be given a width of 240 pixels.
484  * <li>EXACTLY: This is used by the parent to impose an exact size on the
485  * child. The child must use this size, and guarantee that all of its
486  * descendants will fit within this size.
487  * <li>AT_MOST: This is used by the parent to impose a maximum size on the
488  * child. The child must guarantee that it and all of its descendants will fit
489  * within this size.
490  * </ul>
491  * </p>
492  *
493  * <p>
494  * To initiate a layout, call {@link #requestLayout}. This method is typically
495  * called by a view on itself when it believes that is can no longer fit within
496  * its current bounds.
497  * </p>
498  *
499  * <a name="Drawing"></a>
500  * <h3>Drawing</h3>
501  * <p>
502  * Drawing is handled by walking the tree and recording the drawing commands of
503  * any View that needs to update. After this, the drawing commands of the
504  * entire tree are issued to screen, clipped to the newly damaged area.
505  * </p>
506  *
507  * <p>
508  * The tree is largely recorded and drawn in order, with parents drawn before
509  * (i.e., behind) their children, with siblings drawn in the order they appear
510  * in the tree. If you set a background drawable for a View, then the View will
511  * draw it before calling back to its <code>onDraw()</code> method. The child
512  * drawing order can be overridden with
513  * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
514  * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
515  * </p>
516  *
517  * <p>
518  * To force a view to draw, call {@link #invalidate()}.
519  * </p>
520  *
521  * <a name="EventHandlingThreading"></a>
522  * <h3>Event Handling and Threading</h3>
523  * <p>
524  * The basic cycle of a view is as follows:
525  * <ol>
526  * <li>An event comes in and is dispatched to the appropriate view. The view
527  * handles the event and notifies any listeners.</li>
528  * <li>If in the course of processing the event, the view's bounds may need
529  * to be changed, the view will call {@link #requestLayout()}.</li>
530  * <li>Similarly, if in the course of processing the event the view's appearance
531  * may need to be changed, the view will call {@link #invalidate()}.</li>
532  * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
533  * the framework will take care of measuring, laying out, and drawing the tree
534  * as appropriate.</li>
535  * </ol>
536  * </p>
537  *
538  * <p><em>Note: The entire view tree is single threaded. You must always be on
539  * the UI thread when calling any method on any view.</em>
540  * If you are doing work on other threads and want to update the state of a view
541  * from that thread, you should use a {@link Handler}.
542  * </p>
543  *
544  * <a name="FocusHandling"></a>
545  * <h3>Focus Handling</h3>
546  * <p>
547  * The framework will handle routine focus movement in response to user input.
548  * This includes changing the focus as views are removed or hidden, or as new
549  * views become available. Views indicate their willingness to take focus
550  * through the {@link #isFocusable} method. To change whether a view can take
551  * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
552  * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
553  * and can change this via {@link #setFocusableInTouchMode(boolean)}.
554  * </p>
555  * <p>
556  * Focus movement is based on an algorithm which finds the nearest neighbor in a
557  * given direction. In rare cases, the default algorithm may not match the
558  * intended behavior of the developer. In these situations, you can provide
559  * explicit overrides by using these XML attributes in the layout file:
560  * <pre>
561  * nextFocusDown
562  * nextFocusLeft
563  * nextFocusRight
564  * nextFocusUp
565  * </pre>
566  * </p>
567  *
568  *
569  * <p>
570  * To get a particular view to take focus, call {@link #requestFocus()}.
571  * </p>
572  *
573  * <a name="TouchMode"></a>
574  * <h3>Touch Mode</h3>
575  * <p>
576  * When a user is navigating a user interface via directional keys such as a D-pad, it is
577  * necessary to give focus to actionable items such as buttons so the user can see
578  * what will take input.  If the device has touch capabilities, however, and the user
579  * begins interacting with the interface by touching it, it is no longer necessary to
580  * always highlight, or give focus to, a particular view.  This motivates a mode
581  * for interaction named 'touch mode'.
582  * </p>
583  * <p>
584  * For a touch capable device, once the user touches the screen, the device
585  * will enter touch mode.  From this point onward, only views for which
586  * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
587  * Other views that are touchable, like buttons, will not take focus when touched; they will
588  * only fire the on click listeners.
589  * </p>
590  * <p>
591  * Any time a user hits a directional key, such as a D-pad direction, the view device will
592  * exit touch mode, and find a view to take focus, so that the user may resume interacting
593  * with the user interface without touching the screen again.
594  * </p>
595  * <p>
596  * The touch mode state is maintained across {@link android.app.Activity}s.  Call
597  * {@link #isInTouchMode} to see whether the device is currently in touch mode.
598  * </p>
599  *
600  * <a name="Scrolling"></a>
601  * <h3>Scrolling</h3>
602  * <p>
603  * The framework provides basic support for views that wish to internally
604  * scroll their content. This includes keeping track of the X and Y scroll
605  * offset as well as mechanisms for drawing scrollbars. See
606  * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
607  * {@link #awakenScrollBars()} for more details.
608  * </p>
609  *
610  * <a name="Tags"></a>
611  * <h3>Tags</h3>
612  * <p>
613  * Unlike IDs, tags are not used to identify views. Tags are essentially an
614  * extra piece of information that can be associated with a view. They are most
615  * often used as a convenience to store data related to views in the views
616  * themselves rather than by putting them in a separate structure.
617  * </p>
618  * <p>
619  * Tags may be specified with character sequence values in layout XML as either
620  * a single tag using the {@link android.R.styleable#View_tag android:tag}
621  * attribute or multiple tags using the {@code <tag>} child element:
622  * <pre>
623  *     &lt;View ...
624  *           android:tag="@string/mytag_value" /&gt;
625  *     &lt;View ...&gt;
626  *         &lt;tag android:id="@+id/mytag"
627  *              android:value="@string/mytag_value" /&gt;
628  *     &lt;/View>
629  * </pre>
630  * </p>
631  * <p>
632  * Tags may also be specified with arbitrary objects from code using
633  * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
634  * </p>
635  *
636  * <a name="Themes"></a>
637  * <h3>Themes</h3>
638  * <p>
639  * By default, Views are created using the theme of the Context object supplied
640  * to their constructor; however, a different theme may be specified by using
641  * the {@link android.R.styleable#View_theme android:theme} attribute in layout
642  * XML or by passing a {@link ContextThemeWrapper} to the constructor from
643  * code.
644  * </p>
645  * <p>
646  * When the {@link android.R.styleable#View_theme android:theme} attribute is
647  * used in XML, the specified theme is applied on top of the inflation
648  * context's theme (see {@link LayoutInflater}) and used for the view itself as
649  * well as any child elements.
650  * </p>
651  * <p>
652  * In the following example, both views will be created using the Material dark
653  * color scheme; however, because an overlay theme is used which only defines a
654  * subset of attributes, the value of
655  * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
656  * the inflation context's theme (e.g. the Activity theme) will be preserved.
657  * <pre>
658  *     &lt;LinearLayout
659  *             ...
660  *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
661  *         &lt;View ...&gt;
662  *     &lt;/LinearLayout&gt;
663  * </pre>
664  * </p>
665  *
666  * <a name="Properties"></a>
667  * <h3>Properties</h3>
668  * <p>
669  * The View class exposes an {@link #ALPHA} property, as well as several transform-related
670  * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
671  * available both in the {@link Property} form as well as in similarly-named setter/getter
672  * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
673  * be used to set persistent state associated with these rendering-related properties on the view.
674  * The properties and methods can also be used in conjunction with
675  * {@link android.animation.Animator Animator}-based animations, described more in the
676  * <a href="#Animation">Animation</a> section.
677  * </p>
678  *
679  * <a name="Animation"></a>
680  * <h3>Animation</h3>
681  * <p>
682  * Starting with Android 3.0, the preferred way of animating views is to use the
683  * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
684  * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
685  * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
686  * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
687  * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
688  * makes animating these View properties particularly easy and efficient.
689  * </p>
690  * <p>
691  * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
692  * You can attach an {@link Animation} object to a view using
693  * {@link #setAnimation(Animation)} or
694  * {@link #startAnimation(Animation)}. The animation can alter the scale,
695  * rotation, translation and alpha of a view over time. If the animation is
696  * attached to a view that has children, the animation will affect the entire
697  * subtree rooted by that node. When an animation is started, the framework will
698  * take care of redrawing the appropriate views until the animation completes.
699  * </p>
700  *
701  * <a name="Security"></a>
702  * <h3>Security</h3>
703  * <p>
704  * Sometimes it is essential that an application be able to verify that an action
705  * is being performed with the full knowledge and consent of the user, such as
706  * granting a permission request, making a purchase or clicking on an advertisement.
707  * Unfortunately, a malicious application could try to spoof the user into
708  * performing these actions, unaware, by concealing the intended purpose of the view.
709  * As a remedy, the framework offers a touch filtering mechanism that can be used to
710  * improve the security of views that provide access to sensitive functionality.
711  * </p><p>
712  * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
713  * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
714  * will discard touches that are received whenever the view's window is obscured by
715  * another visible window.  As a result, the view will not receive touches whenever a
716  * toast, dialog or other window appears above the view's window.
717  * </p><p>
718  * For more fine-grained control over security, consider overriding the
719  * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
720  * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
721  * </p>
722  *
723  * @attr ref android.R.styleable#View_accessibilityHeading
724  * @attr ref android.R.styleable#View_alpha
725  * @attr ref android.R.styleable#View_background
726  * @attr ref android.R.styleable#View_clickable
727  * @attr ref android.R.styleable#View_contentDescription
728  * @attr ref android.R.styleable#View_drawingCacheQuality
729  * @attr ref android.R.styleable#View_duplicateParentState
730  * @attr ref android.R.styleable#View_id
731  * @attr ref android.R.styleable#View_requiresFadingEdge
732  * @attr ref android.R.styleable#View_fadeScrollbars
733  * @attr ref android.R.styleable#View_fadingEdgeLength
734  * @attr ref android.R.styleable#View_filterTouchesWhenObscured
735  * @attr ref android.R.styleable#View_fitsSystemWindows
736  * @attr ref android.R.styleable#View_isScrollContainer
737  * @attr ref android.R.styleable#View_focusable
738  * @attr ref android.R.styleable#View_focusableInTouchMode
739  * @attr ref android.R.styleable#View_focusedByDefault
740  * @attr ref android.R.styleable#View_hapticFeedbackEnabled
741  * @attr ref android.R.styleable#View_keepScreenOn
742  * @attr ref android.R.styleable#View_keyboardNavigationCluster
743  * @attr ref android.R.styleable#View_layerType
744  * @attr ref android.R.styleable#View_layoutDirection
745  * @attr ref android.R.styleable#View_longClickable
746  * @attr ref android.R.styleable#View_minHeight
747  * @attr ref android.R.styleable#View_minWidth
748  * @attr ref android.R.styleable#View_nextClusterForward
749  * @attr ref android.R.styleable#View_nextFocusDown
750  * @attr ref android.R.styleable#View_nextFocusLeft
751  * @attr ref android.R.styleable#View_nextFocusRight
752  * @attr ref android.R.styleable#View_nextFocusUp
753  * @attr ref android.R.styleable#View_onClick
754  * @attr ref android.R.styleable#View_outlineSpotShadowColor
755  * @attr ref android.R.styleable#View_outlineAmbientShadowColor
756  * @attr ref android.R.styleable#View_padding
757  * @attr ref android.R.styleable#View_paddingHorizontal
758  * @attr ref android.R.styleable#View_paddingVertical
759  * @attr ref android.R.styleable#View_paddingBottom
760  * @attr ref android.R.styleable#View_paddingLeft
761  * @attr ref android.R.styleable#View_paddingRight
762  * @attr ref android.R.styleable#View_paddingTop
763  * @attr ref android.R.styleable#View_paddingStart
764  * @attr ref android.R.styleable#View_paddingEnd
765  * @attr ref android.R.styleable#View_saveEnabled
766  * @attr ref android.R.styleable#View_rotation
767  * @attr ref android.R.styleable#View_rotationX
768  * @attr ref android.R.styleable#View_rotationY
769  * @attr ref android.R.styleable#View_scaleX
770  * @attr ref android.R.styleable#View_scaleY
771  * @attr ref android.R.styleable#View_scrollX
772  * @attr ref android.R.styleable#View_scrollY
773  * @attr ref android.R.styleable#View_scrollbarSize
774  * @attr ref android.R.styleable#View_scrollbarStyle
775  * @attr ref android.R.styleable#View_scrollbars
776  * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
777  * @attr ref android.R.styleable#View_scrollbarFadeDuration
778  * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
779  * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
780  * @attr ref android.R.styleable#View_scrollbarThumbVertical
781  * @attr ref android.R.styleable#View_scrollbarTrackVertical
782  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
783  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
784  * @attr ref android.R.styleable#View_stateListAnimator
785  * @attr ref android.R.styleable#View_transitionName
786  * @attr ref android.R.styleable#View_soundEffectsEnabled
787  * @attr ref android.R.styleable#View_tag
788  * @attr ref android.R.styleable#View_textAlignment
789  * @attr ref android.R.styleable#View_textDirection
790  * @attr ref android.R.styleable#View_transformPivotX
791  * @attr ref android.R.styleable#View_transformPivotY
792  * @attr ref android.R.styleable#View_translationX
793  * @attr ref android.R.styleable#View_translationY
794  * @attr ref android.R.styleable#View_translationZ
795  * @attr ref android.R.styleable#View_visibility
796  * @attr ref android.R.styleable#View_theme
797  *
798  * @see android.view.ViewGroup
799  */
800 @UiThread
801 public class View implements Drawable.Callback, KeyEvent.Callback,
802         AccessibilityEventSource {
803     @UnsupportedAppUsage
804     private static final boolean DBG = false;
805 
806     /** @hide */
807     public static boolean DEBUG_DRAW = false;
808 
809     /**
810      * The logging tag used by this class with android.util.Log.
811      */
812     protected static final String VIEW_LOG_TAG = "View";
813 
814     /**
815      * The logging tag used by this class when logging verbose, autofill-related messages.
816      */
817     // NOTE: We cannot use android.view.autofill.Helper.sVerbose because that variable is not
818     // set if a session is not started.
819     private static final String AUTOFILL_LOG_TAG = "View.Autofill";
820 
821     /**
822      * The logging tag used by this class when logging content capture-related messages.
823      */
824     private static final String CONTENT_CAPTURE_LOG_TAG = "View.ContentCapture";
825 
826     private static final boolean DEBUG_CONTENT_CAPTURE = false;
827 
828     /**
829      * When set to true, this view will save its attribute data.
830      *
831      * @hide
832      */
833     public static boolean sDebugViewAttributes = false;
834 
835     /**
836      * When set to this application package view will save its attribute data.
837      *
838      * @hide
839      */
840     public static String sDebugViewAttributesApplicationPackage;
841 
842     /**
843      * Used to mark a View that has no ID.
844      */
845     public static final int NO_ID = -1;
846 
847     /**
848      * Last ID that is given to Views that are no part of activities.
849      *
850      * {@hide}
851      */
852     public static final int LAST_APP_AUTOFILL_ID = Integer.MAX_VALUE / 2;
853 
854     /**
855      * Attribute to find the autofilled highlight
856      *
857      * @see #getAutofilledDrawable()
858      */
859     private static final int[] AUTOFILL_HIGHLIGHT_ATTR =
860             new int[]{android.R.attr.autofilledHighlight};
861 
862     /**
863      * Signals that compatibility booleans have been initialized according to
864      * target SDK versions.
865      */
866     private static boolean sCompatibilityDone = false;
867 
868     /**
869      * Use the old (broken) way of building MeasureSpecs.
870      */
871     private static boolean sUseBrokenMakeMeasureSpec = false;
872 
873     /**
874      * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
875      */
876     static boolean sUseZeroUnspecifiedMeasureSpec = false;
877 
878     /**
879      * Ignore any optimizations using the measure cache.
880      */
881     private static boolean sIgnoreMeasureCache = false;
882 
883     /**
884      * Ignore an optimization that skips unnecessary EXACTLY layout passes.
885      */
886     private static boolean sAlwaysRemeasureExactly = false;
887 
888     /**
889      * Allow setForeground/setBackground to be called (and ignored) on a textureview,
890      * without throwing
891      */
892     static boolean sTextureViewIgnoresDrawableSetters = false;
893 
894     /**
895      * Prior to N, some ViewGroups would not convert LayoutParams properly even though both extend
896      * MarginLayoutParams. For instance, converting LinearLayout.LayoutParams to
897      * RelativeLayout.LayoutParams would lose margin information. This is fixed on N but target API
898      * check is implemented for backwards compatibility.
899      *
900      * {@hide}
901      */
902     protected static boolean sPreserveMarginParamsInLayoutParamConversion;
903 
904     /**
905      * Prior to N, when drag enters into child of a view that has already received an
906      * ACTION_DRAG_ENTERED event, the parent doesn't get a ACTION_DRAG_EXITED event.
907      * ACTION_DRAG_LOCATION and ACTION_DROP were delivered to the parent of a view that returned
908      * false from its event handler for these events.
909      * Starting from N, the parent will get ACTION_DRAG_EXITED event before the child gets its
910      * ACTION_DRAG_ENTERED. ACTION_DRAG_LOCATION and ACTION_DROP are never propagated to the parent.
911      * sCascadedDragDrop is true for pre-N apps for backwards compatibility implementation.
912      */
913     static boolean sCascadedDragDrop;
914 
915     /**
916      * Prior to O, auto-focusable didn't exist and widgets such as ListView use hasFocusable
917      * to determine things like whether or not to permit item click events. We can't break
918      * apps that do this just because more things (clickable things) are now auto-focusable
919      * and they would get different results, so give old behavior to old apps.
920      */
921     static boolean sHasFocusableExcludeAutoFocusable;
922 
923     /**
924      * Prior to O, auto-focusable didn't exist and views marked as clickable weren't implicitly
925      * made focusable by default. As a result, apps could (incorrectly) change the clickable
926      * setting of views off the UI thread. Now that clickable can effect the focusable state,
927      * changing the clickable attribute off the UI thread will cause an exception (since changing
928      * the focusable state checks). In order to prevent apps from crashing, we will handle this
929      * specific case and just not notify parents on new focusables resulting from marking views
930      * clickable from outside the UI thread.
931      */
932     private static boolean sAutoFocusableOffUIThreadWontNotifyParents;
933 
934     /**
935      * Prior to P things like setScaleX() allowed passing float values that were bogus such as
936      * Float.NaN. If the app is targetting P or later then passing these values will result in an
937      * exception being thrown. If the app is targetting an earlier SDK version, then we will
938      * silently clamp these values to avoid crashes elsewhere when the rendering code hits
939      * these bogus values.
940      */
941     private static boolean sThrowOnInvalidFloatProperties;
942 
943     /**
944      * Prior to P, {@code #startDragAndDrop} accepts a builder which produces an empty drag shadow.
945      * Currently zero size SurfaceControl cannot be created thus we create a dummy 1x1 surface
946      * instead.
947      */
948     private static boolean sAcceptZeroSizeDragShadow;
949 
950     /**
951      * Prior to Q, {@link #dispatchApplyWindowInsets} had some issues:
952      * <ul>
953      *     <li>The modified insets changed by {@link #onApplyWindowInsets} were passed to the
954      *     entire view hierarchy in prefix order, including siblings as well as siblings of parents
955      *     further down the hierarchy. This violates the basic concepts of the view hierarchy, and
956      *     thus, the hierarchical dispatching mechanism was hard to use for apps.</li>
957      *
958      *     <li>Dispatch was stopped after the insets were fully consumed. This is somewhat confusing
959      *     for developers, but more importantly, by adding more granular information to
960      *     {@link WindowInsets} it becomes really cumbersome to define what consumed actually means
961      *     </li>
962      * </ul>
963      *
964      * In order to make window inset dispatching work properly, we dispatch window insets
965      * in the view hierarchy in a proper hierarchical manner and don't stop dispatching if the
966      * insets are consumed if this flag is set to {@code false}.
967      */
968     static boolean sBrokenInsetsDispatch;
969 
970     /**
971      * Prior to Q, calling
972      * {@link com.android.internal.policy.DecorView#setBackgroundDrawable(Drawable)}
973      * did not call update the window format so the opacity of the background was not correctly
974      * applied to the window. Some applications rely on this misbehavior to work properly.
975      * <p>
976      * From Q, {@link com.android.internal.policy.DecorView#setBackgroundDrawable(Drawable)} is
977      * the same as {@link com.android.internal.policy.DecorView#setWindowBackground(Drawable)}
978      * which updates the window format.
979      * @hide
980      */
981     protected static boolean sBrokenWindowBackground;
982 
983     /** @hide */
984     @IntDef({NOT_FOCUSABLE, FOCUSABLE, FOCUSABLE_AUTO})
985     @Retention(RetentionPolicy.SOURCE)
986     public @interface Focusable {}
987 
988     /**
989      * This view does not want keystrokes.
990      * <p>
991      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
992      * android:focusable}.
993      */
994     public static final int NOT_FOCUSABLE = 0x00000000;
995 
996     /**
997      * This view wants keystrokes.
998      * <p>
999      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
1000      * android:focusable}.
1001      */
1002     public static final int FOCUSABLE = 0x00000001;
1003 
1004     /**
1005      * This view determines focusability automatically. This is the default.
1006      * <p>
1007      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
1008      * android:focusable}.
1009      */
1010     public static final int FOCUSABLE_AUTO = 0x00000010;
1011 
1012     /**
1013      * Mask for use with setFlags indicating bits used for focus.
1014      */
1015     private static final int FOCUSABLE_MASK = 0x00000011;
1016 
1017     /**
1018      * This view will adjust its padding to fit sytem windows (e.g. status bar)
1019      */
1020     private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
1021 
1022     /** @hide */
1023     @IntDef({VISIBLE, INVISIBLE, GONE})
1024     @Retention(RetentionPolicy.SOURCE)
1025     public @interface Visibility {}
1026 
1027     /**
1028      * This view is visible.
1029      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
1030      * android:visibility}.
1031      */
1032     public static final int VISIBLE = 0x00000000;
1033 
1034     /**
1035      * This view is invisible, but it still takes up space for layout purposes.
1036      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
1037      * android:visibility}.
1038      */
1039     public static final int INVISIBLE = 0x00000004;
1040 
1041     /**
1042      * This view is invisible, and it doesn't take any space for layout
1043      * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
1044      * android:visibility}.
1045      */
1046     public static final int GONE = 0x00000008;
1047 
1048     /**
1049      * Mask for use with setFlags indicating bits used for visibility.
1050      * {@hide}
1051      */
1052     static final int VISIBILITY_MASK = 0x0000000C;
1053 
1054     private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
1055 
1056     /**
1057      * Hint indicating that this view can be autofilled with an email address.
1058      *
1059      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1060      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1061      * value should be <code>{@value #AUTOFILL_HINT_EMAIL_ADDRESS}</code>).
1062      *
1063      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1064      */
1065     public static final String AUTOFILL_HINT_EMAIL_ADDRESS = "emailAddress";
1066 
1067     /**
1068      * Hint indicating that this view can be autofilled with a user's real name.
1069      *
1070      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1071      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1072      * value should be <code>{@value #AUTOFILL_HINT_NAME}</code>).
1073      *
1074      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1075      */
1076     public static final String AUTOFILL_HINT_NAME = "name";
1077 
1078     /**
1079      * Hint indicating that this view can be autofilled with a username.
1080      *
1081      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1082      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1083      * value should be <code>{@value #AUTOFILL_HINT_USERNAME}</code>).
1084      *
1085      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1086      */
1087     public static final String AUTOFILL_HINT_USERNAME = "username";
1088 
1089     /**
1090      * Hint indicating that this view can be autofilled with a password.
1091      *
1092      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1093      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1094      * value should be <code>{@value #AUTOFILL_HINT_PASSWORD}</code>).
1095      *
1096      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1097      */
1098     public static final String AUTOFILL_HINT_PASSWORD = "password";
1099 
1100     /**
1101      * Hint indicating that this view can be autofilled with a phone number.
1102      *
1103      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1104      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1105      * value should be <code>{@value #AUTOFILL_HINT_PHONE}</code>).
1106      *
1107      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1108      */
1109     public static final String AUTOFILL_HINT_PHONE = "phone";
1110 
1111     /**
1112      * Hint indicating that this view can be autofilled with a postal address.
1113      *
1114      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1115      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1116      * value should be <code>{@value #AUTOFILL_HINT_POSTAL_ADDRESS}</code>).
1117      *
1118      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1119      */
1120     public static final String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress";
1121 
1122     /**
1123      * Hint indicating that this view can be autofilled with a postal code.
1124      *
1125      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1126      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1127      * value should be <code>{@value #AUTOFILL_HINT_POSTAL_CODE}</code>).
1128      *
1129      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1130      */
1131     public static final String AUTOFILL_HINT_POSTAL_CODE = "postalCode";
1132 
1133     /**
1134      * Hint indicating that this view can be autofilled with a credit card number.
1135      *
1136      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1137      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1138      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_NUMBER}</code>).
1139      *
1140      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1141      */
1142     public static final String AUTOFILL_HINT_CREDIT_CARD_NUMBER = "creditCardNumber";
1143 
1144     /**
1145      * Hint indicating that this view can be autofilled with a credit card security code.
1146      *
1147      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1148      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1149      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE}</code>).
1150      *
1151      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1152      */
1153     public static final String AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE = "creditCardSecurityCode";
1154 
1155     /**
1156      * Hint indicating that this view can be autofilled with a credit card expiration date.
1157      *
1158      * <p>It should be used when the credit card expiration date is represented by just one view;
1159      * if it is represented by more than one (for example, one view for the month and another view
1160      * for the year), then each of these views should use the hint specific for the unit
1161      * ({@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
1162      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH},
1163      * or {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}).
1164      *
1165      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1166      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1167      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE}</code>).
1168      *
1169      * <p>When annotating a view with this hint, it's recommended to use a date autofill value to
1170      * avoid ambiguity when the autofill service provides a value for it. To understand why a
1171      * value can be ambiguous, consider "April of 2020", which could be represented as either of
1172      * the following options:
1173      *
1174      * <ul>
1175      *   <li>{@code "04/2020"}
1176      *   <li>{@code "4/2020"}
1177      *   <li>{@code "2020/04"}
1178      *   <li>{@code "2020/4"}
1179      *   <li>{@code "April/2020"}
1180      *   <li>{@code "Apr/2020"}
1181      * </ul>
1182      *
1183      * <p>You define a date autofill value for the view by overriding the following methods:
1184      *
1185      * <ol>
1186      *   <li>{@link #getAutofillType()} to return {@link #AUTOFILL_TYPE_DATE}.
1187      *   <li>{@link #getAutofillValue()} to return a
1188      *       {@link AutofillValue#forDate(long) date autofillvalue}.
1189      *   <li>{@link #autofill(AutofillValue)} to expect a data autofillvalue.
1190      * </ol>
1191      *
1192      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1193      */
1194     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE =
1195             "creditCardExpirationDate";
1196 
1197     /**
1198      * Hint indicating that this view can be autofilled with a credit card expiration month.
1199      *
1200      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1201      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1202      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH}</code>).
1203      *
1204      * <p>When annotating a view with this hint, it's recommended to use a text autofill value
1205      * whose value is the numerical representation of the month, starting on {@code 1} to avoid
1206      * ambiguity when the autofill service provides a value for it. To understand why a
1207      * value can be ambiguous, consider "January", which could be represented as either of
1208      *
1209      * <ul>
1210      *   <li>{@code "1"}: recommended way.
1211      *   <li>{@code "0"}: if following the {@link Calendar#MONTH} convention.
1212      *   <li>{@code "January"}: full name, in English.
1213      *   <li>{@code "jan"}: abbreviated name, in English.
1214      *   <li>{@code "Janeiro"}: full name, in another language.
1215      * </ul>
1216      *
1217      * <p>Another recommended approach is to use a date autofill value - see
1218      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE} for more details.
1219      *
1220      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1221      */
1222     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH =
1223             "creditCardExpirationMonth";
1224 
1225     /**
1226      * Hint indicating that this view can be autofilled with a credit card expiration year.
1227      *
1228      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1229      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1230      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}</code>).
1231      *
1232      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1233      */
1234     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR =
1235             "creditCardExpirationYear";
1236 
1237     /**
1238      * Hint indicating that this view can be autofilled with a credit card expiration day.
1239      *
1240      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1241      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1242      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY}</code>).
1243      *
1244      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1245      */
1246     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY = "creditCardExpirationDay";
1247 
1248     /**
1249      * Hints for the autofill services that describes the content of the view.
1250      */
1251     private @Nullable String[] mAutofillHints;
1252 
1253     /**
1254      * Autofill id, lazily created on calls to {@link #getAutofillId()}.
1255      */
1256     private AutofillId mAutofillId;
1257 
1258     /** @hide */
1259     @IntDef(prefix = { "AUTOFILL_TYPE_" }, value = {
1260             AUTOFILL_TYPE_NONE,
1261             AUTOFILL_TYPE_TEXT,
1262             AUTOFILL_TYPE_TOGGLE,
1263             AUTOFILL_TYPE_LIST,
1264             AUTOFILL_TYPE_DATE
1265     })
1266     @Retention(RetentionPolicy.SOURCE)
1267     public @interface AutofillType {}
1268 
1269     /**
1270      * Autofill type for views that cannot be autofilled.
1271      *
1272      * <p>Typically used when the view is read-only; for example, a text label.
1273      *
1274      * @see #getAutofillType()
1275      */
1276     public static final int AUTOFILL_TYPE_NONE = 0;
1277 
1278     /**
1279      * Autofill type for a text field, which is filled by a {@link CharSequence}.
1280      *
1281      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1282      * {@link AutofillValue#forText(CharSequence)}, and the value passed to autofill a
1283      * {@link View} can be fetched through {@link AutofillValue#getTextValue()}.
1284      *
1285      * @see #getAutofillType()
1286      */
1287     public static final int AUTOFILL_TYPE_TEXT = 1;
1288 
1289     /**
1290      * Autofill type for a togglable field, which is filled by a {@code boolean}.
1291      *
1292      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1293      * {@link AutofillValue#forToggle(boolean)}, and the value passed to autofill a
1294      * {@link View} can be fetched through {@link AutofillValue#getToggleValue()}.
1295      *
1296      * @see #getAutofillType()
1297      */
1298     public static final int AUTOFILL_TYPE_TOGGLE = 2;
1299 
1300     /**
1301      * Autofill type for a selection list field, which is filled by an {@code int}
1302      * representing the element index inside the list (starting at {@code 0}).
1303      *
1304      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1305      * {@link AutofillValue#forList(int)}, and the value passed to autofill a
1306      * {@link View} can be fetched through {@link AutofillValue#getListValue()}.
1307      *
1308      * <p>The available options in the selection list are typically provided by
1309      * {@link android.app.assist.AssistStructure.ViewNode#getAutofillOptions()}.
1310      *
1311      * @see #getAutofillType()
1312      */
1313     public static final int AUTOFILL_TYPE_LIST = 3;
1314 
1315 
1316     /**
1317      * Autofill type for a field that contains a date, which is represented by a long representing
1318      * the number of milliseconds since the standard base time known as "the epoch", namely
1319      * January 1, 1970, 00:00:00 GMT (see {@link java.util.Date#getTime()}.
1320      *
1321      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1322      * {@link AutofillValue#forDate(long)}, and the values passed to
1323      * autofill a {@link View} can be fetched through {@link AutofillValue#getDateValue()}.
1324      *
1325      * @see #getAutofillType()
1326      */
1327     public static final int AUTOFILL_TYPE_DATE = 4;
1328 
1329     /** @hide */
1330     @IntDef(prefix = { "IMPORTANT_FOR_AUTOFILL_" }, value = {
1331             IMPORTANT_FOR_AUTOFILL_AUTO,
1332             IMPORTANT_FOR_AUTOFILL_YES,
1333             IMPORTANT_FOR_AUTOFILL_NO,
1334             IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
1335             IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
1336     })
1337     @Retention(RetentionPolicy.SOURCE)
1338     public @interface AutofillImportance {}
1339 
1340     /**
1341      * Automatically determine whether a view is important for autofill.
1342      *
1343      * @see #isImportantForAutofill()
1344      * @see #setImportantForAutofill(int)
1345      */
1346     public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0x0;
1347 
1348     /**
1349      * The view is important for autofill, and its children (if any) will be traversed.
1350      *
1351      * @see #isImportantForAutofill()
1352      * @see #setImportantForAutofill(int)
1353      */
1354     public static final int IMPORTANT_FOR_AUTOFILL_YES = 0x1;
1355 
1356     /**
1357      * The view is not important for autofill, but its children (if any) will be traversed.
1358      *
1359      * @see #isImportantForAutofill()
1360      * @see #setImportantForAutofill(int)
1361      */
1362     public static final int IMPORTANT_FOR_AUTOFILL_NO = 0x2;
1363 
1364     /**
1365      * The view is important for autofill, but its children (if any) will not be traversed.
1366      *
1367      * @see #isImportantForAutofill()
1368      * @see #setImportantForAutofill(int)
1369      */
1370     public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 0x4;
1371 
1372     /**
1373      * The view is not important for autofill, and its children (if any) will not be traversed.
1374      *
1375      * @see #isImportantForAutofill()
1376      * @see #setImportantForAutofill(int)
1377      */
1378     public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 0x8;
1379 
1380     /** @hide */
1381     @IntDef(flag = true, prefix = { "AUTOFILL_FLAG_" }, value = {
1382             AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
1383     })
1384     @Retention(RetentionPolicy.SOURCE)
1385     public @interface AutofillFlags {}
1386 
1387     /**
1388      * Flag requesting you to add views that are marked as not important for autofill
1389      * (see {@link #setImportantForAutofill(int)}) to a {@link ViewStructure}.
1390      */
1391     public static final int AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x1;
1392 
1393     /**
1394      * This view is enabled. Interpretation varies by subclass.
1395      * Use with ENABLED_MASK when calling setFlags.
1396      * {@hide}
1397      */
1398     static final int ENABLED = 0x00000000;
1399 
1400     /**
1401      * This view is disabled. Interpretation varies by subclass.
1402      * Use with ENABLED_MASK when calling setFlags.
1403      * {@hide}
1404      */
1405     static final int DISABLED = 0x00000020;
1406 
1407    /**
1408     * Mask for use with setFlags indicating bits used for indicating whether
1409     * this view is enabled
1410     * {@hide}
1411     */
1412     static final int ENABLED_MASK = 0x00000020;
1413 
1414     /**
1415      * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
1416      * called and further optimizations will be performed. It is okay to have
1417      * this flag set and a background. Use with DRAW_MASK when calling setFlags.
1418      * {@hide}
1419      */
1420     static final int WILL_NOT_DRAW = 0x00000080;
1421 
1422     /**
1423      * Mask for use with setFlags indicating bits used for indicating whether
1424      * this view is will draw
1425      * {@hide}
1426      */
1427     static final int DRAW_MASK = 0x00000080;
1428 
1429     /**
1430      * <p>This view doesn't show scrollbars.</p>
1431      * {@hide}
1432      */
1433     static final int SCROLLBARS_NONE = 0x00000000;
1434 
1435     /**
1436      * <p>This view shows horizontal scrollbars.</p>
1437      * {@hide}
1438      */
1439     static final int SCROLLBARS_HORIZONTAL = 0x00000100;
1440 
1441     /**
1442      * <p>This view shows vertical scrollbars.</p>
1443      * {@hide}
1444      */
1445     static final int SCROLLBARS_VERTICAL = 0x00000200;
1446 
1447     /**
1448      * <p>Mask for use with setFlags indicating bits used for indicating which
1449      * scrollbars are enabled.</p>
1450      * {@hide}
1451      */
1452     static final int SCROLLBARS_MASK = 0x00000300;
1453 
1454     /**
1455      * Indicates that the view should filter touches when its window is obscured.
1456      * Refer to the class comments for more information about this security feature.
1457      * {@hide}
1458      */
1459     static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
1460 
1461     /**
1462      * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
1463      * that they are optional and should be skipped if the window has
1464      * requested system UI flags that ignore those insets for layout.
1465      */
1466     static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
1467 
1468     /**
1469      * <p>This view doesn't show fading edges.</p>
1470      * {@hide}
1471      */
1472     static final int FADING_EDGE_NONE = 0x00000000;
1473 
1474     /**
1475      * <p>This view shows horizontal fading edges.</p>
1476      * {@hide}
1477      */
1478     static final int FADING_EDGE_HORIZONTAL = 0x00001000;
1479 
1480     /**
1481      * <p>This view shows vertical fading edges.</p>
1482      * {@hide}
1483      */
1484     static final int FADING_EDGE_VERTICAL = 0x00002000;
1485 
1486     /**
1487      * <p>Mask for use with setFlags indicating bits used for indicating which
1488      * fading edges are enabled.</p>
1489      * {@hide}
1490      */
1491     static final int FADING_EDGE_MASK = 0x00003000;
1492 
1493     /**
1494      * <p>Indicates this view can be clicked. When clickable, a View reacts
1495      * to clicks by notifying the OnClickListener.<p>
1496      * {@hide}
1497      */
1498     static final int CLICKABLE = 0x00004000;
1499 
1500     /**
1501      * <p>Indicates this view is caching its drawing into a bitmap.</p>
1502      * {@hide}
1503      */
1504     static final int DRAWING_CACHE_ENABLED = 0x00008000;
1505 
1506     /**
1507      * <p>Indicates that no icicle should be saved for this view.<p>
1508      * {@hide}
1509      */
1510     static final int SAVE_DISABLED = 0x000010000;
1511 
1512     /**
1513      * <p>Mask for use with setFlags indicating bits used for the saveEnabled
1514      * property.</p>
1515      * {@hide}
1516      */
1517     static final int SAVE_DISABLED_MASK = 0x000010000;
1518 
1519     /**
1520      * <p>Indicates that no drawing cache should ever be created for this view.<p>
1521      * {@hide}
1522      */
1523     static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
1524 
1525     /**
1526      * <p>Indicates this view can take / keep focus when int touch mode.</p>
1527      * {@hide}
1528      */
1529     static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
1530 
1531     /** @hide */
1532     @Retention(RetentionPolicy.SOURCE)
1533     @IntDef(prefix = { "DRAWING_CACHE_QUALITY_" }, value = {
1534             DRAWING_CACHE_QUALITY_LOW,
1535             DRAWING_CACHE_QUALITY_HIGH,
1536             DRAWING_CACHE_QUALITY_AUTO
1537     })
1538     public @interface DrawingCacheQuality {}
1539 
1540     /**
1541      * <p>Enables low quality mode for the drawing cache.</p>
1542      *
1543      * @deprecated The view drawing cache was largely made obsolete with the introduction of
1544      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
1545      * layers are largely unnecessary and can easily result in a net loss in performance due to the
1546      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
1547      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
1548      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
1549      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
1550      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
1551      * software-rendered usages are discouraged and have compatibility issues with hardware-only
1552      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
1553      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
1554      * reports or unit testing the {@link PixelCopy} API is recommended.
1555      */
1556     @Deprecated
1557     public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
1558 
1559     /**
1560      * <p>Enables high quality mode for the drawing cache.</p>
1561      *
1562      * @deprecated The view drawing cache was largely made obsolete with the introduction of
1563      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
1564      * layers are largely unnecessary and can easily result in a net loss in performance due to the
1565      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
1566      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
1567      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
1568      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
1569      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
1570      * software-rendered usages are discouraged and have compatibility issues with hardware-only
1571      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
1572      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
1573      * reports or unit testing the {@link PixelCopy} API is recommended.
1574      */
1575     @Deprecated
1576     public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
1577 
1578     /**
1579      * <p>Enables automatic quality mode for the drawing cache.</p>
1580      *
1581      * @deprecated The view drawing cache was largely made obsolete with the introduction of
1582      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
1583      * layers are largely unnecessary and can easily result in a net loss in performance due to the
1584      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
1585      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
1586      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
1587      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
1588      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
1589      * software-rendered usages are discouraged and have compatibility issues with hardware-only
1590      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
1591      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
1592      * reports or unit testing the {@link PixelCopy} API is recommended.
1593      */
1594     @Deprecated
1595     public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
1596 
1597     private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
1598             DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
1599     };
1600 
1601     /**
1602      * <p>Mask for use with setFlags indicating bits used for the cache
1603      * quality property.</p>
1604      * {@hide}
1605      */
1606     static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
1607 
1608     /**
1609      * <p>
1610      * Indicates this view can be long clicked. When long clickable, a View
1611      * reacts to long clicks by notifying the OnLongClickListener or showing a
1612      * context menu.
1613      * </p>
1614      * {@hide}
1615      */
1616     static final int LONG_CLICKABLE = 0x00200000;
1617 
1618     /**
1619      * <p>Indicates that this view gets its drawable states from its direct parent
1620      * and ignores its original internal states.</p>
1621      *
1622      * @hide
1623      */
1624     static final int DUPLICATE_PARENT_STATE = 0x00400000;
1625 
1626     /**
1627      * <p>
1628      * Indicates this view can be context clicked. When context clickable, a View reacts to a
1629      * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1630      * OnContextClickListener.
1631      * </p>
1632      * {@hide}
1633      */
1634     static final int CONTEXT_CLICKABLE = 0x00800000;
1635 
1636     /** @hide */
1637     @IntDef(prefix = { "SCROLLBARS_" }, value = {
1638             SCROLLBARS_INSIDE_OVERLAY,
1639             SCROLLBARS_INSIDE_INSET,
1640             SCROLLBARS_OUTSIDE_OVERLAY,
1641             SCROLLBARS_OUTSIDE_INSET
1642     })
1643     @Retention(RetentionPolicy.SOURCE)
1644     public @interface ScrollBarStyle {}
1645 
1646     /**
1647      * The scrollbar style to display the scrollbars inside the content area,
1648      * without increasing the padding. The scrollbars will be overlaid with
1649      * translucency on the view's content.
1650      */
1651     public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1652 
1653     /**
1654      * The scrollbar style to display the scrollbars inside the padded area,
1655      * increasing the padding of the view. The scrollbars will not overlap the
1656      * content area of the view.
1657      */
1658     public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1659 
1660     /**
1661      * The scrollbar style to display the scrollbars at the edge of the view,
1662      * without increasing the padding. The scrollbars will be overlaid with
1663      * translucency.
1664      */
1665     public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1666 
1667     /**
1668      * The scrollbar style to display the scrollbars at the edge of the view,
1669      * increasing the padding of the view. The scrollbars will only overlap the
1670      * background, if any.
1671      */
1672     public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1673 
1674     /**
1675      * Mask to check if the scrollbar style is overlay or inset.
1676      * {@hide}
1677      */
1678     static final int SCROLLBARS_INSET_MASK = 0x01000000;
1679 
1680     /**
1681      * Mask to check if the scrollbar style is inside or outside.
1682      * {@hide}
1683      */
1684     static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1685 
1686     /**
1687      * Mask for scrollbar style.
1688      * {@hide}
1689      */
1690     static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1691 
1692     /**
1693      * View flag indicating that the screen should remain on while the
1694      * window containing this view is visible to the user.  This effectively
1695      * takes care of automatically setting the WindowManager's
1696      * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1697      */
1698     public static final int KEEP_SCREEN_ON = 0x04000000;
1699 
1700     /**
1701      * View flag indicating whether this view should have sound effects enabled
1702      * for events such as clicking and touching.
1703      */
1704     public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1705 
1706     /**
1707      * View flag indicating whether this view should have haptic feedback
1708      * enabled for events such as long presses.
1709      */
1710     public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1711 
1712     /**
1713      * <p>Indicates that the view hierarchy should stop saving state when
1714      * it reaches this view.  If state saving is initiated immediately at
1715      * the view, it will be allowed.
1716      * {@hide}
1717      */
1718     static final int PARENT_SAVE_DISABLED = 0x20000000;
1719 
1720     /**
1721      * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1722      * {@hide}
1723      */
1724     static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1725 
1726     private static Paint sDebugPaint;
1727 
1728     /**
1729      * <p>Indicates this view can display a tooltip on hover or long press.</p>
1730      * {@hide}
1731      */
1732     static final int TOOLTIP = 0x40000000;
1733 
1734     /** @hide */
1735     @IntDef(flag = true, prefix = { "FOCUSABLES_" }, value = {
1736             FOCUSABLES_ALL,
1737             FOCUSABLES_TOUCH_MODE
1738     })
1739     @Retention(RetentionPolicy.SOURCE)
1740     public @interface FocusableMode {}
1741 
1742     /**
1743      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1744      * should add all focusable Views regardless if they are focusable in touch mode.
1745      */
1746     public static final int FOCUSABLES_ALL = 0x00000000;
1747 
1748     /**
1749      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1750      * should add only Views focusable in touch mode.
1751      */
1752     public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1753 
1754     /** @hide */
1755     @IntDef(prefix = { "FOCUS_" }, value = {
1756             FOCUS_BACKWARD,
1757             FOCUS_FORWARD,
1758             FOCUS_LEFT,
1759             FOCUS_UP,
1760             FOCUS_RIGHT,
1761             FOCUS_DOWN
1762     })
1763     @Retention(RetentionPolicy.SOURCE)
1764     public @interface FocusDirection {}
1765 
1766     /** @hide */
1767     @IntDef(prefix = { "FOCUS_" }, value = {
1768             FOCUS_LEFT,
1769             FOCUS_UP,
1770             FOCUS_RIGHT,
1771             FOCUS_DOWN
1772     })
1773     @Retention(RetentionPolicy.SOURCE)
1774     public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1775 
1776     /**
1777      * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1778      * item.
1779      */
1780     public static final int FOCUS_BACKWARD = 0x00000001;
1781 
1782     /**
1783      * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1784      * item.
1785      */
1786     public static final int FOCUS_FORWARD = 0x00000002;
1787 
1788     /**
1789      * Use with {@link #focusSearch(int)}. Move focus to the left.
1790      */
1791     public static final int FOCUS_LEFT = 0x00000011;
1792 
1793     /**
1794      * Use with {@link #focusSearch(int)}. Move focus up.
1795      */
1796     public static final int FOCUS_UP = 0x00000021;
1797 
1798     /**
1799      * Use with {@link #focusSearch(int)}. Move focus to the right.
1800      */
1801     public static final int FOCUS_RIGHT = 0x00000042;
1802 
1803     /**
1804      * Use with {@link #focusSearch(int)}. Move focus down.
1805      */
1806     public static final int FOCUS_DOWN = 0x00000082;
1807 
1808     /**
1809      * Bits of {@link #getMeasuredWidthAndState()} and
1810      * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1811      */
1812     public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1813 
1814     /**
1815      * Bits of {@link #getMeasuredWidthAndState()} and
1816      * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1817      */
1818     public static final int MEASURED_STATE_MASK = 0xff000000;
1819 
1820     /**
1821      * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1822      * for functions that combine both width and height into a single int,
1823      * such as {@link #getMeasuredState()} and the childState argument of
1824      * {@link #resolveSizeAndState(int, int, int)}.
1825      */
1826     public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1827 
1828     /**
1829      * Bit of {@link #getMeasuredWidthAndState()} and
1830      * {@link #getMeasuredWidthAndState()} that indicates the measured size
1831      * is smaller that the space the view would like to have.
1832      */
1833     public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1834 
1835     /**
1836      * Base View state sets
1837      */
1838     // Singles
1839     /**
1840      * Indicates the view has no states set. States are used with
1841      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1842      * view depending on its state.
1843      *
1844      * @see android.graphics.drawable.Drawable
1845      * @see #getDrawableState()
1846      */
1847     protected static final int[] EMPTY_STATE_SET;
1848     /**
1849      * Indicates the view is enabled. States are used with
1850      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1851      * view depending on its state.
1852      *
1853      * @see android.graphics.drawable.Drawable
1854      * @see #getDrawableState()
1855      */
1856     protected static final int[] ENABLED_STATE_SET;
1857     /**
1858      * Indicates the view is focused. States are used with
1859      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1860      * view depending on its state.
1861      *
1862      * @see android.graphics.drawable.Drawable
1863      * @see #getDrawableState()
1864      */
1865     protected static final int[] FOCUSED_STATE_SET;
1866     /**
1867      * Indicates the view is selected. States are used with
1868      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1869      * view depending on its state.
1870      *
1871      * @see android.graphics.drawable.Drawable
1872      * @see #getDrawableState()
1873      */
1874     protected static final int[] SELECTED_STATE_SET;
1875     /**
1876      * Indicates the view is pressed. States are used with
1877      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1878      * view depending on its state.
1879      *
1880      * @see android.graphics.drawable.Drawable
1881      * @see #getDrawableState()
1882      */
1883     protected static final int[] PRESSED_STATE_SET;
1884     /**
1885      * Indicates the view's window has focus. States are used with
1886      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1887      * view depending on its state.
1888      *
1889      * @see android.graphics.drawable.Drawable
1890      * @see #getDrawableState()
1891      */
1892     protected static final int[] WINDOW_FOCUSED_STATE_SET;
1893     // Doubles
1894     /**
1895      * Indicates the view is enabled and has the focus.
1896      *
1897      * @see #ENABLED_STATE_SET
1898      * @see #FOCUSED_STATE_SET
1899      */
1900     protected static final int[] ENABLED_FOCUSED_STATE_SET;
1901     /**
1902      * Indicates the view is enabled and selected.
1903      *
1904      * @see #ENABLED_STATE_SET
1905      * @see #SELECTED_STATE_SET
1906      */
1907     protected static final int[] ENABLED_SELECTED_STATE_SET;
1908     /**
1909      * Indicates the view is enabled and that its window has focus.
1910      *
1911      * @see #ENABLED_STATE_SET
1912      * @see #WINDOW_FOCUSED_STATE_SET
1913      */
1914     protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1915     /**
1916      * Indicates the view is focused and selected.
1917      *
1918      * @see #FOCUSED_STATE_SET
1919      * @see #SELECTED_STATE_SET
1920      */
1921     protected static final int[] FOCUSED_SELECTED_STATE_SET;
1922     /**
1923      * Indicates the view has the focus and that its window has the focus.
1924      *
1925      * @see #FOCUSED_STATE_SET
1926      * @see #WINDOW_FOCUSED_STATE_SET
1927      */
1928     protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1929     /**
1930      * Indicates the view is selected and that its window has the focus.
1931      *
1932      * @see #SELECTED_STATE_SET
1933      * @see #WINDOW_FOCUSED_STATE_SET
1934      */
1935     protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1936     // Triples
1937     /**
1938      * Indicates the view is enabled, focused and selected.
1939      *
1940      * @see #ENABLED_STATE_SET
1941      * @see #FOCUSED_STATE_SET
1942      * @see #SELECTED_STATE_SET
1943      */
1944     protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1945     /**
1946      * Indicates the view is enabled, focused and its window has the focus.
1947      *
1948      * @see #ENABLED_STATE_SET
1949      * @see #FOCUSED_STATE_SET
1950      * @see #WINDOW_FOCUSED_STATE_SET
1951      */
1952     protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1953     /**
1954      * Indicates the view is enabled, selected and its window has the focus.
1955      *
1956      * @see #ENABLED_STATE_SET
1957      * @see #SELECTED_STATE_SET
1958      * @see #WINDOW_FOCUSED_STATE_SET
1959      */
1960     protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1961     /**
1962      * Indicates the view is focused, selected and its window has the focus.
1963      *
1964      * @see #FOCUSED_STATE_SET
1965      * @see #SELECTED_STATE_SET
1966      * @see #WINDOW_FOCUSED_STATE_SET
1967      */
1968     protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1969     /**
1970      * Indicates the view is enabled, focused, selected and its window
1971      * has the focus.
1972      *
1973      * @see #ENABLED_STATE_SET
1974      * @see #FOCUSED_STATE_SET
1975      * @see #SELECTED_STATE_SET
1976      * @see #WINDOW_FOCUSED_STATE_SET
1977      */
1978     protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1979     /**
1980      * Indicates the view is pressed and its window has the focus.
1981      *
1982      * @see #PRESSED_STATE_SET
1983      * @see #WINDOW_FOCUSED_STATE_SET
1984      */
1985     protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1986     /**
1987      * Indicates the view is pressed and selected.
1988      *
1989      * @see #PRESSED_STATE_SET
1990      * @see #SELECTED_STATE_SET
1991      */
1992     protected static final int[] PRESSED_SELECTED_STATE_SET;
1993     /**
1994      * Indicates the view is pressed, selected and its window has the focus.
1995      *
1996      * @see #PRESSED_STATE_SET
1997      * @see #SELECTED_STATE_SET
1998      * @see #WINDOW_FOCUSED_STATE_SET
1999      */
2000     protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2001     /**
2002      * Indicates the view is pressed and focused.
2003      *
2004      * @see #PRESSED_STATE_SET
2005      * @see #FOCUSED_STATE_SET
2006      */
2007     protected static final int[] PRESSED_FOCUSED_STATE_SET;
2008     /**
2009      * Indicates the view is pressed, focused and its window has the focus.
2010      *
2011      * @see #PRESSED_STATE_SET
2012      * @see #FOCUSED_STATE_SET
2013      * @see #WINDOW_FOCUSED_STATE_SET
2014      */
2015     protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
2016     /**
2017      * Indicates the view is pressed, focused and selected.
2018      *
2019      * @see #PRESSED_STATE_SET
2020      * @see #SELECTED_STATE_SET
2021      * @see #FOCUSED_STATE_SET
2022      */
2023     protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
2024     /**
2025      * Indicates the view is pressed, focused, selected and its window has the focus.
2026      *
2027      * @see #PRESSED_STATE_SET
2028      * @see #FOCUSED_STATE_SET
2029      * @see #SELECTED_STATE_SET
2030      * @see #WINDOW_FOCUSED_STATE_SET
2031      */
2032     protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2033     /**
2034      * Indicates the view is pressed and enabled.
2035      *
2036      * @see #PRESSED_STATE_SET
2037      * @see #ENABLED_STATE_SET
2038      */
2039     protected static final int[] PRESSED_ENABLED_STATE_SET;
2040     /**
2041      * Indicates the view is pressed, enabled and its window has the focus.
2042      *
2043      * @see #PRESSED_STATE_SET
2044      * @see #ENABLED_STATE_SET
2045      * @see #WINDOW_FOCUSED_STATE_SET
2046      */
2047     protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
2048     /**
2049      * Indicates the view is pressed, enabled and selected.
2050      *
2051      * @see #PRESSED_STATE_SET
2052      * @see #ENABLED_STATE_SET
2053      * @see #SELECTED_STATE_SET
2054      */
2055     protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
2056     /**
2057      * Indicates the view is pressed, enabled, selected and its window has the
2058      * focus.
2059      *
2060      * @see #PRESSED_STATE_SET
2061      * @see #ENABLED_STATE_SET
2062      * @see #SELECTED_STATE_SET
2063      * @see #WINDOW_FOCUSED_STATE_SET
2064      */
2065     protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2066     /**
2067      * Indicates the view is pressed, enabled and focused.
2068      *
2069      * @see #PRESSED_STATE_SET
2070      * @see #ENABLED_STATE_SET
2071      * @see #FOCUSED_STATE_SET
2072      */
2073     protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
2074     /**
2075      * Indicates the view is pressed, enabled, focused and its window has the
2076      * focus.
2077      *
2078      * @see #PRESSED_STATE_SET
2079      * @see #ENABLED_STATE_SET
2080      * @see #FOCUSED_STATE_SET
2081      * @see #WINDOW_FOCUSED_STATE_SET
2082      */
2083     protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
2084     /**
2085      * Indicates the view is pressed, enabled, focused and selected.
2086      *
2087      * @see #PRESSED_STATE_SET
2088      * @see #ENABLED_STATE_SET
2089      * @see #SELECTED_STATE_SET
2090      * @see #FOCUSED_STATE_SET
2091      */
2092     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
2093     /**
2094      * Indicates the view is pressed, enabled, focused, selected and its window
2095      * has the focus.
2096      *
2097      * @see #PRESSED_STATE_SET
2098      * @see #ENABLED_STATE_SET
2099      * @see #SELECTED_STATE_SET
2100      * @see #FOCUSED_STATE_SET
2101      * @see #WINDOW_FOCUSED_STATE_SET
2102      */
2103     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2104 
2105     static {
2106         EMPTY_STATE_SET = StateSet.get(0);
2107 
2108         WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
2109 
2110         SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
2111         SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2112                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
2113 
2114         FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
2115         FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2116                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
2117         FOCUSED_SELECTED_STATE_SET = StateSet.get(
2118                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
2119         FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2120                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2121                         | StateSet.VIEW_STATE_FOCUSED);
2122 
2123         ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
2124         ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2125                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
2126         ENABLED_SELECTED_STATE_SET = StateSet.get(
2127                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
2128         ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2129                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2130                         | StateSet.VIEW_STATE_ENABLED);
2131         ENABLED_FOCUSED_STATE_SET = StateSet.get(
2132                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
2133         ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2134                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2135                         | StateSet.VIEW_STATE_ENABLED);
2136         ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2137                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2138                         | StateSet.VIEW_STATE_ENABLED);
2139         ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2140                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2141                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
2142 
2143         PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
2144         PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2145                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
2146         PRESSED_SELECTED_STATE_SET = StateSet.get(
2147                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
2148         PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2149                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2150                         | StateSet.VIEW_STATE_PRESSED);
2151         PRESSED_FOCUSED_STATE_SET = StateSet.get(
2152                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
2153         PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2154                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2155                         | StateSet.VIEW_STATE_PRESSED);
2156         PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2157                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2158                         | StateSet.VIEW_STATE_PRESSED);
2159         PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2160                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2161                         | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
2162         PRESSED_ENABLED_STATE_SET = StateSet.get(
2163                 StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2164         PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2165                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
2166                         | StateSet.VIEW_STATE_PRESSED);
2167         PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
2168                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
2169                         | StateSet.VIEW_STATE_PRESSED);
2170         PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2171                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2172                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2173         PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
2174                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
2175                         | StateSet.VIEW_STATE_PRESSED);
2176         PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2177                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2178                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2179         PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2180                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2181                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2182         PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2183                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2184                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
2185                         | StateSet.VIEW_STATE_PRESSED);
2186     }
2187 
2188     /**
2189      * Accessibility event types that are dispatched for text population.
2190      */
2191     private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
2192             AccessibilityEvent.TYPE_VIEW_CLICKED
2193             | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
2194             | AccessibilityEvent.TYPE_VIEW_SELECTED
2195             | AccessibilityEvent.TYPE_VIEW_FOCUSED
2196             | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
2197             | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
2198             | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
2199             | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
2200             | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
2201             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
2202             | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
2203 
2204     static final int DEBUG_CORNERS_COLOR = Color.rgb(63, 127, 255);
2205 
2206     static final int DEBUG_CORNERS_SIZE_DIP = 8;
2207 
2208     /**
2209      * Temporary Rect currently for use in setBackground().  This will probably
2210      * be extended in the future to hold our own class with more than just
2211      * a Rect. :)
2212      */
2213     static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
2214 
2215     /**
2216      * Map used to store views' tags.
2217      */
2218     @UnsupportedAppUsage
2219     private SparseArray<Object> mKeyedTags;
2220 
2221     /**
2222      * The next available accessibility id.
2223      */
2224     private static int sNextAccessibilityViewId;
2225 
2226     /**
2227      * The animation currently associated with this view.
2228      * @hide
2229      */
2230     protected Animation mCurrentAnimation = null;
2231 
2232     /**
2233      * Width as measured during measure pass.
2234      * {@hide}
2235      */
2236     @ViewDebug.ExportedProperty(category = "measurement")
2237     @UnsupportedAppUsage
2238     int mMeasuredWidth;
2239 
2240     /**
2241      * Height as measured during measure pass.
2242      * {@hide}
2243      */
2244     @ViewDebug.ExportedProperty(category = "measurement")
2245     @UnsupportedAppUsage
2246     int mMeasuredHeight;
2247 
2248     /**
2249      * Flag to indicate that this view was marked INVALIDATED, or had its display list
2250      * invalidated, prior to the current drawing iteration. If true, the view must re-draw
2251      * its display list. This flag, used only when hw accelerated, allows us to clear the
2252      * flag while retaining this information until it's needed (at getDisplayList() time and
2253      * in drawChild(), when we decide to draw a view's children's display lists into our own).
2254      *
2255      * {@hide}
2256      */
2257     @UnsupportedAppUsage
2258     boolean mRecreateDisplayList = false;
2259 
2260     /**
2261      * The view's identifier.
2262      * {@hide}
2263      *
2264      * @see #setId(int)
2265      * @see #getId()
2266      */
2267     @IdRes
2268     @ViewDebug.ExportedProperty(resolveId = true)
2269     int mID = NO_ID;
2270 
2271     /** The ID of this view for autofill purposes.
2272      * <ul>
2273      *     <li>== {@link #NO_ID}: ID has not been assigned yet
2274      *     <li>&le; {@link #LAST_APP_AUTOFILL_ID}: View is not part of a activity. The ID is
2275      *                                                  unique in the process. This might change
2276      *                                                  over activity lifecycle events.
2277      *     <li>&gt; {@link #LAST_APP_AUTOFILL_ID}: View is part of a activity. The ID is
2278      *                                                  unique in the activity. This stays the same
2279      *                                                  over activity lifecycle events.
2280      */
2281     private int mAutofillViewId = NO_ID;
2282 
2283     // ID for accessibility purposes. This ID must be unique for every window
2284     @UnsupportedAppUsage
2285     private int mAccessibilityViewId = NO_ID;
2286 
2287     private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
2288 
2289     /**
2290      * The view's tag.
2291      * {@hide}
2292      *
2293      * @see #setTag(Object)
2294      * @see #getTag()
2295      */
2296     @UnsupportedAppUsage
2297     protected Object mTag = null;
2298 
2299     /*
2300      * Masks for mPrivateFlags, as generated by dumpFlags():
2301      *
2302      * |-------|-------|-------|-------|
2303      *                                 1 PFLAG_WANTS_FOCUS
2304      *                                1  PFLAG_FOCUSED
2305      *                               1   PFLAG_SELECTED
2306      *                              1    PFLAG_IS_ROOT_NAMESPACE
2307      *                             1     PFLAG_HAS_BOUNDS
2308      *                            1      PFLAG_DRAWN
2309      *                           1       PFLAG_DRAW_ANIMATION
2310      *                          1        PFLAG_SKIP_DRAW
2311      *                        1          PFLAG_REQUEST_TRANSPARENT_REGIONS
2312      *                       1           PFLAG_DRAWABLE_STATE_DIRTY
2313      *                      1            PFLAG_MEASURED_DIMENSION_SET
2314      *                     1             PFLAG_FORCE_LAYOUT
2315      *                    1              PFLAG_LAYOUT_REQUIRED
2316      *                   1               PFLAG_PRESSED
2317      *                  1                PFLAG_DRAWING_CACHE_VALID
2318      *                 1                 PFLAG_ANIMATION_STARTED
2319      *                1                  PFLAG_SAVE_STATE_CALLED
2320      *               1                   PFLAG_ALPHA_SET
2321      *              1                    PFLAG_SCROLL_CONTAINER
2322      *             1                     PFLAG_SCROLL_CONTAINER_ADDED
2323      *            1                      PFLAG_DIRTY
2324      *            1                      PFLAG_DIRTY_MASK
2325      *          1                        PFLAG_OPAQUE_BACKGROUND
2326      *         1                         PFLAG_OPAQUE_SCROLLBARS
2327      *         11                        PFLAG_OPAQUE_MASK
2328      *        1                          PFLAG_PREPRESSED
2329      *       1                           PFLAG_CANCEL_NEXT_UP_EVENT
2330      *      1                            PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH
2331      *     1                             PFLAG_HOVERED
2332      *    1                              PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK
2333      *   1                               PFLAG_ACTIVATED
2334      *  1                                PFLAG_INVALIDATED
2335      * |-------|-------|-------|-------|
2336      */
2337     /** {@hide} */
2338     static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
2339     /** {@hide} */
2340     static final int PFLAG_FOCUSED                     = 0x00000002;
2341     /** {@hide} */
2342     static final int PFLAG_SELECTED                    = 0x00000004;
2343     /** {@hide} */
2344     static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
2345     /** {@hide} */
2346     static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
2347     /** {@hide} */
2348     static final int PFLAG_DRAWN                       = 0x00000020;
2349     /**
2350      * When this flag is set, this view is running an animation on behalf of its
2351      * children and should therefore not cancel invalidate requests, even if they
2352      * lie outside of this view's bounds.
2353      *
2354      * {@hide}
2355      */
2356     static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
2357     /** {@hide} */
2358     static final int PFLAG_SKIP_DRAW                   = 0x00000080;
2359     /** {@hide} */
2360     static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
2361     /** {@hide} */
2362     static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
2363     /** {@hide} */
2364     static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
2365     /** {@hide} */
2366     static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
2367     /** {@hide} */
2368     static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
2369 
2370     private static final int PFLAG_PRESSED             = 0x00004000;
2371 
2372     /** {@hide} */
2373     static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
2374     /**
2375      * Flag used to indicate that this view should be drawn once more (and only once
2376      * more) after its animation has completed.
2377      * {@hide}
2378      */
2379     static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
2380 
2381     private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
2382 
2383     /**
2384      * Indicates that the View returned true when onSetAlpha() was called and that
2385      * the alpha must be restored.
2386      * {@hide}
2387      */
2388     static final int PFLAG_ALPHA_SET                   = 0x00040000;
2389 
2390     /**
2391      * Set by {@link #setScrollContainer(boolean)}.
2392      */
2393     static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
2394 
2395     /**
2396      * Set by {@link #setScrollContainer(boolean)}.
2397      */
2398     static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
2399 
2400     /**
2401      * View flag indicating whether this view was invalidated (fully or partially.)
2402      *
2403      * @hide
2404      */
2405     static final int PFLAG_DIRTY                       = 0x00200000;
2406 
2407     /**
2408      * Mask for {@link #PFLAG_DIRTY}.
2409      *
2410      * @hide
2411      */
2412     static final int PFLAG_DIRTY_MASK                  = 0x00200000;
2413 
2414     /**
2415      * Indicates whether the background is opaque.
2416      *
2417      * @hide
2418      */
2419     static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
2420 
2421     /**
2422      * Indicates whether the scrollbars are opaque.
2423      *
2424      * @hide
2425      */
2426     static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
2427 
2428     /**
2429      * Indicates whether the view is opaque.
2430      *
2431      * @hide
2432      */
2433     static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
2434 
2435     /**
2436      * Indicates a prepressed state;
2437      * the short time between ACTION_DOWN and recognizing
2438      * a 'real' press. Prepressed is used to recognize quick taps
2439      * even when they are shorter than ViewConfiguration.getTapTimeout().
2440      *
2441      * @hide
2442      */
2443     private static final int PFLAG_PREPRESSED          = 0x02000000;
2444 
2445     /**
2446      * Indicates whether the view is temporarily detached.
2447      *
2448      * @hide
2449      */
2450     static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
2451 
2452     /**
2453      * Indicates that we should awaken scroll bars once attached
2454      *
2455      * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
2456      * during window attachment and it is no longer needed. Feel free to repurpose it.
2457      *
2458      * @hide
2459      */
2460     private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
2461 
2462     /**
2463      * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
2464      * @hide
2465      */
2466     private static final int PFLAG_HOVERED             = 0x10000000;
2467 
2468     /**
2469      * Flag set by {@link AutofillManager} if it needs to be notified when this view is clicked.
2470      */
2471     private static final int PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK = 0x20000000;
2472 
2473     /** {@hide} */
2474     static final int PFLAG_ACTIVATED                   = 0x40000000;
2475 
2476     /**
2477      * Indicates that this view was specifically invalidated, not just dirtied because some
2478      * child view was invalidated. The flag is used to determine when we need to recreate
2479      * a view's display list (as opposed to just returning a reference to its existing
2480      * display list).
2481      *
2482      * @hide
2483      */
2484     static final int PFLAG_INVALIDATED                 = 0x80000000;
2485 
2486     /* End of masks for mPrivateFlags */
2487 
2488     /*
2489      * Masks for mPrivateFlags2, as generated by dumpFlags():
2490      *
2491      * |-------|-------|-------|-------|
2492      *                                 1 PFLAG2_DRAG_CAN_ACCEPT
2493      *                                1  PFLAG2_DRAG_HOVERED
2494      *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
2495      *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
2496      *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
2497      *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
2498      *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
2499      *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
2500      *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
2501      *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
2502      *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
2503      *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
2504      *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
2505      *                         111       PFLAG2_TEXT_DIRECTION_MASK
2506      *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
2507      *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
2508      *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
2509      *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
2510      *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
2511      *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
2512      *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
2513      *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
2514      *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
2515      *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
2516      *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
2517      *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
2518      *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
2519      *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
2520      *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
2521      *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
2522      *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
2523      *     1                             PFLAG2_VIEW_QUICK_REJECTED
2524      *    1                              PFLAG2_PADDING_RESOLVED
2525      *   1                               PFLAG2_DRAWABLE_RESOLVED
2526      *  1                                PFLAG2_HAS_TRANSIENT_STATE
2527      * |-------|-------|-------|-------|
2528      */
2529 
2530     /**
2531      * Indicates that this view has reported that it can accept the current drag's content.
2532      * Cleared when the drag operation concludes.
2533      * @hide
2534      */
2535     static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
2536 
2537     /**
2538      * Indicates that this view is currently directly under the drag location in a
2539      * drag-and-drop operation involving content that it can accept.  Cleared when
2540      * the drag exits the view, or when the drag operation concludes.
2541      * @hide
2542      */
2543     static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
2544 
2545     /** @hide */
2546     @IntDef(prefix = { "LAYOUT_DIRECTION_" }, value = {
2547             LAYOUT_DIRECTION_LTR,
2548             LAYOUT_DIRECTION_RTL,
2549             LAYOUT_DIRECTION_INHERIT,
2550             LAYOUT_DIRECTION_LOCALE
2551     })
2552     @Retention(RetentionPolicy.SOURCE)
2553     // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
2554     public @interface LayoutDir {}
2555 
2556     /** @hide */
2557     @IntDef(prefix = { "LAYOUT_DIRECTION_" }, value = {
2558             LAYOUT_DIRECTION_LTR,
2559             LAYOUT_DIRECTION_RTL
2560     })
2561     @Retention(RetentionPolicy.SOURCE)
2562     public @interface ResolvedLayoutDir {}
2563 
2564     /**
2565      * A flag to indicate that the layout direction of this view has not been defined yet.
2566      * @hide
2567      */
2568     public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
2569 
2570     /**
2571      * Horizontal layout direction of this view is from Left to Right.
2572      * Use with {@link #setLayoutDirection}.
2573      */
2574     public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
2575 
2576     /**
2577      * Horizontal layout direction of this view is from Right to Left.
2578      * Use with {@link #setLayoutDirection}.
2579      */
2580     public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
2581 
2582     /**
2583      * Horizontal layout direction of this view is inherited from its parent.
2584      * Use with {@link #setLayoutDirection}.
2585      */
2586     public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
2587 
2588     /**
2589      * Horizontal layout direction of this view is from deduced from the default language
2590      * script for the locale. Use with {@link #setLayoutDirection}.
2591      */
2592     public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
2593 
2594     /**
2595      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2596      * @hide
2597      */
2598     static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
2599 
2600     /**
2601      * Mask for use with private flags indicating bits used for horizontal layout direction.
2602      * @hide
2603      */
2604     static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2605 
2606     /**
2607      * Indicates whether the view horizontal layout direction has been resolved and drawn to the
2608      * right-to-left direction.
2609      * @hide
2610      */
2611     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2612 
2613     /**
2614      * Indicates whether the view horizontal layout direction has been resolved.
2615      * @hide
2616      */
2617     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2618 
2619     /**
2620      * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
2621      * @hide
2622      */
2623     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
2624             << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2625 
2626     /*
2627      * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
2628      * flag value.
2629      * @hide
2630      */
2631     private static final int[] LAYOUT_DIRECTION_FLAGS = {
2632             LAYOUT_DIRECTION_LTR,
2633             LAYOUT_DIRECTION_RTL,
2634             LAYOUT_DIRECTION_INHERIT,
2635             LAYOUT_DIRECTION_LOCALE
2636     };
2637 
2638     /**
2639      * Default horizontal layout direction.
2640      */
2641     private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
2642 
2643     /**
2644      * Default horizontal layout direction.
2645      * @hide
2646      */
2647     static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
2648 
2649     /**
2650      * Text direction is inherited through {@link ViewGroup}
2651      */
2652     public static final int TEXT_DIRECTION_INHERIT = 0;
2653 
2654     /**
2655      * Text direction is using "first strong algorithm". The first strong directional character
2656      * determines the paragraph direction. If there is no strong directional character, the
2657      * paragraph direction is the view's resolved layout direction.
2658      */
2659     public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2660 
2661     /**
2662      * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2663      * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2664      * If there are neither, the paragraph direction is the view's resolved layout direction.
2665      */
2666     public static final int TEXT_DIRECTION_ANY_RTL = 2;
2667 
2668     /**
2669      * Text direction is forced to LTR.
2670      */
2671     public static final int TEXT_DIRECTION_LTR = 3;
2672 
2673     /**
2674      * Text direction is forced to RTL.
2675      */
2676     public static final int TEXT_DIRECTION_RTL = 4;
2677 
2678     /**
2679      * Text direction is coming from the system Locale.
2680      */
2681     public static final int TEXT_DIRECTION_LOCALE = 5;
2682 
2683     /**
2684      * Text direction is using "first strong algorithm". The first strong directional character
2685      * determines the paragraph direction. If there is no strong directional character, the
2686      * paragraph direction is LTR.
2687      */
2688     public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2689 
2690     /**
2691      * Text direction is using "first strong algorithm". The first strong directional character
2692      * determines the paragraph direction. If there is no strong directional character, the
2693      * paragraph direction is RTL.
2694      */
2695     public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2696 
2697     /**
2698      * Default text direction is inherited
2699      */
2700     private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2701 
2702     /**
2703      * Default resolved text direction
2704      * @hide
2705      */
2706     static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2707 
2708     /**
2709      * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2710      * @hide
2711      */
2712     static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2713 
2714     /**
2715      * Mask for use with private flags indicating bits used for text direction.
2716      * @hide
2717      */
2718     static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2719             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2720 
2721     /**
2722      * Array of text direction flags for mapping attribute "textDirection" to correct
2723      * flag value.
2724      * @hide
2725      */
2726     private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2727             TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2728             TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2729             TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2730             TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2731             TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2732             TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2733             TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2734             TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2735     };
2736 
2737     /**
2738      * Indicates whether the view text direction has been resolved.
2739      * @hide
2740      */
2741     static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2742             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2743 
2744     /**
2745      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2746      * @hide
2747      */
2748     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2749 
2750     /**
2751      * Mask for use with private flags indicating bits used for resolved text direction.
2752      * @hide
2753      */
2754     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2755             << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2756 
2757     /**
2758      * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2759      * @hide
2760      */
2761     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2762             TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2763 
2764     /** @hide */
2765     @IntDef(prefix = { "TEXT_ALIGNMENT_" }, value = {
2766             TEXT_ALIGNMENT_INHERIT,
2767             TEXT_ALIGNMENT_GRAVITY,
2768             TEXT_ALIGNMENT_CENTER,
2769             TEXT_ALIGNMENT_TEXT_START,
2770             TEXT_ALIGNMENT_TEXT_END,
2771             TEXT_ALIGNMENT_VIEW_START,
2772             TEXT_ALIGNMENT_VIEW_END
2773     })
2774     @Retention(RetentionPolicy.SOURCE)
2775     public @interface TextAlignment {}
2776 
2777     /**
2778      * Default text alignment. The text alignment of this View is inherited from its parent.
2779      * Use with {@link #setTextAlignment(int)}
2780      */
2781     public static final int TEXT_ALIGNMENT_INHERIT = 0;
2782 
2783     /**
2784      * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2785      * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2786      *
2787      * Use with {@link #setTextAlignment(int)}
2788      */
2789     public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2790 
2791     /**
2792      * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2793      *
2794      * Use with {@link #setTextAlignment(int)}
2795      */
2796     public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2797 
2798     /**
2799      * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2800      *
2801      * Use with {@link #setTextAlignment(int)}
2802      */
2803     public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2804 
2805     /**
2806      * Center the paragraph, e.g. ALIGN_CENTER.
2807      *
2808      * Use with {@link #setTextAlignment(int)}
2809      */
2810     public static final int TEXT_ALIGNMENT_CENTER = 4;
2811 
2812     /**
2813      * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2814      * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2815      *
2816      * Use with {@link #setTextAlignment(int)}
2817      */
2818     public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2819 
2820     /**
2821      * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2822      * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2823      *
2824      * Use with {@link #setTextAlignment(int)}
2825      */
2826     public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2827 
2828     /**
2829      * Default text alignment is inherited
2830      */
2831     private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2832 
2833     /**
2834      * Default resolved text alignment
2835      * @hide
2836      */
2837     static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2838 
2839     /**
2840       * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2841       * @hide
2842       */
2843     static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2844 
2845     /**
2846       * Mask for use with private flags indicating bits used for text alignment.
2847       * @hide
2848       */
2849     static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2850 
2851     /**
2852      * Array of text direction flags for mapping attribute "textAlignment" to correct
2853      * flag value.
2854      * @hide
2855      */
2856     private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2857             TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2858             TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2859             TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2860             TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2861             TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2862             TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2863             TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2864     };
2865 
2866     /**
2867      * Indicates whether the view text alignment has been resolved.
2868      * @hide
2869      */
2870     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2871 
2872     /**
2873      * Bit shift to get the resolved text alignment.
2874      * @hide
2875      */
2876     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2877 
2878     /**
2879      * Mask for use with private flags indicating bits used for text alignment.
2880      * @hide
2881      */
2882     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2883             << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2884 
2885     /**
2886      * Indicates whether if the view text alignment has been resolved to gravity
2887      */
2888     private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2889             TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2890 
2891     // Accessiblity constants for mPrivateFlags2
2892 
2893     /**
2894      * Shift for the bits in {@link #mPrivateFlags2} related to the
2895      * "importantForAccessibility" attribute.
2896      */
2897     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2898 
2899     /**
2900      * Automatically determine whether a view is important for accessibility.
2901      */
2902     public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2903 
2904     /**
2905      * The view is important for accessibility.
2906      */
2907     public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2908 
2909     /**
2910      * The view is not important for accessibility.
2911      */
2912     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2913 
2914     /**
2915      * The view is not important for accessibility, nor are any of its
2916      * descendant views.
2917      */
2918     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2919 
2920     /**
2921      * The default whether the view is important for accessibility.
2922      */
2923     static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2924 
2925     /**
2926      * Mask for obtaining the bits which specify how to determine
2927      * whether a view is important for accessibility.
2928      */
2929     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2930         | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2931         | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2932         << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2933 
2934     /**
2935      * Shift for the bits in {@link #mPrivateFlags2} related to the
2936      * "accessibilityLiveRegion" attribute.
2937      */
2938     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2939 
2940     /**
2941      * Live region mode specifying that accessibility services should not
2942      * automatically announce changes to this view. This is the default live
2943      * region mode for most views.
2944      * <p>
2945      * Use with {@link #setAccessibilityLiveRegion(int)}.
2946      */
2947     public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2948 
2949     /**
2950      * Live region mode specifying that accessibility services should announce
2951      * changes to this view.
2952      * <p>
2953      * Use with {@link #setAccessibilityLiveRegion(int)}.
2954      */
2955     public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2956 
2957     /**
2958      * Live region mode specifying that accessibility services should interrupt
2959      * ongoing speech to immediately announce changes to this view.
2960      * <p>
2961      * Use with {@link #setAccessibilityLiveRegion(int)}.
2962      */
2963     public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2964 
2965     /**
2966      * The default whether the view is important for accessibility.
2967      */
2968     static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2969 
2970     /**
2971      * Mask for obtaining the bits which specify a view's accessibility live
2972      * region mode.
2973      */
2974     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2975             | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2976             << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2977 
2978     /**
2979      * Flag indicating whether a view has accessibility focus.
2980      */
2981     static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2982 
2983     /**
2984      * Flag whether the accessibility state of the subtree rooted at this view changed.
2985      */
2986     static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2987 
2988     /**
2989      * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2990      * is used to check whether later changes to the view's transform should invalidate the
2991      * view to force the quickReject test to run again.
2992      */
2993     static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2994 
2995     /**
2996      * Flag indicating that start/end padding has been resolved into left/right padding
2997      * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2998      * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2999      * during measurement. In some special cases this is required such as when an adapter-based
3000      * view measures prospective children without attaching them to a window.
3001      */
3002     static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
3003 
3004     /**
3005      * Flag indicating that the start/end drawables has been resolved into left/right ones.
3006      */
3007     static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
3008 
3009     /**
3010      * Indicates that the view is tracking some sort of transient state
3011      * that the app should not need to be aware of, but that the framework
3012      * should take special care to preserve.
3013      */
3014     static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
3015 
3016     /**
3017      * Group of bits indicating that RTL properties resolution is done.
3018      */
3019     static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
3020             PFLAG2_TEXT_DIRECTION_RESOLVED |
3021             PFLAG2_TEXT_ALIGNMENT_RESOLVED |
3022             PFLAG2_PADDING_RESOLVED |
3023             PFLAG2_DRAWABLE_RESOLVED;
3024 
3025     // There are a couple of flags left in mPrivateFlags2
3026 
3027     /* End of masks for mPrivateFlags2 */
3028 
3029     /*
3030      * Masks for mPrivateFlags3, as generated by dumpFlags():
3031      *
3032      * |-------|-------|-------|-------|
3033      *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
3034      *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
3035      *                               1   PFLAG3_IS_LAID_OUT
3036      *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
3037      *                             1     PFLAG3_CALLED_SUPER
3038      *                            1      PFLAG3_APPLYING_INSETS
3039      *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
3040      *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
3041      *                         1         PFLAG3_SCROLL_INDICATOR_TOP
3042      *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
3043      *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
3044      *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
3045      *                     1             PFLAG3_SCROLL_INDICATOR_START
3046      *                    1              PFLAG3_SCROLL_INDICATOR_END
3047      *                   1               PFLAG3_ASSIST_BLOCKED
3048      *                  1                PFLAG3_CLUSTER
3049      *                 1                 PFLAG3_IS_AUTOFILLED
3050      *                1                  PFLAG3_FINGER_DOWN
3051      *               1                   PFLAG3_FOCUSED_BY_DEFAULT
3052      *           1111                    PFLAG3_IMPORTANT_FOR_AUTOFILL
3053      *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
3054      *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
3055      *        1                          PFLAG3_TEMPORARY_DETACH
3056      *       1                           PFLAG3_NO_REVEAL_ON_FOCUS
3057      *      1                            PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT
3058      *     1                             PFLAG3_SCREEN_READER_FOCUSABLE
3059      *    1                              PFLAG3_AGGREGATED_VISIBLE
3060      *   1                               PFLAG3_AUTOFILLID_EXPLICITLY_SET
3061      *  1                                PFLAG3_ACCESSIBILITY_HEADING
3062      * |-------|-------|-------|-------|
3063      */
3064 
3065     /**
3066      * Flag indicating that view has a transform animation set on it. This is used to track whether
3067      * an animation is cleared between successive frames, in order to tell the associated
3068      * DisplayList to clear its animation matrix.
3069      */
3070     static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
3071 
3072     /**
3073      * Flag indicating that view has an alpha animation set on it. This is used to track whether an
3074      * animation is cleared between successive frames, in order to tell the associated
3075      * DisplayList to restore its alpha value.
3076      */
3077     static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
3078 
3079     /**
3080      * Flag indicating that the view has been through at least one layout since it
3081      * was last attached to a window.
3082      */
3083     static final int PFLAG3_IS_LAID_OUT = 0x4;
3084 
3085     /**
3086      * Flag indicating that a call to measure() was skipped and should be done
3087      * instead when layout() is invoked.
3088      */
3089     static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
3090 
3091     /**
3092      * Flag indicating that an overridden method correctly called down to
3093      * the superclass implementation as required by the API spec.
3094      */
3095     static final int PFLAG3_CALLED_SUPER = 0x10;
3096 
3097     /**
3098      * Flag indicating that we're in the process of applying window insets.
3099      */
3100     static final int PFLAG3_APPLYING_INSETS = 0x20;
3101 
3102     /**
3103      * Flag indicating that we're in the process of fitting system windows using the old method.
3104      */
3105     static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
3106 
3107     /**
3108      * Flag indicating that nested scrolling is enabled for this view.
3109      * The view will optionally cooperate with views up its parent chain to allow for
3110      * integrated nested scrolling along the same axis.
3111      */
3112     static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
3113 
3114     /**
3115      * Flag indicating that the bottom scroll indicator should be displayed
3116      * when this view can scroll up.
3117      */
3118     static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
3119 
3120     /**
3121      * Flag indicating that the bottom scroll indicator should be displayed
3122      * when this view can scroll down.
3123      */
3124     static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
3125 
3126     /**
3127      * Flag indicating that the left scroll indicator should be displayed
3128      * when this view can scroll left.
3129      */
3130     static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
3131 
3132     /**
3133      * Flag indicating that the right scroll indicator should be displayed
3134      * when this view can scroll right.
3135      */
3136     static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
3137 
3138     /**
3139      * Flag indicating that the start scroll indicator should be displayed
3140      * when this view can scroll in the start direction.
3141      */
3142     static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
3143 
3144     /**
3145      * Flag indicating that the end scroll indicator should be displayed
3146      * when this view can scroll in the end direction.
3147      */
3148     static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
3149 
3150     static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
3151 
3152     static final int SCROLL_INDICATORS_NONE = 0x0000;
3153 
3154     /**
3155      * Mask for use with setFlags indicating bits used for indicating which
3156      * scroll indicators are enabled.
3157      */
3158     static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
3159             | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
3160             | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
3161             | PFLAG3_SCROLL_INDICATOR_END;
3162 
3163     /**
3164      * Left-shift required to translate between public scroll indicator flags
3165      * and internal PFLAGS3 flags. When used as a right-shift, translates
3166      * PFLAGS3 flags to public flags.
3167      */
3168     static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
3169 
3170     /** @hide */
3171     @Retention(RetentionPolicy.SOURCE)
3172     @IntDef(flag = true, prefix = { "SCROLL_INDICATOR_" }, value = {
3173             SCROLL_INDICATOR_TOP,
3174             SCROLL_INDICATOR_BOTTOM,
3175             SCROLL_INDICATOR_LEFT,
3176             SCROLL_INDICATOR_RIGHT,
3177             SCROLL_INDICATOR_START,
3178             SCROLL_INDICATOR_END,
3179     })
3180     public @interface ScrollIndicators {}
3181 
3182     /**
3183      * Scroll indicator direction for the top edge of the view.
3184      *
3185      * @see #setScrollIndicators(int)
3186      * @see #setScrollIndicators(int, int)
3187      * @see #getScrollIndicators()
3188      */
3189     public static final int SCROLL_INDICATOR_TOP =
3190             PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3191 
3192     /**
3193      * Scroll indicator direction for the bottom edge of the view.
3194      *
3195      * @see #setScrollIndicators(int)
3196      * @see #setScrollIndicators(int, int)
3197      * @see #getScrollIndicators()
3198      */
3199     public static final int SCROLL_INDICATOR_BOTTOM =
3200             PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3201 
3202     /**
3203      * Scroll indicator direction for the left edge of the view.
3204      *
3205      * @see #setScrollIndicators(int)
3206      * @see #setScrollIndicators(int, int)
3207      * @see #getScrollIndicators()
3208      */
3209     public static final int SCROLL_INDICATOR_LEFT =
3210             PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3211 
3212     /**
3213      * Scroll indicator direction for the right edge of the view.
3214      *
3215      * @see #setScrollIndicators(int)
3216      * @see #setScrollIndicators(int, int)
3217      * @see #getScrollIndicators()
3218      */
3219     public static final int SCROLL_INDICATOR_RIGHT =
3220             PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3221 
3222     /**
3223      * Scroll indicator direction for the starting edge of the view.
3224      * <p>
3225      * Resolved according to the view's layout direction, see
3226      * {@link #getLayoutDirection()} for more information.
3227      *
3228      * @see #setScrollIndicators(int)
3229      * @see #setScrollIndicators(int, int)
3230      * @see #getScrollIndicators()
3231      */
3232     public static final int SCROLL_INDICATOR_START =
3233             PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3234 
3235     /**
3236      * Scroll indicator direction for the ending edge of the view.
3237      * <p>
3238      * Resolved according to the view's layout direction, see
3239      * {@link #getLayoutDirection()} for more information.
3240      *
3241      * @see #setScrollIndicators(int)
3242      * @see #setScrollIndicators(int, int)
3243      * @see #getScrollIndicators()
3244      */
3245     public static final int SCROLL_INDICATOR_END =
3246             PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3247 
3248     /**
3249      * <p>Indicates that we are allowing {@link ViewStructure} to traverse
3250      * into this view.<p>
3251      */
3252     static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
3253 
3254     /**
3255      * Flag indicating that the view is a root of a keyboard navigation cluster.
3256      *
3257      * @see #isKeyboardNavigationCluster()
3258      * @see #setKeyboardNavigationCluster(boolean)
3259      */
3260     private static final int PFLAG3_CLUSTER = 0x8000;
3261 
3262     /**
3263      * Flag indicating that the view is autofilled
3264      *
3265      * @see #isAutofilled()
3266      * @see #setAutofilled(boolean)
3267      */
3268     private static final int PFLAG3_IS_AUTOFILLED = 0x10000;
3269 
3270     /**
3271      * Indicates that the user is currently touching the screen.
3272      * Currently used for the tooltip positioning only.
3273      */
3274     private static final int PFLAG3_FINGER_DOWN = 0x20000;
3275 
3276     /**
3277      * Flag indicating that this view is the default-focus view.
3278      *
3279      * @see #isFocusedByDefault()
3280      * @see #setFocusedByDefault(boolean)
3281      */
3282     private static final int PFLAG3_FOCUSED_BY_DEFAULT = 0x40000;
3283 
3284     /**
3285      * Shift for the bits in {@link #mPrivateFlags3} related to the
3286      * "importantForAutofill" attribute.
3287      */
3288     static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT = 19;
3289 
3290     /**
3291      * Mask for obtaining the bits which specify how to determine
3292      * whether a view is important for autofill.
3293      */
3294     static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK = (IMPORTANT_FOR_AUTOFILL_AUTO
3295             | IMPORTANT_FOR_AUTOFILL_YES | IMPORTANT_FOR_AUTOFILL_NO
3296             | IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
3297             | IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS)
3298             << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
3299 
3300     /**
3301      * Whether this view has rendered elements that overlap (see {@link
3302      * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
3303      * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
3304      * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
3305      * determined by whatever {@link #hasOverlappingRendering()} returns.
3306      */
3307     private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
3308 
3309     /**
3310      * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
3311      * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
3312      */
3313     private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
3314 
3315     /**
3316      * Flag indicating that the view is temporarily detached from the parent view.
3317      *
3318      * @see #onStartTemporaryDetach()
3319      * @see #onFinishTemporaryDetach()
3320      */
3321     static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
3322 
3323     /**
3324      * Flag indicating that the view does not wish to be revealed within its parent
3325      * hierarchy when it gains focus. Expressed in the negative since the historical
3326      * default behavior is to reveal on focus; this flag suppresses that behavior.
3327      *
3328      * @see #setRevealOnFocusHint(boolean)
3329      * @see #getRevealOnFocusHint()
3330      */
3331     private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
3332 
3333     /**
3334      * Flag indicating that when layout is completed we should notify
3335      * that the view was entered for autofill purposes. To minimize
3336      * showing autofill for views not visible to the user we evaluate
3337      * user visibility which cannot be done until the view is laid out.
3338      */
3339     static final int PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT = 0x8000000;
3340 
3341     /**
3342      * Works like focusable for screen readers, but without the side effects on input focus.
3343      * @see #setScreenReaderFocusable(boolean)
3344      */
3345     private static final int PFLAG3_SCREEN_READER_FOCUSABLE = 0x10000000;
3346 
3347     /**
3348      * The last aggregated visibility. Used to detect when it truly changes.
3349      */
3350     private static final int PFLAG3_AGGREGATED_VISIBLE = 0x20000000;
3351 
3352     /**
3353      * Used to indicate that {@link #mAutofillId} was explicitly set through
3354      * {@link #setAutofillId(AutofillId)}.
3355      */
3356     private static final int PFLAG3_AUTOFILLID_EXPLICITLY_SET = 0x40000000;
3357 
3358     /**
3359      * Indicates if the View is a heading for accessibility purposes
3360      */
3361     private static final int PFLAG3_ACCESSIBILITY_HEADING = 0x80000000;
3362 
3363     /* End of masks for mPrivateFlags3 */
3364 
3365     /** @hide */
3366     protected static final int VIEW_STRUCTURE_FOR_ASSIST = 0;
3367     /** @hide */
3368     protected  static final int VIEW_STRUCTURE_FOR_AUTOFILL = 1;
3369     /** @hide */
3370     protected  static final int VIEW_STRUCTURE_FOR_CONTENT_CAPTURE = 2;
3371 
3372     /** @hide */
3373     @IntDef(flag = true, prefix = { "VIEW_STRUCTURE_FOR" }, value = {
3374             VIEW_STRUCTURE_FOR_ASSIST,
3375             VIEW_STRUCTURE_FOR_AUTOFILL,
3376             VIEW_STRUCTURE_FOR_CONTENT_CAPTURE
3377     })
3378     @Retention(RetentionPolicy.SOURCE)
3379     public @interface ViewStructureType {}
3380 
3381     /**
3382      * Always allow a user to over-scroll this view, provided it is a
3383      * view that can scroll.
3384      *
3385      * @see #getOverScrollMode()
3386      * @see #setOverScrollMode(int)
3387      */
3388     public static final int OVER_SCROLL_ALWAYS = 0;
3389 
3390     /**
3391      * Allow a user to over-scroll this view only if the content is large
3392      * enough to meaningfully scroll, provided it is a view that can scroll.
3393      *
3394      * @see #getOverScrollMode()
3395      * @see #setOverScrollMode(int)
3396      */
3397     public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
3398 
3399     /**
3400      * Never allow a user to over-scroll this view.
3401      *
3402      * @see #getOverScrollMode()
3403      * @see #setOverScrollMode(int)
3404      */
3405     public static final int OVER_SCROLL_NEVER = 2;
3406 
3407     /**
3408      * Special constant for {@link #setSystemUiVisibility(int)}: View has
3409      * requested the system UI (status bar) to be visible (the default).
3410      *
3411      * @see #setSystemUiVisibility(int)
3412      */
3413     public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
3414 
3415     /**
3416      * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
3417      * system UI to enter an unobtrusive "low profile" mode.
3418      *
3419      * <p>This is for use in games, book readers, video players, or any other
3420      * "immersive" application where the usual system chrome is deemed too distracting.
3421      *
3422      * <p>In low profile mode, the status bar and/or navigation icons may dim.
3423      *
3424      * @see #setSystemUiVisibility(int)
3425      */
3426     public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
3427 
3428     /**
3429      * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
3430      * system navigation be temporarily hidden.
3431      *
3432      * <p>This is an even less obtrusive state than that called for by
3433      * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
3434      * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
3435      * those to disappear. This is useful (in conjunction with the
3436      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
3437      * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
3438      * window flags) for displaying content using every last pixel on the display.
3439      *
3440      * <p>There is a limitation: because navigation controls are so important, the least user
3441      * interaction will cause them to reappear immediately.  When this happens, both
3442      * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
3443      * so that both elements reappear at the same time.
3444      *
3445      * @see #setSystemUiVisibility(int)
3446      */
3447     public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
3448 
3449     /**
3450      * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
3451      * into the normal fullscreen mode so that its content can take over the screen
3452      * while still allowing the user to interact with the application.
3453      *
3454      * <p>This has the same visual effect as
3455      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
3456      * WindowManager.LayoutParams.FLAG_FULLSCREEN},
3457      * meaning that non-critical screen decorations (such as the status bar) will be
3458      * hidden while the user is in the View's window, focusing the experience on
3459      * that content.  Unlike the window flag, if you are using ActionBar in
3460      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3461      * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
3462      * hide the action bar.
3463      *
3464      * <p>This approach to going fullscreen is best used over the window flag when
3465      * it is a transient state -- that is, the application does this at certain
3466      * points in its user interaction where it wants to allow the user to focus
3467      * on content, but not as a continuous state.  For situations where the application
3468      * would like to simply stay full screen the entire time (such as a game that
3469      * wants to take over the screen), the
3470      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
3471      * is usually a better approach.  The state set here will be removed by the system
3472      * in various situations (such as the user moving to another application) like
3473      * the other system UI states.
3474      *
3475      * <p>When using this flag, the application should provide some easy facility
3476      * for the user to go out of it.  A common example would be in an e-book
3477      * reader, where tapping on the screen brings back whatever screen and UI
3478      * decorations that had been hidden while the user was immersed in reading
3479      * the book.
3480      *
3481      * @see #setSystemUiVisibility(int)
3482      */
3483     public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
3484 
3485     /**
3486      * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
3487      * flags, we would like a stable view of the content insets given to
3488      * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
3489      * will always represent the worst case that the application can expect
3490      * as a continuous state.  In the stock Android UI this is the space for
3491      * the system bar, nav bar, and status bar, but not more transient elements
3492      * such as an input method.
3493      *
3494      * The stable layout your UI sees is based on the system UI modes you can
3495      * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
3496      * then you will get a stable layout for changes of the
3497      * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
3498      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
3499      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
3500      * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
3501      * with a stable layout.  (Note that you should avoid using
3502      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
3503      *
3504      * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
3505      * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
3506      * then a hidden status bar will be considered a "stable" state for purposes
3507      * here.  This allows your UI to continually hide the status bar, while still
3508      * using the system UI flags to hide the action bar while still retaining
3509      * a stable layout.  Note that changing the window fullscreen flag will never
3510      * provide a stable layout for a clean transition.
3511      *
3512      * <p>If you are using ActionBar in
3513      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3514      * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
3515      * insets it adds to those given to the application.
3516      */
3517     public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
3518 
3519     /**
3520      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3521      * to be laid out as if it has requested
3522      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
3523      * allows it to avoid artifacts when switching in and out of that mode, at
3524      * the expense that some of its user interface may be covered by screen
3525      * decorations when they are shown.  You can perform layout of your inner
3526      * UI elements to account for the navigation system UI through the
3527      * {@link #fitSystemWindows(Rect)} method.
3528      */
3529     public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
3530 
3531     /**
3532      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3533      * to be laid out as if it has requested
3534      * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
3535      * allows it to avoid artifacts when switching in and out of that mode, at
3536      * the expense that some of its user interface may be covered by screen
3537      * decorations when they are shown.  You can perform layout of your inner
3538      * UI elements to account for non-fullscreen system UI through the
3539      * {@link #fitSystemWindows(Rect)} method.
3540      *
3541      * <p>Note: on displays that have a {@link DisplayCutout}, the window may still be placed
3542      *  differently than if {@link #SYSTEM_UI_FLAG_FULLSCREEN} was set, if the
3543      *  window's {@link WindowManager.LayoutParams#layoutInDisplayCutoutMode
3544      *  layoutInDisplayCutoutMode} is
3545      *  {@link WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
3546      *  LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT}. To avoid this, use either of the other modes.
3547      *
3548      * @see WindowManager.LayoutParams#layoutInDisplayCutoutMode
3549      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
3550      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
3551      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
3552      */
3553     public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
3554 
3555     /**
3556      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3557      * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
3558      * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
3559      * user interaction.
3560      * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
3561      * has an effect when used in combination with that flag.</p>
3562      */
3563     public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
3564 
3565     /**
3566      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3567      * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
3568      * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
3569      * experience while also hiding the system bars.  If this flag is not set,
3570      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
3571      * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
3572      * if the user swipes from the top of the screen.
3573      * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
3574      * system gestures, such as swiping from the top of the screen.  These transient system bars
3575      * will overlay app’s content, may have some degree of transparency, and will automatically
3576      * hide after a short timeout.
3577      * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
3578      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
3579      * with one or both of those flags.</p>
3580      */
3581     public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
3582 
3583     /**
3584      * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
3585      * is compatible with light status bar backgrounds.
3586      *
3587      * <p>For this to take effect, the window must request
3588      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3589      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3590      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
3591      *         FLAG_TRANSLUCENT_STATUS}.
3592      *
3593      * @see android.R.attr#windowLightStatusBar
3594      */
3595     public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
3596 
3597     /**
3598      * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3599      * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3600      */
3601     private static final int SYSTEM_UI_RESERVED_LEGACY1 = 0x00004000;
3602 
3603     /**
3604      * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3605      * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3606      */
3607     private static final int SYSTEM_UI_RESERVED_LEGACY2 = 0x00010000;
3608 
3609     /**
3610      * Flag for {@link #setSystemUiVisibility(int)}: Requests the navigation bar to draw in a mode
3611      * that is compatible with light navigation bar backgrounds.
3612      *
3613      * <p>For this to take effect, the window must request
3614      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3615      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3616      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION
3617      *         FLAG_TRANSLUCENT_NAVIGATION}.
3618      *
3619      * @see android.R.attr#windowLightNavigationBar
3620      */
3621     public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010;
3622 
3623     /**
3624      * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
3625      */
3626     @Deprecated
3627     public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
3628 
3629     /**
3630      * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
3631      */
3632     @Deprecated
3633     public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
3634 
3635     /**
3636      * @hide
3637      *
3638      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3639      * out of the public fields to keep the undefined bits out of the developer's way.
3640      *
3641      * Flag to make the status bar not expandable.  Unless you also
3642      * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
3643      */
3644     @UnsupportedAppUsage
3645     public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
3646 
3647     /**
3648      * @hide
3649      *
3650      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3651      * out of the public fields to keep the undefined bits out of the developer's way.
3652      *
3653      * Flag to hide notification icons and scrolling ticker text.
3654      */
3655     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
3656 
3657     /**
3658      * @hide
3659      *
3660      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3661      * out of the public fields to keep the undefined bits out of the developer's way.
3662      *
3663      * Flag to disable incoming notification alerts.  This will not block
3664      * icons, but it will block sound, vibrating and other visual or aural notifications.
3665      */
3666     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
3667 
3668     /**
3669      * @hide
3670      *
3671      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3672      * out of the public fields to keep the undefined bits out of the developer's way.
3673      *
3674      * Flag to hide only the scrolling ticker.  Note that
3675      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
3676      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
3677      */
3678     public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
3679 
3680     /**
3681      * @hide
3682      *
3683      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3684      * out of the public fields to keep the undefined bits out of the developer's way.
3685      *
3686      * Flag to hide the center system info area.
3687      */
3688     public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
3689 
3690     /**
3691      * @hide
3692      *
3693      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3694      * out of the public fields to keep the undefined bits out of the developer's way.
3695      *
3696      * Flag to hide only the home button.  Don't use this
3697      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3698      */
3699     @UnsupportedAppUsage
3700     public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
3701 
3702     /**
3703      * @hide
3704      *
3705      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3706      * out of the public fields to keep the undefined bits out of the developer's way.
3707      *
3708      * Flag to hide only the back button. Don't use this
3709      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3710      */
3711     @UnsupportedAppUsage
3712     public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
3713 
3714     /**
3715      * @hide
3716      *
3717      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3718      * out of the public fields to keep the undefined bits out of the developer's way.
3719      *
3720      * Flag to hide only the clock.  You might use this if your activity has
3721      * its own clock making the status bar's clock redundant.
3722      */
3723     public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
3724 
3725     /**
3726      * @hide
3727      *
3728      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3729      * out of the public fields to keep the undefined bits out of the developer's way.
3730      *
3731      * Flag to hide only the recent apps button. Don't use this
3732      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3733      */
3734     @UnsupportedAppUsage
3735     public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
3736 
3737     /**
3738      * @hide
3739      *
3740      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3741      * out of the public fields to keep the undefined bits out of the developer's way.
3742      *
3743      * Flag to disable the global search gesture. Don't use this
3744      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3745      */
3746     public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
3747 
3748     /**
3749      * @hide
3750      *
3751      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3752      * out of the public fields to keep the undefined bits out of the developer's way.
3753      *
3754      * Flag to specify that the status bar is displayed in transient mode.
3755      */
3756     public static final int STATUS_BAR_TRANSIENT = 0x04000000;
3757 
3758     /**
3759      * @hide
3760      *
3761      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3762      * out of the public fields to keep the undefined bits out of the developer's way.
3763      *
3764      * Flag to specify that the navigation bar is displayed in transient mode.
3765      */
3766     @UnsupportedAppUsage
3767     public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
3768 
3769     /**
3770      * @hide
3771      *
3772      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3773      * out of the public fields to keep the undefined bits out of the developer's way.
3774      *
3775      * Flag to specify that the hidden status bar would like to be shown.
3776      */
3777     public static final int STATUS_BAR_UNHIDE = 0x10000000;
3778 
3779     /**
3780      * @hide
3781      *
3782      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3783      * out of the public fields to keep the undefined bits out of the developer's way.
3784      *
3785      * Flag to specify that the hidden navigation bar would like to be shown.
3786      */
3787     public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
3788 
3789     /**
3790      * @hide
3791      *
3792      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3793      * out of the public fields to keep the undefined bits out of the developer's way.
3794      *
3795      * Flag to specify that the status bar is displayed in translucent mode.
3796      */
3797     public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
3798 
3799     /**
3800      * @hide
3801      *
3802      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3803      * out of the public fields to keep the undefined bits out of the developer's way.
3804      *
3805      * Flag to specify that the navigation bar is displayed in translucent mode.
3806      */
3807     public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
3808 
3809     /**
3810      * @hide
3811      *
3812      * Makes navigation bar transparent (but not the status bar).
3813      */
3814     public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
3815 
3816     /**
3817      * @hide
3818      *
3819      * Makes status bar transparent (but not the navigation bar).
3820      */
3821     public static final int STATUS_BAR_TRANSPARENT = 0x00000008;
3822 
3823     /**
3824      * @hide
3825      *
3826      * Makes both status bar and navigation bar transparent.
3827      */
3828     public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
3829             | STATUS_BAR_TRANSPARENT;
3830 
3831     /**
3832      * @hide
3833      */
3834     public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
3835 
3836     /**
3837      * These are the system UI flags that can be cleared by events outside
3838      * of an application.  Currently this is just the ability to tap on the
3839      * screen while hiding the navigation bar to have it return.
3840      * @hide
3841      */
3842     public static final int SYSTEM_UI_CLEARABLE_FLAGS =
3843             SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
3844             | SYSTEM_UI_FLAG_FULLSCREEN;
3845 
3846     /**
3847      * Flags that can impact the layout in relation to system UI.
3848      */
3849     public static final int SYSTEM_UI_LAYOUT_FLAGS =
3850             SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3851             | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
3852 
3853     /** @hide */
3854     @IntDef(flag = true, prefix = { "FIND_VIEWS_" }, value = {
3855             FIND_VIEWS_WITH_TEXT,
3856             FIND_VIEWS_WITH_CONTENT_DESCRIPTION
3857     })
3858     @Retention(RetentionPolicy.SOURCE)
3859     public @interface FindViewFlags {}
3860 
3861     /**
3862      * Find views that render the specified text.
3863      *
3864      * @see #findViewsWithText(ArrayList, CharSequence, int)
3865      */
3866     public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
3867 
3868     /**
3869      * Find find views that contain the specified content description.
3870      *
3871      * @see #findViewsWithText(ArrayList, CharSequence, int)
3872      */
3873     public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
3874 
3875     /**
3876      * Find views that contain {@link AccessibilityNodeProvider}. Such
3877      * a View is a root of virtual view hierarchy and may contain the searched
3878      * text. If this flag is set Views with providers are automatically
3879      * added and it is a responsibility of the client to call the APIs of
3880      * the provider to determine whether the virtual tree rooted at this View
3881      * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3882      * representing the virtual views with this text.
3883      *
3884      * @see #findViewsWithText(ArrayList, CharSequence, int)
3885      *
3886      * @hide
3887      */
3888     public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3889 
3890     /**
3891      * The undefined cursor position.
3892      *
3893      * @hide
3894      */
3895     public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3896 
3897     /**
3898      * Indicates that the screen has changed state and is now off.
3899      *
3900      * @see #onScreenStateChanged(int)
3901      */
3902     public static final int SCREEN_STATE_OFF = 0x0;
3903 
3904     /**
3905      * Indicates that the screen has changed state and is now on.
3906      *
3907      * @see #onScreenStateChanged(int)
3908      */
3909     public static final int SCREEN_STATE_ON = 0x1;
3910 
3911     /**
3912      * Indicates no axis of view scrolling.
3913      */
3914     public static final int SCROLL_AXIS_NONE = 0;
3915 
3916     /**
3917      * Indicates scrolling along the horizontal axis.
3918      */
3919     public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3920 
3921     /**
3922      * Indicates scrolling along the vertical axis.
3923      */
3924     public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3925 
3926     /**
3927      * Controls the over-scroll mode for this view.
3928      * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3929      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3930      * and {@link #OVER_SCROLL_NEVER}.
3931      */
3932     private int mOverScrollMode;
3933 
3934     /**
3935      * The parent this view is attached to.
3936      * {@hide}
3937      *
3938      * @see #getParent()
3939      */
3940     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
3941     protected ViewParent mParent;
3942 
3943     /**
3944      * {@hide}
3945      *
3946      * Not available for general use. If you need help, hang up and then dial one of the following
3947      * public APIs:
3948      *
3949      * @see #isAttachedToWindow() for current attach state
3950      * @see #onAttachedToWindow() for subclasses performing work when becoming attached
3951      * @see #onDetachedFromWindow() for subclasses performing work when becoming detached
3952      * @see OnAttachStateChangeListener for other code performing work on attach/detach
3953      * @see #getHandler() for posting messages to this view's UI thread/looper
3954      * @see #getParent() for interacting with the parent chain
3955      * @see #getWindowToken() for the current window token
3956      * @see #getRootView() for the view at the root of the attached hierarchy
3957      * @see #getDisplay() for the Display this view is presented on
3958      * @see #getRootWindowInsets() for the current insets applied to the whole attached window
3959      * @see #hasWindowFocus() for whether the attached window is currently focused
3960      * @see #getWindowVisibility() for checking the visibility of the attached window
3961      */
3962     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
3963     AttachInfo mAttachInfo;
3964 
3965     /**
3966      * {@hide}
3967      */
3968     @ViewDebug.ExportedProperty(flagMapping = {
3969         @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3970                 name = "FORCE_LAYOUT"),
3971         @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3972                 name = "LAYOUT_REQUIRED"),
3973         @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3974             name = "DRAWING_CACHE_INVALID", outputIf = false),
3975         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3976         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3977         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3978     }, formatToHexString = true)
3979 
3980     /* @hide */
3981     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769414)
3982     public int mPrivateFlags;
3983     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768943)
3984     int mPrivateFlags2;
3985     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 129147060)
3986     int mPrivateFlags3;
3987 
3988     /**
3989      * This view's request for the visibility of the status bar.
3990      * @hide
3991      */
3992     @ViewDebug.ExportedProperty(flagMapping = {
3993             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3994                     equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3995                     name = "LOW_PROFILE"),
3996             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3997                     equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3998                     name = "HIDE_NAVIGATION"),
3999             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_FULLSCREEN,
4000                     equals = SYSTEM_UI_FLAG_FULLSCREEN,
4001                     name = "FULLSCREEN"),
4002             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_STABLE,
4003                     equals = SYSTEM_UI_FLAG_LAYOUT_STABLE,
4004                     name = "LAYOUT_STABLE"),
4005             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
4006                     equals = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
4007                     name = "LAYOUT_HIDE_NAVIGATION"),
4008             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
4009                     equals = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
4010                     name = "LAYOUT_FULLSCREEN"),
4011             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE,
4012                     equals = SYSTEM_UI_FLAG_IMMERSIVE,
4013                     name = "IMMERSIVE"),
4014             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
4015                     equals = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
4016                     name = "IMMERSIVE_STICKY"),
4017             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
4018                     equals = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
4019                     name = "LIGHT_STATUS_BAR"),
4020             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
4021                     equals = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
4022                     name = "LIGHT_NAVIGATION_BAR"),
4023             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_EXPAND,
4024                     equals = STATUS_BAR_DISABLE_EXPAND,
4025                     name = "STATUS_BAR_DISABLE_EXPAND"),
4026             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
4027                     equals = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
4028                     name = "STATUS_BAR_DISABLE_NOTIFICATION_ICONS"),
4029             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
4030                     equals = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
4031                     name = "STATUS_BAR_DISABLE_NOTIFICATION_ALERTS"),
4032             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
4033                     equals = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
4034                     name = "STATUS_BAR_DISABLE_NOTIFICATION_TICKER"),
4035             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SYSTEM_INFO,
4036                     equals = STATUS_BAR_DISABLE_SYSTEM_INFO,
4037                     name = "STATUS_BAR_DISABLE_SYSTEM_INFO"),
4038             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_HOME,
4039                     equals = STATUS_BAR_DISABLE_HOME,
4040                     name = "STATUS_BAR_DISABLE_HOME"),
4041             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_BACK,
4042                     equals = STATUS_BAR_DISABLE_BACK,
4043                     name = "STATUS_BAR_DISABLE_BACK"),
4044             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_CLOCK,
4045                     equals = STATUS_BAR_DISABLE_CLOCK,
4046                     name = "STATUS_BAR_DISABLE_CLOCK"),
4047             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_RECENT,
4048                     equals = STATUS_BAR_DISABLE_RECENT,
4049                     name = "STATUS_BAR_DISABLE_RECENT"),
4050             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SEARCH,
4051                     equals = STATUS_BAR_DISABLE_SEARCH,
4052                     name = "STATUS_BAR_DISABLE_SEARCH"),
4053             @ViewDebug.FlagToString(mask = STATUS_BAR_TRANSIENT,
4054                     equals = STATUS_BAR_TRANSIENT,
4055                     name = "STATUS_BAR_TRANSIENT"),
4056             @ViewDebug.FlagToString(mask = NAVIGATION_BAR_TRANSIENT,
4057                     equals = NAVIGATION_BAR_TRANSIENT,
4058                     name = "NAVIGATION_BAR_TRANSIENT"),
4059             @ViewDebug.FlagToString(mask = STATUS_BAR_UNHIDE,
4060                     equals = STATUS_BAR_UNHIDE,
4061                     name = "STATUS_BAR_UNHIDE"),
4062             @ViewDebug.FlagToString(mask = NAVIGATION_BAR_UNHIDE,
4063                     equals = NAVIGATION_BAR_UNHIDE,
4064                     name = "NAVIGATION_BAR_UNHIDE"),
4065             @ViewDebug.FlagToString(mask = STATUS_BAR_TRANSLUCENT,
4066                     equals = STATUS_BAR_TRANSLUCENT,
4067                     name = "STATUS_BAR_TRANSLUCENT"),
4068             @ViewDebug.FlagToString(mask = NAVIGATION_BAR_TRANSLUCENT,
4069                     equals = NAVIGATION_BAR_TRANSLUCENT,
4070                     name = "NAVIGATION_BAR_TRANSLUCENT"),
4071             @ViewDebug.FlagToString(mask = NAVIGATION_BAR_TRANSPARENT,
4072                     equals = NAVIGATION_BAR_TRANSPARENT,
4073                     name = "NAVIGATION_BAR_TRANSPARENT"),
4074             @ViewDebug.FlagToString(mask = STATUS_BAR_TRANSPARENT,
4075                     equals = STATUS_BAR_TRANSPARENT,
4076                     name = "STATUS_BAR_TRANSPARENT")
4077     }, formatToHexString = true)
4078     int mSystemUiVisibility;
4079 
4080     /**
4081      * Reference count for transient state.
4082      * @see #setHasTransientState(boolean)
4083      */
4084     int mTransientStateCount = 0;
4085 
4086     /**
4087      * Count of how many windows this view has been attached to.
4088      */
4089     int mWindowAttachCount;
4090 
4091     /**
4092      * The layout parameters associated with this view and used by the parent
4093      * {@link android.view.ViewGroup} to determine how this view should be
4094      * laid out.
4095      *
4096      * The field should not be used directly. Instead {@link #getLayoutParams()} and {@link
4097      * #setLayoutParams(ViewGroup.LayoutParams)} should be used. The setter guarantees internal
4098      * state correctness of the class.
4099      * {@hide}
4100      */
4101     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4102     protected ViewGroup.LayoutParams mLayoutParams;
4103 
4104     /**
4105      * The view flags hold various views states.
4106      *
4107      * Use {@link #setTransitionVisibility(int)} to change the visibility of this view without
4108      * triggering updates.
4109      * {@hide}
4110      */
4111     @ViewDebug.ExportedProperty(formatToHexString = true)
4112     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4113     int mViewFlags;
4114 
4115     static class TransformationInfo {
4116         /**
4117          * The transform matrix for the View. This transform is calculated internally
4118          * based on the translation, rotation, and scale properties.
4119          *
4120          * Do *not* use this variable directly; instead call getMatrix(), which will
4121          * load the value from the View's RenderNode.
4122          */
4123         private final Matrix mMatrix = new Matrix();
4124 
4125         /**
4126          * The inverse transform matrix for the View. This transform is calculated
4127          * internally based on the translation, rotation, and scale properties.
4128          *
4129          * Do *not* use this variable directly; instead call getInverseMatrix(),
4130          * which will load the value from the View's RenderNode.
4131          */
4132         private Matrix mInverseMatrix;
4133 
4134         /**
4135          * The opacity of the View. This is a value from 0 to 1, where 0 means
4136          * completely transparent and 1 means completely opaque.
4137          */
4138         @ViewDebug.ExportedProperty
4139         private float mAlpha = 1f;
4140 
4141         /**
4142          * The opacity of the view as manipulated by the Fade transition. This is a
4143          * property only used by transitions, which is composited with the other alpha
4144          * values to calculate the final visual alpha value.
4145          */
4146         float mTransitionAlpha = 1f;
4147     }
4148 
4149     /** @hide */
4150     @UnsupportedAppUsage
4151     public TransformationInfo mTransformationInfo;
4152 
4153     /**
4154      * Current clip bounds. to which all drawing of this view are constrained.
4155      */
4156     @ViewDebug.ExportedProperty(category = "drawing")
4157     Rect mClipBounds = null;
4158 
4159     private boolean mLastIsOpaque;
4160 
4161     /**
4162      * The distance in pixels from the left edge of this view's parent
4163      * to the left edge of this view.
4164      * {@hide}
4165      */
4166     @ViewDebug.ExportedProperty(category = "layout")
4167     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4168     protected int mLeft;
4169     /**
4170      * The distance in pixels from the left edge of this view's parent
4171      * to the right edge of this view.
4172      * {@hide}
4173      */
4174     @ViewDebug.ExportedProperty(category = "layout")
4175     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4176     protected int mRight;
4177     /**
4178      * The distance in pixels from the top edge of this view's parent
4179      * to the top edge of this view.
4180      * {@hide}
4181      */
4182     @ViewDebug.ExportedProperty(category = "layout")
4183     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4184     protected int mTop;
4185     /**
4186      * The distance in pixels from the top edge of this view's parent
4187      * to the bottom edge of this view.
4188      * {@hide}
4189      */
4190     @ViewDebug.ExportedProperty(category = "layout")
4191     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4192     protected int mBottom;
4193 
4194     /**
4195      * The offset, in pixels, by which the content of this view is scrolled
4196      * horizontally.
4197      * Please use {@link View#getScrollX()} and {@link View#setScrollX(int)} instead of
4198      * accessing these directly.
4199      * {@hide}
4200      */
4201     @ViewDebug.ExportedProperty(category = "scrolling")
4202     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4203     protected int mScrollX;
4204     /**
4205      * The offset, in pixels, by which the content of this view is scrolled
4206      * vertically.
4207      * Please use {@link View#getScrollY()} and {@link View#setScrollY(int)} instead of
4208      * accessing these directly.
4209      * {@hide}
4210      */
4211     @ViewDebug.ExportedProperty(category = "scrolling")
4212     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4213     protected int mScrollY;
4214 
4215     /**
4216      * The final computed left padding in pixels that is used for drawing. This is the distance in
4217      * pixels between the left edge of this view and the left edge of its content.
4218      * {@hide}
4219      */
4220     @ViewDebug.ExportedProperty(category = "padding")
4221     @UnsupportedAppUsage
4222     protected int mPaddingLeft = 0;
4223     /**
4224      * The final computed right padding in pixels that is used for drawing. This is the distance in
4225      * pixels between the right edge of this view and the right edge of its content.
4226      * {@hide}
4227      */
4228     @ViewDebug.ExportedProperty(category = "padding")
4229     @UnsupportedAppUsage
4230     protected int mPaddingRight = 0;
4231     /**
4232      * The final computed top padding in pixels that is used for drawing. This is the distance in
4233      * pixels between the top edge of this view and the top edge of its content.
4234      * {@hide}
4235      */
4236     @ViewDebug.ExportedProperty(category = "padding")
4237     @UnsupportedAppUsage
4238     protected int mPaddingTop;
4239     /**
4240      * The final computed bottom padding in pixels that is used for drawing. This is the distance in
4241      * pixels between the bottom edge of this view and the bottom edge of its content.
4242      * {@hide}
4243      */
4244     @ViewDebug.ExportedProperty(category = "padding")
4245     @UnsupportedAppUsage
4246     protected int mPaddingBottom;
4247 
4248     /**
4249      * The layout insets in pixels, that is the distance in pixels between the
4250      * visible edges of this view its bounds.
4251      */
4252     private Insets mLayoutInsets;
4253 
4254     /**
4255      * Briefly describes the view and is primarily used for accessibility support.
4256      */
4257     private CharSequence mContentDescription;
4258 
4259     /**
4260      * If this view represents a distinct part of the window, it can have a title that labels the
4261      * area.
4262      */
4263     private CharSequence mAccessibilityPaneTitle;
4264 
4265     /**
4266      * Specifies the id of a view for which this view serves as a label for
4267      * accessibility purposes.
4268      */
4269     private int mLabelForId = View.NO_ID;
4270 
4271     /**
4272      * Predicate for matching labeled view id with its label for
4273      * accessibility purposes.
4274      */
4275     private MatchLabelForPredicate mMatchLabelForPredicate;
4276 
4277     /**
4278      * Specifies a view before which this one is visited in accessibility traversal.
4279      */
4280     private int mAccessibilityTraversalBeforeId = NO_ID;
4281 
4282     /**
4283      * Specifies a view after which this one is visited in accessibility traversal.
4284      */
4285     private int mAccessibilityTraversalAfterId = NO_ID;
4286 
4287     /**
4288      * Predicate for matching a view by its id.
4289      */
4290     private MatchIdPredicate mMatchIdPredicate;
4291 
4292     /**
4293      * The right padding after RTL resolution, but before taking account of scroll bars.
4294      *
4295      * @hide
4296      */
4297     @ViewDebug.ExportedProperty(category = "padding")
4298     protected int mUserPaddingRight;
4299 
4300     /**
4301      * The resolved bottom padding before taking account of scroll bars.
4302      *
4303      * @hide
4304      */
4305     @ViewDebug.ExportedProperty(category = "padding")
4306     protected int mUserPaddingBottom;
4307 
4308     /**
4309      * The left padding after RTL resolution, but before taking account of scroll bars.
4310      *
4311      * @hide
4312      */
4313     @ViewDebug.ExportedProperty(category = "padding")
4314     protected int mUserPaddingLeft;
4315 
4316     /**
4317      * Cache the paddingStart set by the user to append to the scrollbar's size.
4318      *
4319      */
4320     @ViewDebug.ExportedProperty(category = "padding")
4321     int mUserPaddingStart;
4322 
4323     /**
4324      * Cache the paddingEnd set by the user to append to the scrollbar's size.
4325      *
4326      */
4327     @ViewDebug.ExportedProperty(category = "padding")
4328     int mUserPaddingEnd;
4329 
4330     /**
4331      * The left padding as set by a setter method, a background's padding, or via XML property
4332      * resolution. This value is the padding before LTR resolution or taking account of scrollbars.
4333      *
4334      * @hide
4335      */
4336     int mUserPaddingLeftInitial;
4337 
4338     /**
4339      * The right padding as set by a setter method, a background's padding, or via XML property
4340      * resolution. This value is the padding before LTR resolution or taking account of scrollbars.
4341      *
4342      * @hide
4343      */
4344     int mUserPaddingRightInitial;
4345 
4346     /**
4347      * Default undefined padding
4348      */
4349     private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
4350 
4351     /**
4352      * Cache if a left padding has been defined explicitly via padding, horizontal padding,
4353      * or leftPadding in XML, or by setPadding(...) or setRelativePadding(...)
4354      */
4355     private boolean mLeftPaddingDefined = false;
4356 
4357     /**
4358      * Cache if a right padding has been defined explicitly via padding, horizontal padding,
4359      * or rightPadding in XML, or by setPadding(...) or setRelativePadding(...)
4360      */
4361     private boolean mRightPaddingDefined = false;
4362 
4363     /**
4364      * @hide
4365      */
4366     int mOldWidthMeasureSpec = Integer.MIN_VALUE;
4367     /**
4368      * @hide
4369      */
4370     int mOldHeightMeasureSpec = Integer.MIN_VALUE;
4371 
4372     private LongSparseLongArray mMeasureCache;
4373 
4374     @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
4375     @UnsupportedAppUsage
4376     private Drawable mBackground;
4377     private TintInfo mBackgroundTint;
4378 
4379     @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
4380     private ForegroundInfo mForegroundInfo;
4381 
4382     private Drawable mScrollIndicatorDrawable;
4383 
4384     /**
4385      * RenderNode used for backgrounds.
4386      * <p>
4387      * When non-null and valid, this is expected to contain an up-to-date copy
4388      * of the background drawable. It is cleared on temporary detach, and reset
4389      * on cleanup.
4390      */
4391     private RenderNode mBackgroundRenderNode;
4392 
4393     @UnsupportedAppUsage
4394     private int mBackgroundResource;
4395     private boolean mBackgroundSizeChanged;
4396 
4397     /** The default focus highlight.
4398      * @see #mDefaultFocusHighlightEnabled
4399      * @see Drawable#hasFocusStateSpecified()
4400      */
4401     private Drawable mDefaultFocusHighlight;
4402     private Drawable mDefaultFocusHighlightCache;
4403     private boolean mDefaultFocusHighlightSizeChanged;
4404     /**
4405      * True if the default focus highlight is needed on the target device.
4406      */
4407     private static boolean sUseDefaultFocusHighlight;
4408 
4409     /**
4410      * True if zero-sized views can be focused.
4411      */
4412     private static boolean sCanFocusZeroSized;
4413 
4414     /**
4415      * Always assign focus if a focusable View is available.
4416      */
4417     private static boolean sAlwaysAssignFocus;
4418 
4419     private String mTransitionName;
4420 
4421     static class TintInfo {
4422         ColorStateList mTintList;
4423         BlendMode mBlendMode;
4424         boolean mHasTintMode;
4425         boolean mHasTintList;
4426     }
4427 
4428     private static class ForegroundInfo {
4429         private Drawable mDrawable;
4430         private TintInfo mTintInfo;
4431         private int mGravity = Gravity.FILL;
4432         private boolean mInsidePadding = true;
4433         private boolean mBoundsChanged = true;
4434         private final Rect mSelfBounds = new Rect();
4435         private final Rect mOverlayBounds = new Rect();
4436     }
4437 
4438     static class ListenerInfo {
4439         /**
4440          * Listener used to dispatch focus change events.
4441          * This field should be made private, so it is hidden from the SDK.
4442          * {@hide}
4443          */
4444         @UnsupportedAppUsage
4445         protected OnFocusChangeListener mOnFocusChangeListener;
4446 
4447         /**
4448          * Listeners for layout change events.
4449          */
4450         private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
4451 
4452         protected OnScrollChangeListener mOnScrollChangeListener;
4453 
4454         /**
4455          * Listeners for attach events.
4456          */
4457         private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
4458 
4459         /**
4460          * Listener used to dispatch click events.
4461          * This field should be made private, so it is hidden from the SDK.
4462          * {@hide}
4463          */
4464         @UnsupportedAppUsage
4465         public OnClickListener mOnClickListener;
4466 
4467         /**
4468          * Listener used to dispatch long click events.
4469          * This field should be made private, so it is hidden from the SDK.
4470          * {@hide}
4471          */
4472         @UnsupportedAppUsage
4473         protected OnLongClickListener mOnLongClickListener;
4474 
4475         /**
4476          * Listener used to dispatch context click events. This field should be made private, so it
4477          * is hidden from the SDK.
4478          * {@hide}
4479          */
4480         protected OnContextClickListener mOnContextClickListener;
4481 
4482         /**
4483          * Listener used to build the context menu.
4484          * This field should be made private, so it is hidden from the SDK.
4485          * {@hide}
4486          */
4487         @UnsupportedAppUsage
4488         protected OnCreateContextMenuListener mOnCreateContextMenuListener;
4489 
4490         @UnsupportedAppUsage
4491         private OnKeyListener mOnKeyListener;
4492 
4493         @UnsupportedAppUsage
4494         private OnTouchListener mOnTouchListener;
4495 
4496         @UnsupportedAppUsage
4497         private OnHoverListener mOnHoverListener;
4498 
4499         @UnsupportedAppUsage
4500         private OnGenericMotionListener mOnGenericMotionListener;
4501 
4502         @UnsupportedAppUsage
4503         private OnDragListener mOnDragListener;
4504 
4505         private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
4506 
4507         OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
4508 
4509         OnCapturedPointerListener mOnCapturedPointerListener;
4510 
4511         private ArrayList<OnUnhandledKeyEventListener> mUnhandledKeyListeners;
4512 
4513         private WindowInsetsAnimationListener mWindowInsetsAnimationListener;
4514 
4515         /**
4516          * This lives here since it's only valid for interactive views.
4517          */
4518         private List<Rect> mSystemGestureExclusionRects;
4519 
4520         /**
4521          * Used to track {@link #mSystemGestureExclusionRects}
4522          */
4523         public RenderNode.PositionUpdateListener mPositionUpdateListener;
4524     }
4525 
4526     @UnsupportedAppUsage
4527     ListenerInfo mListenerInfo;
4528 
4529     private static class TooltipInfo {
4530         /**
4531          * Text to be displayed in a tooltip popup.
4532          */
4533         @Nullable
4534         CharSequence mTooltipText;
4535 
4536         /**
4537          * View-relative position of the tooltip anchor point.
4538          */
4539         int mAnchorX;
4540         int mAnchorY;
4541 
4542         /**
4543          * The tooltip popup.
4544          */
4545         @Nullable
4546         TooltipPopup mTooltipPopup;
4547 
4548         /**
4549          * Set to true if the tooltip was shown as a result of a long click.
4550          */
4551         boolean mTooltipFromLongClick;
4552 
4553         /**
4554          * Keep these Runnables so that they can be used to reschedule.
4555          */
4556         Runnable mShowTooltipRunnable;
4557         Runnable mHideTooltipRunnable;
4558 
4559         /**
4560          * Hover move is ignored if it is within this distance in pixels from the previous one.
4561          */
4562         int mHoverSlop;
4563 
4564         /**
4565          * Update the anchor position if it significantly (that is by at least mHoverSlop)
4566          * different from the previously stored position. Ignoring insignificant changes
4567          * filters out the jitter which is typical for such input sources as stylus.
4568          *
4569          * @return True if the position has been updated.
4570          */
updateAnchorPos(MotionEvent event)4571         private boolean updateAnchorPos(MotionEvent event) {
4572             final int newAnchorX = (int) event.getX();
4573             final int newAnchorY = (int) event.getY();
4574             if (Math.abs(newAnchorX - mAnchorX) <= mHoverSlop
4575                     && Math.abs(newAnchorY - mAnchorY) <= mHoverSlop) {
4576                 return false;
4577             }
4578             mAnchorX = newAnchorX;
4579             mAnchorY = newAnchorY;
4580             return true;
4581         }
4582 
4583         /**
4584          *  Clear the anchor position to ensure that the next change is considered significant.
4585          */
clearAnchorPos()4586         private void clearAnchorPos() {
4587             mAnchorX = Integer.MAX_VALUE;
4588             mAnchorY = Integer.MAX_VALUE;
4589         }
4590     }
4591 
4592     TooltipInfo mTooltipInfo;
4593 
4594     // Temporary values used to hold (x,y) coordinates when delegating from the
4595     // two-arg performLongClick() method to the legacy no-arg version.
4596     private float mLongClickX = Float.NaN;
4597     private float mLongClickY = Float.NaN;
4598 
4599     /**
4600      * The application environment this view lives in.
4601      * This field should be made private, so it is hidden from the SDK.
4602      * {@hide}
4603      */
4604     @ViewDebug.ExportedProperty(deepExport = true)
4605     @UnsupportedAppUsage
4606     protected Context mContext;
4607 
4608     @UnsupportedAppUsage
4609     private final Resources mResources;
4610 
4611     @UnsupportedAppUsage
4612     private ScrollabilityCache mScrollCache;
4613 
4614     private int[] mDrawableState = null;
4615 
4616     ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
4617 
4618     /**
4619      * Animator that automatically runs based on state changes.
4620      */
4621     private StateListAnimator mStateListAnimator;
4622 
4623     /**
4624      * When this view has focus and the next focus is {@link #FOCUS_LEFT},
4625      * the user may specify which view to go to next.
4626      */
4627     private int mNextFocusLeftId = View.NO_ID;
4628 
4629     /**
4630      * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
4631      * the user may specify which view to go to next.
4632      */
4633     private int mNextFocusRightId = View.NO_ID;
4634 
4635     /**
4636      * When this view has focus and the next focus is {@link #FOCUS_UP},
4637      * the user may specify which view to go to next.
4638      */
4639     private int mNextFocusUpId = View.NO_ID;
4640 
4641     /**
4642      * When this view has focus and the next focus is {@link #FOCUS_DOWN},
4643      * the user may specify which view to go to next.
4644      */
4645     private int mNextFocusDownId = View.NO_ID;
4646 
4647     /**
4648      * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
4649      * the user may specify which view to go to next.
4650      */
4651     int mNextFocusForwardId = View.NO_ID;
4652 
4653     /**
4654      * User-specified next keyboard navigation cluster in the {@link #FOCUS_FORWARD} direction.
4655      *
4656      * @see #findUserSetNextKeyboardNavigationCluster(View, int)
4657      */
4658     int mNextClusterForwardId = View.NO_ID;
4659 
4660     /**
4661      * Whether this View should use a default focus highlight when it gets focused but doesn't
4662      * have {@link android.R.attr#state_focused} defined in its background.
4663      */
4664     boolean mDefaultFocusHighlightEnabled = true;
4665 
4666     private CheckForLongPress mPendingCheckForLongPress;
4667     @UnsupportedAppUsage
4668     private CheckForTap mPendingCheckForTap = null;
4669     private PerformClick mPerformClick;
4670     private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
4671 
4672     private UnsetPressedState mUnsetPressedState;
4673 
4674     /**
4675      * Whether the long press's action has been invoked.  The tap's action is invoked on the
4676      * up event while a long press is invoked as soon as the long press duration is reached, so
4677      * a long press could be performed before the tap is checked, in which case the tap's action
4678      * should not be invoked.
4679      */
4680     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
4681     private boolean mHasPerformedLongPress;
4682 
4683     /**
4684      * Whether a context click button is currently pressed down. This is true when the stylus is
4685      * touching the screen and the primary button has been pressed, or if a mouse's right button is
4686      * pressed. This is false once the button is released or if the stylus has been lifted.
4687      */
4688     private boolean mInContextButtonPress;
4689 
4690     /**
4691      * Whether the next up event should be ignored for the purposes of gesture recognition. This is
4692      * true after a stylus button press has occured, when the next up event should not be recognized
4693      * as a tap.
4694      */
4695     private boolean mIgnoreNextUpEvent;
4696 
4697     /**
4698      * The minimum height of the view. We'll try our best to have the height
4699      * of this view to at least this amount.
4700      */
4701     @ViewDebug.ExportedProperty(category = "measurement")
4702     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4703     private int mMinHeight;
4704 
4705     /**
4706      * The minimum width of the view. We'll try our best to have the width
4707      * of this view to at least this amount.
4708      */
4709     @ViewDebug.ExportedProperty(category = "measurement")
4710     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4711     private int mMinWidth;
4712 
4713     /**
4714      * The delegate to handle touch events that are physically in this view
4715      * but should be handled by another view.
4716      */
4717     private TouchDelegate mTouchDelegate = null;
4718 
4719     /**
4720      * While touch exploration is in use, set to true when hovering across boundaries and
4721      * inside the touch area of the delegate at receiving {@link MotionEvent#ACTION_HOVER_ENTER}
4722      * or {@link MotionEvent#ACTION_HOVER_MOVE}. False when leaving boundaries or receiving a
4723      * {@link MotionEvent#ACTION_HOVER_EXIT}.
4724      * Note that children of view group are excluded in the touch area.
4725      * @see #dispatchTouchExplorationHoverEvent
4726      */
4727     private boolean mHoveringTouchDelegate = false;
4728 
4729     /**
4730      * Solid color to use as a background when creating the drawing cache. Enables
4731      * the cache to use 16 bit bitmaps instead of 32 bit.
4732      */
4733     private int mDrawingCacheBackgroundColor = 0;
4734 
4735     /**
4736      * Special tree observer used when mAttachInfo is null.
4737      */
4738     private ViewTreeObserver mFloatingTreeObserver;
4739 
4740     /**
4741      * Cache the touch slop from the context that created the view.
4742      */
4743     private int mTouchSlop;
4744 
4745     /**
4746      * Object that handles automatic animation of view properties.
4747      */
4748     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
4749     private ViewPropertyAnimator mAnimator = null;
4750 
4751     /**
4752      * List of registered FrameMetricsObservers.
4753      */
4754     private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
4755 
4756     /**
4757      * Flag indicating that a drag can cross window boundaries.  When
4758      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
4759      * with this flag set, all visible applications with targetSdkVersion >=
4760      * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
4761      * in the drag operation and receive the dragged content.
4762      *
4763      * <p>If this is the only flag set, then the drag recipient will only have access to text data
4764      * and intents contained in the {@link ClipData} object. Access to URIs contained in the
4765      * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p>
4766      */
4767     public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
4768 
4769     /**
4770      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
4771      * request read access to the content URI(s) contained in the {@link ClipData} object.
4772      * @see android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION
4773      */
4774     public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
4775 
4776     /**
4777      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
4778      * request write access to the content URI(s) contained in the {@link ClipData} object.
4779      * @see android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION
4780      */
4781     public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
4782 
4783     /**
4784      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
4785      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
4786      * reboots until explicitly revoked with
4787      * {@link android.content.Context#revokeUriPermission(Uri, int)} Context.revokeUriPermission}.
4788      * @see android.content.Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION
4789      */
4790     public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
4791             Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
4792 
4793     /**
4794      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
4795      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
4796      * match against the original granted URI.
4797      * @see android.content.Intent#FLAG_GRANT_PREFIX_URI_PERMISSION
4798      */
4799     public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
4800             Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
4801 
4802     /**
4803      * Flag indicating that the drag shadow will be opaque.  When
4804      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
4805      * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
4806      */
4807     public static final int DRAG_FLAG_OPAQUE = 1 << 9;
4808 
4809     /**
4810      * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
4811      */
4812     private float mVerticalScrollFactor;
4813 
4814     /**
4815      * Position of the vertical scroll bar.
4816      */
4817     @UnsupportedAppUsage
4818     private int mVerticalScrollbarPosition;
4819 
4820     /**
4821      * Position the scroll bar at the default position as determined by the system.
4822      */
4823     public static final int SCROLLBAR_POSITION_DEFAULT = 0;
4824 
4825     /**
4826      * Position the scroll bar along the left edge.
4827      */
4828     public static final int SCROLLBAR_POSITION_LEFT = 1;
4829 
4830     /**
4831      * Position the scroll bar along the right edge.
4832      */
4833     public static final int SCROLLBAR_POSITION_RIGHT = 2;
4834 
4835     /**
4836      * Indicates that the view does not have a layer.
4837      *
4838      * @see #getLayerType()
4839      * @see #setLayerType(int, android.graphics.Paint)
4840      * @see #LAYER_TYPE_SOFTWARE
4841      * @see #LAYER_TYPE_HARDWARE
4842      */
4843     public static final int LAYER_TYPE_NONE = 0;
4844 
4845     /**
4846      * <p>Indicates that the view has a software layer. A software layer is backed
4847      * by a bitmap and causes the view to be rendered using Android's software
4848      * rendering pipeline, even if hardware acceleration is enabled.</p>
4849      *
4850      * <p>Software layers have various usages:</p>
4851      * <p>When the application is not using hardware acceleration, a software layer
4852      * is useful to apply a specific color filter and/or blending mode and/or
4853      * translucency to a view and all its children.</p>
4854      * <p>When the application is using hardware acceleration, a software layer
4855      * is useful to render drawing primitives not supported by the hardware
4856      * accelerated pipeline. It can also be used to cache a complex view tree
4857      * into a texture and reduce the complexity of drawing operations. For instance,
4858      * when animating a complex view tree with a translation, a software layer can
4859      * be used to render the view tree only once.</p>
4860      * <p>Software layers should be avoided when the affected view tree updates
4861      * often. Every update will require to re-render the software layer, which can
4862      * potentially be slow (particularly when hardware acceleration is turned on
4863      * since the layer will have to be uploaded into a hardware texture after every
4864      * update.)</p>
4865      *
4866      * @see #getLayerType()
4867      * @see #setLayerType(int, android.graphics.Paint)
4868      * @see #LAYER_TYPE_NONE
4869      * @see #LAYER_TYPE_HARDWARE
4870      */
4871     public static final int LAYER_TYPE_SOFTWARE = 1;
4872 
4873     /**
4874      * <p>Indicates that the view has a hardware layer. A hardware layer is backed
4875      * by a hardware specific texture (generally Frame Buffer Objects or FBO on
4876      * OpenGL hardware) and causes the view to be rendered using Android's hardware
4877      * rendering pipeline, but only if hardware acceleration is turned on for the
4878      * view hierarchy. When hardware acceleration is turned off, hardware layers
4879      * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
4880      *
4881      * <p>A hardware layer is useful to apply a specific color filter and/or
4882      * blending mode and/or translucency to a view and all its children.</p>
4883      * <p>A hardware layer can be used to cache a complex view tree into a
4884      * texture and reduce the complexity of drawing operations. For instance,
4885      * when animating a complex view tree with a translation, a hardware layer can
4886      * be used to render the view tree only once.</p>
4887      * <p>A hardware layer can also be used to increase the rendering quality when
4888      * rotation transformations are applied on a view. It can also be used to
4889      * prevent potential clipping issues when applying 3D transforms on a view.</p>
4890      *
4891      * @see #getLayerType()
4892      * @see #setLayerType(int, android.graphics.Paint)
4893      * @see #LAYER_TYPE_NONE
4894      * @see #LAYER_TYPE_SOFTWARE
4895      */
4896     public static final int LAYER_TYPE_HARDWARE = 2;
4897 
4898     /** @hide */
4899     @IntDef(prefix = { "LAYER_TYPE_" }, value = {
4900             LAYER_TYPE_NONE,
4901             LAYER_TYPE_SOFTWARE,
4902             LAYER_TYPE_HARDWARE
4903     })
4904     @Retention(RetentionPolicy.SOURCE)
4905     public @interface LayerType {}
4906 
4907     @ViewDebug.ExportedProperty(category = "drawing", mapping = {
4908             @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
4909             @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
4910             @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
4911     })
4912     int mLayerType = LAYER_TYPE_NONE;
4913     Paint mLayerPaint;
4914 
4915     /**
4916      * Set to true when drawing cache is enabled and cannot be created.
4917      *
4918      * @hide
4919      */
4920     @UnsupportedAppUsage
4921     public boolean mCachingFailed;
4922     @UnsupportedAppUsage
4923     private Bitmap mDrawingCache;
4924     @UnsupportedAppUsage
4925     private Bitmap mUnscaledDrawingCache;
4926 
4927     /**
4928      * RenderNode holding View properties, potentially holding a DisplayList of View content.
4929      * <p>
4930      * When non-null and valid, this is expected to contain an up-to-date copy
4931      * of the View content. Its DisplayList content is cleared on temporary detach and reset on
4932      * cleanup.
4933      */
4934     @UnsupportedAppUsage
4935     final RenderNode mRenderNode;
4936 
4937     /**
4938      * Set to true when the view is sending hover accessibility events because it
4939      * is the innermost hovered view.
4940      */
4941     private boolean mSendingHoverAccessibilityEvents;
4942 
4943     /**
4944      * Delegate for injecting accessibility functionality.
4945      */
4946     @UnsupportedAppUsage
4947     AccessibilityDelegate mAccessibilityDelegate;
4948 
4949     /**
4950      * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
4951      * and add/remove objects to/from the overlay directly through the Overlay methods.
4952      */
4953     ViewOverlay mOverlay;
4954 
4955     /**
4956      * The currently active parent view for receiving delegated nested scrolling events.
4957      * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
4958      * by {@link #stopNestedScroll()} at the same point where we clear
4959      * requestDisallowInterceptTouchEvent.
4960      */
4961     private ViewParent mNestedScrollingParent;
4962 
4963     /**
4964      * Consistency verifier for debugging purposes.
4965      * @hide
4966      */
4967     protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
4968             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
4969                     new InputEventConsistencyVerifier(this, 0) : null;
4970 
4971     private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
4972 
4973     private int[] mTempNestedScrollConsumed;
4974 
4975     /**
4976      * An overlay is going to draw this View instead of being drawn as part of this
4977      * View's parent. mGhostView is the View in the Overlay that must be invalidated
4978      * when this view is invalidated.
4979      */
4980     GhostView mGhostView;
4981 
4982     /**
4983      * Holds pairs of adjacent attribute data: attribute name followed by its value.
4984      * @hide
4985      */
4986     @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
4987     public String[] mAttributes;
4988 
4989     /**
4990      * Maps a Resource id to its name.
4991      */
4992     private static SparseArray<String> mAttributeMap;
4993 
4994     /**
4995      * Queue of pending runnables. Used to postpone calls to post() until this
4996      * view is attached and has a handler.
4997      */
4998     private HandlerActionQueue mRunQueue;
4999 
5000     /**
5001      * The pointer icon when the mouse hovers on this view. The default is null.
5002      */
5003     private PointerIcon mPointerIcon;
5004 
5005     /**
5006      * @hide
5007      */
5008     @UnsupportedAppUsage
5009     String mStartActivityRequestWho;
5010 
5011     @Nullable
5012     private RoundScrollbarRenderer mRoundScrollbarRenderer;
5013 
5014     /** Used to delay visibility updates sent to the autofill manager */
5015     private Handler mVisibilityChangeForAutofillHandler;
5016 
5017     /**
5018      * Used when app developers explicitly set the {@link ContentCaptureSession} associated with the
5019      * view (through {@link #setContentCaptureSession(ContentCaptureSession)}.
5020      */
5021     @Nullable
5022     private ContentCaptureSession mContentCaptureSession;
5023 
5024     @LayoutRes
5025     private int mSourceLayoutId = ID_NULL;
5026 
5027     @Nullable
5028     private SparseIntArray mAttributeSourceResId;
5029 
5030     @Nullable
5031     private SparseArray<int[]> mAttributeResolutionStacks;
5032 
5033     @StyleRes
5034     private int mExplicitStyle;
5035 
5036     /**
5037      * Cached reference to the {@link ContentCaptureSession}, is reset on {@link #invalidate()}.
5038      */
5039     private ContentCaptureSession mCachedContentCaptureSession;
5040 
5041     /**
5042      * Simple constructor to use when creating a view from code.
5043      *
5044      * @param context The Context the view is running in, through which it can
5045      *        access the current theme, resources, etc.
5046      */
View(Context context)5047     public View(Context context) {
5048         mContext = context;
5049         mResources = context != null ? context.getResources() : null;
5050         mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | FOCUSABLE_AUTO;
5051         // Set some flags defaults
5052         mPrivateFlags2 =
5053                 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
5054                 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
5055                 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
5056                 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
5057                 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
5058                 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
5059         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
5060         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
5061         mUserPaddingStart = UNDEFINED_PADDING;
5062         mUserPaddingEnd = UNDEFINED_PADDING;
5063         mRenderNode = RenderNode.create(getClass().getName(), new ViewAnimationHostBridge(this));
5064 
5065         if (!sCompatibilityDone && context != null) {
5066             final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
5067 
5068             // Older apps may need this compatibility hack for measurement.
5069             sUseBrokenMakeMeasureSpec = targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1;
5070 
5071             // Older apps expect onMeasure() to always be called on a layout pass, regardless
5072             // of whether a layout was requested on that View.
5073             sIgnoreMeasureCache = targetSdkVersion < Build.VERSION_CODES.KITKAT;
5074 
5075             Canvas.sCompatibilityRestore = targetSdkVersion < Build.VERSION_CODES.M;
5076             Canvas.sCompatibilitySetBitmap = targetSdkVersion < Build.VERSION_CODES.O;
5077             Canvas.setCompatibilityVersion(targetSdkVersion);
5078 
5079             // In M and newer, our widgets can pass a "hint" value in the size
5080             // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
5081             // know what the expected parent size is going to be, so e.g. list items can size
5082             // themselves at 1/3 the size of their container. It breaks older apps though,
5083             // specifically apps that use some popular open source libraries.
5084             sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < Build.VERSION_CODES.M;
5085 
5086             // Old versions of the platform would give different results from
5087             // LinearLayout measurement passes using EXACTLY and non-EXACTLY
5088             // modes, so we always need to run an additional EXACTLY pass.
5089             sAlwaysRemeasureExactly = targetSdkVersion <= Build.VERSION_CODES.M;
5090 
5091             // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
5092             // On N+, we throw, but that breaks compatibility with apps that use these methods.
5093             sTextureViewIgnoresDrawableSetters = targetSdkVersion <= Build.VERSION_CODES.M;
5094 
5095             // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
5096             // in apps so we target check it to avoid breaking existing apps.
5097             sPreserveMarginParamsInLayoutParamConversion =
5098                     targetSdkVersion >= Build.VERSION_CODES.N;
5099 
5100             sCascadedDragDrop = targetSdkVersion < Build.VERSION_CODES.N;
5101 
5102             sHasFocusableExcludeAutoFocusable = targetSdkVersion < Build.VERSION_CODES.O;
5103 
5104             sAutoFocusableOffUIThreadWontNotifyParents = targetSdkVersion < Build.VERSION_CODES.O;
5105 
5106             sUseDefaultFocusHighlight = context.getResources().getBoolean(
5107                     com.android.internal.R.bool.config_useDefaultFocusHighlight);
5108 
5109             sThrowOnInvalidFloatProperties = targetSdkVersion >= Build.VERSION_CODES.P;
5110 
5111             sCanFocusZeroSized = targetSdkVersion < Build.VERSION_CODES.P;
5112 
5113             sAlwaysAssignFocus = targetSdkVersion < Build.VERSION_CODES.P;
5114 
5115             sAcceptZeroSizeDragShadow = targetSdkVersion < Build.VERSION_CODES.P;
5116 
5117             sBrokenInsetsDispatch = ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_FULL
5118                     || targetSdkVersion < Build.VERSION_CODES.Q;
5119 
5120             sBrokenWindowBackground = targetSdkVersion < Build.VERSION_CODES.Q;
5121 
5122             sCompatibilityDone = true;
5123         }
5124     }
5125 
5126     /**
5127      * Constructor that is called when inflating a view from XML. This is called
5128      * when a view is being constructed from an XML file, supplying attributes
5129      * that were specified in the XML file. This version uses a default style of
5130      * 0, so the only attribute values applied are those in the Context's Theme
5131      * and the given AttributeSet.
5132      *
5133      * <p>
5134      * The method onFinishInflate() will be called after all children have been
5135      * added.
5136      *
5137      * @param context The Context the view is running in, through which it can
5138      *        access the current theme, resources, etc.
5139      * @param attrs The attributes of the XML tag that is inflating the view.
5140      * @see #View(Context, AttributeSet, int)
5141      */
5142     public View(Context context, @Nullable AttributeSet attrs) {
5143         this(context, attrs, 0);
5144     }
5145 
5146     /**
5147      * Perform inflation from XML and apply a class-specific base style from a
5148      * theme attribute. This constructor of View allows subclasses to use their
5149      * own base style when they are inflating. For example, a Button class's
5150      * constructor would call this version of the super class constructor and
5151      * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
5152      * allows the theme's button style to modify all of the base view attributes
5153      * (in particular its background) as well as the Button class's attributes.
5154      *
5155      * @param context The Context the view is running in, through which it can
5156      *        access the current theme, resources, etc.
5157      * @param attrs The attributes of the XML tag that is inflating the view.
5158      * @param defStyleAttr An attribute in the current theme that contains a
5159      *        reference to a style resource that supplies default values for
5160      *        the view. Can be 0 to not look for defaults.
5161      * @see #View(Context, AttributeSet)
5162      */
5163     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
5164         this(context, attrs, defStyleAttr, 0);
5165     }
5166 
5167     /**
5168      * Perform inflation from XML and apply a class-specific base style from a
5169      * theme attribute or style resource. This constructor of View allows
5170      * subclasses to use their own base style when they are inflating.
5171      * <p>
5172      * When determining the final value of a particular attribute, there are
5173      * four inputs that come into play:
5174      * <ol>
5175      * <li>Any attribute values in the given AttributeSet.
5176      * <li>The style resource specified in the AttributeSet (named "style").
5177      * <li>The default style specified by <var>defStyleAttr</var>.
5178      * <li>The default style specified by <var>defStyleRes</var>.
5179      * <li>The base values in this theme.
5180      * </ol>
5181      * <p>
5182      * Each of these inputs is considered in-order, with the first listed taking
5183      * precedence over the following ones. In other words, if in the
5184      * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
5185      * , then the button's text will <em>always</em> be black, regardless of
5186      * what is specified in any of the styles.
5187      *
5188      * @param context The Context the view is running in, through which it can
5189      *        access the current theme, resources, etc.
5190      * @param attrs The attributes of the XML tag that is inflating the view.
5191      * @param defStyleAttr An attribute in the current theme that contains a
5192      *        reference to a style resource that supplies default values for
5193      *        the view. Can be 0 to not look for defaults.
5194      * @param defStyleRes A resource identifier of a style resource that
5195      *        supplies default values for the view, used only if
5196      *        defStyleAttr is 0 or can not be found in the theme. Can be 0
5197      *        to not look for defaults.
5198      * @see #View(Context, AttributeSet, int)
5199      */
5200     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
5201         this(context);
5202 
5203         mSourceLayoutId = Resources.getAttributeSetSourceResId(attrs);
5204 
5205         final TypedArray a = context.obtainStyledAttributes(
5206                 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
5207 
5208         retrieveExplicitStyle(context.getTheme(), attrs);
5209         saveAttributeDataForStyleable(context, com.android.internal.R.styleable.View, attrs, a,
5210                 defStyleAttr, defStyleRes);
5211 
5212         if (sDebugViewAttributes) {
5213             saveAttributeData(attrs, a);
5214         }
5215 
5216         Drawable background = null;
5217 
5218         int leftPadding = -1;
5219         int topPadding = -1;
5220         int rightPadding = -1;
5221         int bottomPadding = -1;
5222         int startPadding = UNDEFINED_PADDING;
5223         int endPadding = UNDEFINED_PADDING;
5224 
5225         int padding = -1;
5226         int paddingHorizontal = -1;
5227         int paddingVertical = -1;
5228 
5229         int viewFlagValues = 0;
5230         int viewFlagMasks = 0;
5231 
5232         boolean setScrollContainer = false;
5233 
5234         int x = 0;
5235         int y = 0;
5236 
5237         float tx = 0;
5238         float ty = 0;
5239         float tz = 0;
5240         float elevation = 0;
5241         float rotation = 0;
5242         float rotationX = 0;
5243         float rotationY = 0;
5244         float sx = 1f;
5245         float sy = 1f;
5246         boolean transformSet = false;
5247 
5248         int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
5249         int overScrollMode = mOverScrollMode;
5250         boolean initializeScrollbars = false;
5251         boolean initializeScrollIndicators = false;
5252 
5253         boolean startPaddingDefined = false;
5254         boolean endPaddingDefined = false;
5255         boolean leftPaddingDefined = false;
5256         boolean rightPaddingDefined = false;
5257 
5258         final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
5259 
5260         // Set default values.
5261         viewFlagValues |= FOCUSABLE_AUTO;
5262         viewFlagMasks |= FOCUSABLE_AUTO;
5263 
5264         final int N = a.getIndexCount();
5265         for (int i = 0; i < N; i++) {
5266             int attr = a.getIndex(i);
5267             switch (attr) {
5268                 case com.android.internal.R.styleable.View_background:
5269                     background = a.getDrawable(attr);
5270                     break;
5271                 case com.android.internal.R.styleable.View_padding:
5272                     padding = a.getDimensionPixelSize(attr, -1);
5273                     mUserPaddingLeftInitial = padding;
5274                     mUserPaddingRightInitial = padding;
5275                     leftPaddingDefined = true;
5276                     rightPaddingDefined = true;
5277                     break;
5278                 case com.android.internal.R.styleable.View_paddingHorizontal:
5279                     paddingHorizontal = a.getDimensionPixelSize(attr, -1);
5280                     mUserPaddingLeftInitial = paddingHorizontal;
5281                     mUserPaddingRightInitial = paddingHorizontal;
5282                     leftPaddingDefined = true;
5283                     rightPaddingDefined = true;
5284                     break;
5285                 case com.android.internal.R.styleable.View_paddingVertical:
5286                     paddingVertical = a.getDimensionPixelSize(attr, -1);
5287                     break;
5288                 case com.android.internal.R.styleable.View_paddingLeft:
5289                     leftPadding = a.getDimensionPixelSize(attr, -1);
5290                     mUserPaddingLeftInitial = leftPadding;
5291                     leftPaddingDefined = true;
5292                     break;
5293                 case com.android.internal.R.styleable.View_paddingTop:
5294                     topPadding = a.getDimensionPixelSize(attr, -1);
5295                     break;
5296                 case com.android.internal.R.styleable.View_paddingRight:
5297                     rightPadding = a.getDimensionPixelSize(attr, -1);
5298                     mUserPaddingRightInitial = rightPadding;
5299                     rightPaddingDefined = true;
5300                     break;
5301                 case com.android.internal.R.styleable.View_paddingBottom:
5302                     bottomPadding = a.getDimensionPixelSize(attr, -1);
5303                     break;
5304                 case com.android.internal.R.styleable.View_paddingStart:
5305                     startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
5306                     startPaddingDefined = (startPadding != UNDEFINED_PADDING);
5307                     break;
5308                 case com.android.internal.R.styleable.View_paddingEnd:
5309                     endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
5310                     endPaddingDefined = (endPadding != UNDEFINED_PADDING);
5311                     break;
5312                 case com.android.internal.R.styleable.View_scrollX:
5313                     x = a.getDimensionPixelOffset(attr, 0);
5314                     break;
5315                 case com.android.internal.R.styleable.View_scrollY:
5316                     y = a.getDimensionPixelOffset(attr, 0);
5317                     break;
5318                 case com.android.internal.R.styleable.View_alpha:
5319                     setAlpha(a.getFloat(attr, 1f));
5320                     break;
5321                 case com.android.internal.R.styleable.View_transformPivotX:
5322                     setPivotX(a.getDimension(attr, 0));
5323                     break;
5324                 case com.android.internal.R.styleable.View_transformPivotY:
5325                     setPivotY(a.getDimension(attr, 0));
5326                     break;
5327                 case com.android.internal.R.styleable.View_translationX:
5328                     tx = a.getDimension(attr, 0);
5329                     transformSet = true;
5330                     break;
5331                 case com.android.internal.R.styleable.View_translationY:
5332                     ty = a.getDimension(attr, 0);
5333                     transformSet = true;
5334                     break;
5335                 case com.android.internal.R.styleable.View_translationZ:
5336                     tz = a.getDimension(attr, 0);
5337                     transformSet = true;
5338                     break;
5339                 case com.android.internal.R.styleable.View_elevation:
5340                     elevation = a.getDimension(attr, 0);
5341                     transformSet = true;
5342                     break;
5343                 case com.android.internal.R.styleable.View_rotation:
5344                     rotation = a.getFloat(attr, 0);
5345                     transformSet = true;
5346                     break;
5347                 case com.android.internal.R.styleable.View_rotationX:
5348                     rotationX = a.getFloat(attr, 0);
5349                     transformSet = true;
5350                     break;
5351                 case com.android.internal.R.styleable.View_rotationY:
5352                     rotationY = a.getFloat(attr, 0);
5353                     transformSet = true;
5354                     break;
5355                 case com.android.internal.R.styleable.View_scaleX:
5356                     sx = a.getFloat(attr, 1f);
5357                     transformSet = true;
5358                     break;
5359                 case com.android.internal.R.styleable.View_scaleY:
5360                     sy = a.getFloat(attr, 1f);
5361                     transformSet = true;
5362                     break;
5363                 case com.android.internal.R.styleable.View_id:
5364                     mID = a.getResourceId(attr, NO_ID);
5365                     break;
5366                 case com.android.internal.R.styleable.View_tag:
5367                     mTag = a.getText(attr);
5368                     break;
5369                 case com.android.internal.R.styleable.View_fitsSystemWindows:
5370                     if (a.getBoolean(attr, false)) {
5371                         viewFlagValues |= FITS_SYSTEM_WINDOWS;
5372                         viewFlagMasks |= FITS_SYSTEM_WINDOWS;
5373                     }
5374                     break;
5375                 case com.android.internal.R.styleable.View_focusable:
5376                     viewFlagValues = (viewFlagValues & ~FOCUSABLE_MASK) | getFocusableAttribute(a);
5377                     if ((viewFlagValues & FOCUSABLE_AUTO) == 0) {
5378                         viewFlagMasks |= FOCUSABLE_MASK;
5379                     }
5380                     break;
5381                 case com.android.internal.R.styleable.View_focusableInTouchMode:
5382                     if (a.getBoolean(attr, false)) {
5383                         // unset auto focus since focusableInTouchMode implies explicit focusable
5384                         viewFlagValues &= ~FOCUSABLE_AUTO;
5385                         viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
5386                         viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
5387                     }
5388                     break;
5389                 case com.android.internal.R.styleable.View_clickable:
5390                     if (a.getBoolean(attr, false)) {
5391                         viewFlagValues |= CLICKABLE;
5392                         viewFlagMasks |= CLICKABLE;
5393                     }
5394                     break;
5395                 case com.android.internal.R.styleable.View_longClickable:
5396                     if (a.getBoolean(attr, false)) {
5397                         viewFlagValues |= LONG_CLICKABLE;
5398                         viewFlagMasks |= LONG_CLICKABLE;
5399                     }
5400                     break;
5401                 case com.android.internal.R.styleable.View_contextClickable:
5402                     if (a.getBoolean(attr, false)) {
5403                         viewFlagValues |= CONTEXT_CLICKABLE;
5404                         viewFlagMasks |= CONTEXT_CLICKABLE;
5405                     }
5406                     break;
5407                 case com.android.internal.R.styleable.View_saveEnabled:
5408                     if (!a.getBoolean(attr, true)) {
5409                         viewFlagValues |= SAVE_DISABLED;
5410                         viewFlagMasks |= SAVE_DISABLED_MASK;
5411                     }
5412                     break;
5413                 case com.android.internal.R.styleable.View_duplicateParentState:
5414                     if (a.getBoolean(attr, false)) {
5415                         viewFlagValues |= DUPLICATE_PARENT_STATE;
5416                         viewFlagMasks |= DUPLICATE_PARENT_STATE;
5417                     }
5418                     break;
5419                 case com.android.internal.R.styleable.View_visibility:
5420                     final int visibility = a.getInt(attr, 0);
5421                     if (visibility != 0) {
5422                         viewFlagValues |= VISIBILITY_FLAGS[visibility];
5423                         viewFlagMasks |= VISIBILITY_MASK;
5424                     }
5425                     break;
5426                 case com.android.internal.R.styleable.View_layoutDirection:
5427                     // Clear any layout direction flags (included resolved bits) already set
5428                     mPrivateFlags2 &=
5429                             ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
5430                     // Set the layout direction flags depending on the value of the attribute
5431                     final int layoutDirection = a.getInt(attr, -1);
5432                     final int value = (layoutDirection != -1) ?
5433                             LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
5434                     mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
5435                     break;
5436                 case com.android.internal.R.styleable.View_drawingCacheQuality:
5437                     final int cacheQuality = a.getInt(attr, 0);
5438                     if (cacheQuality != 0) {
5439                         viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
5440                         viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
5441                     }
5442                     break;
5443                 case com.android.internal.R.styleable.View_contentDescription:
5444                     setContentDescription(a.getString(attr));
5445                     break;
5446                 case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
5447                     setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
5448                     break;
5449                 case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
5450                     setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
5451                     break;
5452                 case com.android.internal.R.styleable.View_labelFor:
5453                     setLabelFor(a.getResourceId(attr, NO_ID));
5454                     break;
5455                 case com.android.internal.R.styleable.View_soundEffectsEnabled:
5456                     if (!a.getBoolean(attr, true)) {
5457                         viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
5458                         viewFlagMasks |= SOUND_EFFECTS_ENABLED;
5459                     }
5460                     break;
5461                 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
5462                     if (!a.getBoolean(attr, true)) {
5463                         viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
5464                         viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
5465                     }
5466                     break;
5467                 case R.styleable.View_scrollbars:
5468                     final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
5469                     if (scrollbars != SCROLLBARS_NONE) {
5470                         viewFlagValues |= scrollbars;
5471                         viewFlagMasks |= SCROLLBARS_MASK;
5472                         initializeScrollbars = true;
5473                     }
5474                     break;
5475                 //noinspection deprecation
5476                 case R.styleable.View_fadingEdge:
5477                     if (targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
5478                         // Ignore the attribute starting with ICS
5479                         break;
5480                     }
5481                     // With builds < ICS, fall through and apply fading edges
5482                 case R.styleable.View_requiresFadingEdge:
5483                     final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
5484                     if (fadingEdge != FADING_EDGE_NONE) {
5485                         viewFlagValues |= fadingEdge;
5486                         viewFlagMasks |= FADING_EDGE_MASK;
5487                         initializeFadingEdgeInternal(a);
5488                     }
5489                     break;
5490                 case R.styleable.View_scrollbarStyle:
5491                     scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
5492                     if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
5493                         viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
5494                         viewFlagMasks |= SCROLLBARS_STYLE_MASK;
5495                     }
5496                     break;
5497                 case R.styleable.View_isScrollContainer:
5498                     setScrollContainer = true;
5499                     if (a.getBoolean(attr, false)) {
5500                         setScrollContainer(true);
5501                     }
5502                     break;
5503                 case com.android.internal.R.styleable.View_keepScreenOn:
5504                     if (a.getBoolean(attr, false)) {
5505                         viewFlagValues |= KEEP_SCREEN_ON;
5506                         viewFlagMasks |= KEEP_SCREEN_ON;
5507                     }
5508                     break;
5509                 case R.styleable.View_filterTouchesWhenObscured:
5510                     if (a.getBoolean(attr, false)) {
5511                         viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
5512                         viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
5513                     }
5514                     break;
5515                 case R.styleable.View_nextFocusLeft:
5516                     mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
5517                     break;
5518                 case R.styleable.View_nextFocusRight:
5519                     mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
5520                     break;
5521                 case R.styleable.View_nextFocusUp:
5522                     mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
5523                     break;
5524                 case R.styleable.View_nextFocusDown:
5525                     mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
5526                     break;
5527                 case R.styleable.View_nextFocusForward:
5528                     mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
5529                     break;
5530                 case R.styleable.View_nextClusterForward:
5531                     mNextClusterForwardId = a.getResourceId(attr, View.NO_ID);
5532                     break;
5533                 case R.styleable.View_minWidth:
5534                     mMinWidth = a.getDimensionPixelSize(attr, 0);
5535                     break;
5536                 case R.styleable.View_minHeight:
5537                     mMinHeight = a.getDimensionPixelSize(attr, 0);
5538                     break;
5539                 case R.styleable.View_onClick:
5540                     if (context.isRestricted()) {
5541                         throw new IllegalStateException("The android:onClick attribute cannot "
5542                                 + "be used within a restricted context");
5543                     }
5544 
5545                     final String handlerName = a.getString(attr);
5546                     if (handlerName != null) {
5547                         setOnClickListener(new DeclaredOnClickListener(this, handlerName));
5548                     }
5549                     break;
5550                 case R.styleable.View_overScrollMode:
5551                     overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
5552                     break;
5553                 case R.styleable.View_verticalScrollbarPosition:
5554                     mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
5555                     break;
5556                 case R.styleable.View_layerType:
5557                     setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
5558                     break;
5559                 case R.styleable.View_textDirection:
5560                     // Clear any text direction flag already set
5561                     mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
5562                     // Set the text direction flags depending on the value of the attribute
5563                     final int textDirection = a.getInt(attr, -1);
5564                     if (textDirection != -1) {
5565                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
5566                     }
5567                     break;
5568                 case R.styleable.View_textAlignment:
5569                     // Clear any text alignment flag already set
5570                     mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
5571                     // Set the text alignment flag depending on the value of the attribute
5572                     final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
5573                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
5574                     break;
5575                 case R.styleable.View_importantForAccessibility:
5576                     setImportantForAccessibility(a.getInt(attr,
5577                             IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
5578                     break;
5579                 case R.styleable.View_accessibilityLiveRegion:
5580                     setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
5581                     break;
5582                 case R.styleable.View_transitionName:
5583                     setTransitionName(a.getString(attr));
5584                     break;
5585                 case R.styleable.View_nestedScrollingEnabled:
5586                     setNestedScrollingEnabled(a.getBoolean(attr, false));
5587                     break;
5588                 case R.styleable.View_stateListAnimator:
5589                     setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
5590                             a.getResourceId(attr, 0)));
5591                     break;
5592                 case R.styleable.View_backgroundTint:
5593                     // This will get applied later during setBackground().
5594                     if (mBackgroundTint == null) {
5595                         mBackgroundTint = new TintInfo();
5596                     }
5597                     mBackgroundTint.mTintList = a.getColorStateList(
5598                             R.styleable.View_backgroundTint);
5599                     mBackgroundTint.mHasTintList = true;
5600                     break;
5601                 case R.styleable.View_backgroundTintMode:
5602                     // This will get applied later during setBackground().
5603                     if (mBackgroundTint == null) {
5604                         mBackgroundTint = new TintInfo();
5605                     }
5606                     mBackgroundTint.mBlendMode = Drawable.parseBlendMode(a.getInt(
5607                             R.styleable.View_backgroundTintMode, -1), null);
5608                     mBackgroundTint.mHasTintMode = true;
5609                     break;
5610                 case R.styleable.View_outlineProvider:
5611                     setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
5612                             PROVIDER_BACKGROUND));
5613                     break;
5614                 case R.styleable.View_foreground:
5615                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5616                         setForeground(a.getDrawable(attr));
5617                     }
5618                     break;
5619                 case R.styleable.View_foregroundGravity:
5620                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5621                         setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
5622                     }
5623                     break;
5624                 case R.styleable.View_foregroundTintMode:
5625                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5626                         setForegroundTintBlendMode(
5627                                 Drawable.parseBlendMode(a.getInt(attr, -1),
5628                                         null));
5629                     }
5630                     break;
5631                 case R.styleable.View_foregroundTint:
5632                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5633                         setForegroundTintList(a.getColorStateList(attr));
5634                     }
5635                     break;
5636                 case R.styleable.View_foregroundInsidePadding:
5637                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5638                         if (mForegroundInfo == null) {
5639                             mForegroundInfo = new ForegroundInfo();
5640                         }
5641                         mForegroundInfo.mInsidePadding = a.getBoolean(attr,
5642                                 mForegroundInfo.mInsidePadding);
5643                     }
5644                     break;
5645                 case R.styleable.View_scrollIndicators:
5646                     final int scrollIndicators =
5647                             (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
5648                                     & SCROLL_INDICATORS_PFLAG3_MASK;
5649                     if (scrollIndicators != 0) {
5650                         mPrivateFlags3 |= scrollIndicators;
5651                         initializeScrollIndicators = true;
5652                     }
5653                     break;
5654                 case R.styleable.View_pointerIcon:
5655                     final int resourceId = a.getResourceId(attr, 0);
5656                     if (resourceId != 0) {
5657                         setPointerIcon(PointerIcon.load(
5658                                 context.getResources(), resourceId));
5659                     } else {
5660                         final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
5661                         if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
5662                             setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
5663                         }
5664                     }
5665                     break;
5666                 case R.styleable.View_forceHasOverlappingRendering:
5667                     if (a.peekValue(attr) != null) {
5668                         forceHasOverlappingRendering(a.getBoolean(attr, true));
5669                     }
5670                     break;
5671                 case R.styleable.View_tooltipText:
5672                     setTooltipText(a.getText(attr));
5673                     break;
5674                 case R.styleable.View_keyboardNavigationCluster:
5675                     if (a.peekValue(attr) != null) {
5676                         setKeyboardNavigationCluster(a.getBoolean(attr, true));
5677                     }
5678                     break;
5679                 case R.styleable.View_focusedByDefault:
5680                     if (a.peekValue(attr) != null) {
5681                         setFocusedByDefault(a.getBoolean(attr, true));
5682                     }
5683                     break;
5684                 case R.styleable.View_autofillHints:
5685                     if (a.peekValue(attr) != null) {
5686                         CharSequence[] rawHints = null;
5687                         String rawString = null;
5688 
5689                         if (a.getType(attr) == TypedValue.TYPE_REFERENCE) {
5690                             int resId = a.getResourceId(attr, 0);
5691 
5692                             try {
5693                                 rawHints = a.getTextArray(attr);
5694                             } catch (Resources.NotFoundException e) {
5695                                 rawString = getResources().getString(resId);
5696                             }
5697                         } else {
5698                             rawString = a.getString(attr);
5699                         }
5700 
5701                         if (rawHints == null) {
5702                             if (rawString == null) {
5703                                 throw new IllegalArgumentException(
5704                                         "Could not resolve autofillHints");
5705                             } else {
5706                                 rawHints = rawString.split(",");
5707                             }
5708                         }
5709 
5710                         String[] hints = new String[rawHints.length];
5711 
5712                         int numHints = rawHints.length;
5713                         for (int rawHintNum = 0; rawHintNum < numHints; rawHintNum++) {
5714                             hints[rawHintNum] = rawHints[rawHintNum].toString().trim();
5715                         }
5716                         setAutofillHints(hints);
5717                     }
5718                     break;
5719                 case R.styleable.View_importantForAutofill:
5720                     if (a.peekValue(attr) != null) {
5721                         setImportantForAutofill(a.getInt(attr, IMPORTANT_FOR_AUTOFILL_AUTO));
5722                     }
5723                     break;
5724                 case R.styleable.View_defaultFocusHighlightEnabled:
5725                     if (a.peekValue(attr) != null) {
5726                         setDefaultFocusHighlightEnabled(a.getBoolean(attr, true));
5727                     }
5728                     break;
5729                 case R.styleable.View_screenReaderFocusable:
5730                     if (a.peekValue(attr) != null) {
5731                         setScreenReaderFocusable(a.getBoolean(attr, false));
5732                     }
5733                     break;
5734                 case R.styleable.View_accessibilityPaneTitle:
5735                     if (a.peekValue(attr) != null) {
5736                         setAccessibilityPaneTitle(a.getString(attr));
5737                     }
5738                     break;
5739                 case R.styleable.View_outlineSpotShadowColor:
5740                     setOutlineSpotShadowColor(a.getColor(attr, Color.BLACK));
5741                     break;
5742                 case R.styleable.View_outlineAmbientShadowColor:
5743                     setOutlineAmbientShadowColor(a.getColor(attr, Color.BLACK));
5744                     break;
5745                 case com.android.internal.R.styleable.View_accessibilityHeading:
5746                     setAccessibilityHeading(a.getBoolean(attr, false));
5747                     break;
5748                 case R.styleable.View_forceDarkAllowed:
5749                     mRenderNode.setForceDarkAllowed(a.getBoolean(attr, true));
5750                     break;
5751             }
5752         }
5753 
5754         setOverScrollMode(overScrollMode);
5755 
5756         // Cache start/end user padding as we cannot fully resolve padding here (we don't have yet
5757         // the resolved layout direction). Those cached values will be used later during padding
5758         // resolution.
5759         mUserPaddingStart = startPadding;
5760         mUserPaddingEnd = endPadding;
5761 
5762         if (background != null) {
5763             setBackground(background);
5764         }
5765 
5766         // setBackground above will record that padding is currently provided by the background.
5767         // If we have padding specified via xml, record that here instead and use it.
5768         mLeftPaddingDefined = leftPaddingDefined;
5769         mRightPaddingDefined = rightPaddingDefined;
5770 
5771         // Valid paddingHorizontal/paddingVertical beats leftPadding, rightPadding, topPadding,
5772         // bottomPadding, and padding set by background.  Valid padding beats everything.
5773         if (padding >= 0) {
5774             leftPadding = padding;
5775             topPadding = padding;
5776             rightPadding = padding;
5777             bottomPadding = padding;
5778             mUserPaddingLeftInitial = padding;
5779             mUserPaddingRightInitial = padding;
5780         } else {
5781             if (paddingHorizontal >= 0) {
5782                 leftPadding = paddingHorizontal;
5783                 rightPadding = paddingHorizontal;
5784                 mUserPaddingLeftInitial = paddingHorizontal;
5785                 mUserPaddingRightInitial = paddingHorizontal;
5786             }
5787             if (paddingVertical >= 0) {
5788                 topPadding = paddingVertical;
5789                 bottomPadding = paddingVertical;
5790             }
5791         }
5792 
5793         if (isRtlCompatibilityMode()) {
5794             // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
5795             // left / right padding are used if defined (meaning here nothing to do). If they are not
5796             // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
5797             // start / end and resolve them as left / right (layout direction is not taken into account).
5798             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
5799             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
5800             // defined.
5801             if (!mLeftPaddingDefined && startPaddingDefined) {
5802                 leftPadding = startPadding;
5803             }
5804             mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
5805             if (!mRightPaddingDefined && endPaddingDefined) {
5806                 rightPadding = endPadding;
5807             }
5808             mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
5809         } else {
5810             // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
5811             // values defined. Otherwise, left /right values are used.
5812             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
5813             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
5814             // defined.
5815             final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
5816 
5817             if (mLeftPaddingDefined && !hasRelativePadding) {
5818                 mUserPaddingLeftInitial = leftPadding;
5819             }
5820             if (mRightPaddingDefined && !hasRelativePadding) {
5821                 mUserPaddingRightInitial = rightPadding;
5822             }
5823         }
5824 
5825         // mPaddingTop and mPaddingBottom may have been set by setBackground(Drawable) so must pass
5826         // them on if topPadding or bottomPadding are not valid.
5827         internalSetPadding(
5828                 mUserPaddingLeftInitial,
5829                 topPadding >= 0 ? topPadding : mPaddingTop,
5830                 mUserPaddingRightInitial,
5831                 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
5832 
5833         if (viewFlagMasks != 0) {
5834             setFlags(viewFlagValues, viewFlagMasks);
5835         }
5836 
5837         if (initializeScrollbars) {
5838             initializeScrollbarsInternal(a);
5839         }
5840 
5841         if (initializeScrollIndicators) {
5842             initializeScrollIndicatorsInternal();
5843         }
5844 
5845         a.recycle();
5846 
5847         // Needs to be called after mViewFlags is set
5848         if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
5849             recomputePadding();
5850         }
5851 
5852         if (x != 0 || y != 0) {
5853             scrollTo(x, y);
5854         }
5855 
5856         if (transformSet) {
5857             setTranslationX(tx);
5858             setTranslationY(ty);
5859             setTranslationZ(tz);
5860             setElevation(elevation);
5861             setRotation(rotation);
5862             setRotationX(rotationX);
5863             setRotationY(rotationY);
5864             setScaleX(sx);
5865             setScaleY(sy);
5866         }
5867 
5868         if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
5869             setScrollContainer(true);
5870         }
5871 
5872         computeOpaqueFlags();
5873     }
5874 
5875     /**
5876      * Returns the ordered list of resource ID that are considered when resolving attribute values
5877      * for this {@link View}. The list will include layout resource ID if the View is inflated from
5878      * XML. It will also include a set of explicit styles if specified in XML using
5879      * {@code style="..."}. Finally, it will include the default styles resolved from the theme.
5880      *
5881      * <p>
5882      * <b>Note:</b> this method will only return actual values if the view attribute debugging
5883      * is enabled in Android developer options.
5884      *
5885      * @param attribute Attribute resource ID for which the resolution stack should be returned.
5886      * @return ordered list of resource ID that are considered when resolving attribute values for
5887      * this {@link View}.
5888      */
5889     @NonNull
5890     public int[] getAttributeResolutionStack(@AttrRes int attribute) {
5891         if (!sDebugViewAttributes
5892                 || mAttributeResolutionStacks == null
5893                 || mAttributeResolutionStacks.get(attribute) == null) {
5894             return new int[0];
5895         }
5896         int[] attributeResolutionStack = mAttributeResolutionStacks.get(attribute);
5897         int stackSize = attributeResolutionStack.length;
5898         if (mSourceLayoutId != ID_NULL) {
5899             stackSize++;
5900         }
5901 
5902         int currentIndex = 0;
5903         int[] stack = new int[stackSize];
5904 
5905         if (mSourceLayoutId != ID_NULL) {
5906             stack[currentIndex] = mSourceLayoutId;
5907             currentIndex++;
5908         }
5909         for (int i = 0; i < attributeResolutionStack.length; i++) {
5910             stack[currentIndex] = attributeResolutionStack[i];
5911             currentIndex++;
5912         }
5913         return stack;
5914     }
5915 
5916     /**
5917      * Returns the mapping of attribute resource ID to source resource ID where the attribute value
5918      * was set. Source resource ID can either be a layout resource ID, if the value was set in XML
5919      * within the View tag, or a style resource ID, if the attribute was set in a style. The source
5920      * resource value will be one of the resource IDs from {@link #getAttributeSourceResourceMap()}.
5921      *
5922      * <p>
5923      * <b>Note:</b> this method will only return actual values if the view attribute debugging
5924      * is enabled in Android developer options.
5925      *
5926      * @return mapping of attribute resource ID to source resource ID where the attribute value
5927      * was set.
5928      */
5929     @NonNull
5930     public Map<Integer, Integer> getAttributeSourceResourceMap() {
5931         HashMap<Integer, Integer> map = new HashMap<>();
5932         if (!sDebugViewAttributes || mAttributeSourceResId == null) {
5933             return map;
5934         }
5935         for (int i = 0; i < mAttributeSourceResId.size(); i++) {
5936             map.put(mAttributeSourceResId.keyAt(i), mAttributeSourceResId.valueAt(i));
5937         }
5938         return map;
5939     }
5940 
5941     /**
5942      * Returns the resource ID for the style specified using {@code style="..."} in the
5943      * {@link AttributeSet}'s backing XML element or {@link Resources#ID_NULL} otherwise if not
5944      * specified or otherwise not applicable.
5945      * <p>
5946      * Each {@link View} can have an explicit style specified in the layout file.
5947      * This style is used first during the {@link View} attribute resolution, then if an attribute
5948      * is not defined there the resource system looks at default style and theme as fallbacks.
5949      *
5950      * <p>
5951      * <b>Note:</b> this method will only return actual values if the view attribute debugging
5952      * is enabled in Android developer options.
5953      *
5954      * @return The resource ID for the style specified using {@code style="..."} in the
5955      *      {@link AttributeSet}'s backing XML element or {@link Resources#ID_NULL} otherwise
5956      *      if not specified or otherwise not applicable.
5957      */
5958     @StyleRes
5959     public int getExplicitStyle() {
5960         if (!sDebugViewAttributes) {
5961             return ID_NULL;
5962         }
5963         return mExplicitStyle;
5964     }
5965 
5966     /**
5967      * An implementation of OnClickListener that attempts to lazily load a
5968      * named click handling method from a parent or ancestor context.
5969      */
5970     private static class DeclaredOnClickListener implements OnClickListener {
5971         private final View mHostView;
5972         private final String mMethodName;
5973 
5974         private Method mResolvedMethod;
5975         private Context mResolvedContext;
5976 
5977         public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
5978             mHostView = hostView;
5979             mMethodName = methodName;
5980         }
5981 
5982         @Override
5983         public void onClick(@NonNull View v) {
5984             if (mResolvedMethod == null) {
5985                 resolveMethod(mHostView.getContext(), mMethodName);
5986             }
5987 
5988             try {
5989                 mResolvedMethod.invoke(mResolvedContext, v);
5990             } catch (IllegalAccessException e) {
5991                 throw new IllegalStateException(
5992                         "Could not execute non-public method for android:onClick", e);
5993             } catch (InvocationTargetException e) {
5994                 throw new IllegalStateException(
5995                         "Could not execute method for android:onClick", e);
5996             }
5997         }
5998 
5999         @NonNull
6000         private void resolveMethod(@Nullable Context context, @NonNull String name) {
6001             while (context != null) {
6002                 try {
6003                     if (!context.isRestricted()) {
6004                         final Method method = context.getClass().getMethod(mMethodName, View.class);
6005                         if (method != null) {
6006                             mResolvedMethod = method;
6007                             mResolvedContext = context;
6008                             return;
6009                         }
6010                     }
6011                 } catch (NoSuchMethodException e) {
6012                     // Failed to find method, keep searching up the hierarchy.
6013                 }
6014 
6015                 if (context instanceof ContextWrapper) {
6016                     context = ((ContextWrapper) context).getBaseContext();
6017                 } else {
6018                     // Can't search up the hierarchy, null out and fail.
6019                     context = null;
6020                 }
6021             }
6022 
6023             final int id = mHostView.getId();
6024             final String idText = id == NO_ID ? "" : " with id '"
6025                     + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
6026             throw new IllegalStateException("Could not find method " + mMethodName
6027                     + "(View) in a parent or ancestor Context for android:onClick "
6028                     + "attribute defined on view " + mHostView.getClass() + idText);
6029         }
6030     }
6031 
6032     /**
6033      * Non-public constructor for use in testing
6034      */
6035     @UnsupportedAppUsage
6036     View() {
6037         mResources = null;
6038         mRenderNode = RenderNode.create(getClass().getName(), new ViewAnimationHostBridge(this));
6039     }
6040 
6041     final boolean debugDraw() {
6042         return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
6043     }
6044 
6045     private static SparseArray<String> getAttributeMap() {
6046         if (mAttributeMap == null) {
6047             mAttributeMap = new SparseArray<>();
6048         }
6049         return mAttributeMap;
6050     }
6051 
6052     private void retrieveExplicitStyle(@NonNull Resources.Theme theme,
6053             @Nullable AttributeSet attrs) {
6054         if (!sDebugViewAttributes) {
6055             return;
6056         }
6057         mExplicitStyle = theme.getExplicitStyle(attrs);
6058     }
6059 
6060     /**
6061      * Stores debugging information about attributes. This should be called in a constructor by
6062      * every custom {@link View} that uses a custom styleable. If the custom view does not call it,
6063      * then the custom attributes used by this view will not be visible in layout inspection tools.
6064      *
6065      *  @param context Context under which this view is created.
6066      * @param styleable A reference to styleable array R.styleable.Foo
6067      * @param attrs AttributeSet used to construct this view.
6068      * @param t Resolved {@link TypedArray} returned by a call to
6069      *        {@link Resources#obtainAttributes(AttributeSet, int[])}.
6070      * @param defStyleAttr Default style attribute passed into the view constructor.
6071      * @param defStyleRes Default style resource passed into the view constructor.
6072      */
6073     public final void saveAttributeDataForStyleable(@NonNull Context context,
6074             @NonNull int[] styleable, @Nullable AttributeSet attrs, @NonNull TypedArray t,
6075             int defStyleAttr, int defStyleRes) {
6076         if (!sDebugViewAttributes) {
6077             return;
6078         }
6079 
6080         int[] attributeResolutionStack = context.getTheme().getAttributeResolutionStack(
6081                 defStyleAttr, defStyleRes, mExplicitStyle);
6082 
6083         if (mAttributeResolutionStacks == null) {
6084             mAttributeResolutionStacks = new SparseArray<>();
6085         }
6086 
6087         if (mAttributeSourceResId == null) {
6088             mAttributeSourceResId = new SparseIntArray();
6089         }
6090 
6091         final int indexCount = t.getIndexCount();
6092         for (int j = 0; j < indexCount; ++j) {
6093             final int index = t.getIndex(j);
6094             mAttributeSourceResId.append(styleable[index], t.getSourceResourceId(index, 0));
6095             mAttributeResolutionStacks.append(styleable[index], attributeResolutionStack);
6096         }
6097     }
6098 
6099     private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
6100         final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
6101         final int indexCount = t.getIndexCount();
6102         final String[] attributes = new String[(attrsCount + indexCount) * 2];
6103 
6104         int i = 0;
6105 
6106         // Store raw XML attributes.
6107         for (int j = 0; j < attrsCount; ++j) {
6108             attributes[i] = attrs.getAttributeName(j);
6109             attributes[i + 1] = attrs.getAttributeValue(j);
6110             i += 2;
6111         }
6112 
6113         // Store resolved styleable attributes.
6114         final Resources res = t.getResources();
6115         final SparseArray<String> attributeMap = getAttributeMap();
6116         for (int j = 0; j < indexCount; ++j) {
6117             final int index = t.getIndex(j);
6118             if (!t.hasValueOrEmpty(index)) {
6119                 // Value is undefined. Skip it.
6120                 continue;
6121             }
6122 
6123             final int resourceId = t.getResourceId(index, 0);
6124             if (resourceId == 0) {
6125                 // Value is not a reference. Skip it.
6126                 continue;
6127             }
6128 
6129             String resourceName = attributeMap.get(resourceId);
6130             if (resourceName == null) {
6131                 try {
6132                     resourceName = res.getResourceName(resourceId);
6133                 } catch (Resources.NotFoundException e) {
6134                     resourceName = "0x" + Integer.toHexString(resourceId);
6135                 }
6136                 attributeMap.put(resourceId, resourceName);
6137             }
6138 
6139             attributes[i] = resourceName;
6140             attributes[i + 1] = t.getString(index);
6141             i += 2;
6142         }
6143 
6144         // Trim to fit contents.
6145         final String[] trimmed = new String[i];
6146         System.arraycopy(attributes, 0, trimmed, 0, i);
6147         mAttributes = trimmed;
6148     }
6149 
6150     @Override
6151     public String toString() {
6152         StringBuilder out = new StringBuilder(128);
6153         out.append(getClass().getName());
6154         out.append('{');
6155         out.append(Integer.toHexString(System.identityHashCode(this)));
6156         out.append(' ');
6157         switch (mViewFlags&VISIBILITY_MASK) {
6158             case VISIBLE: out.append('V'); break;
6159             case INVISIBLE: out.append('I'); break;
6160             case GONE: out.append('G'); break;
6161             default: out.append('.'); break;
6162         }
6163         out.append((mViewFlags & FOCUSABLE) == FOCUSABLE ? 'F' : '.');
6164         out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
6165         out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
6166         out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
6167         out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
6168         out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
6169         out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
6170         out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
6171         out.append(' ');
6172         out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
6173         out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
6174         out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
6175         if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
6176             out.append('p');
6177         } else {
6178             out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
6179         }
6180         out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
6181         out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
6182         out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
6183         out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
6184         out.append(' ');
6185         out.append(mLeft);
6186         out.append(',');
6187         out.append(mTop);
6188         out.append('-');
6189         out.append(mRight);
6190         out.append(',');
6191         out.append(mBottom);
6192         final int id = getId();
6193         if (id != NO_ID) {
6194             out.append(" #");
6195             out.append(Integer.toHexString(id));
6196             final Resources r = mResources;
6197             if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
6198                 try {
6199                     String pkgname;
6200                     switch (id&0xff000000) {
6201                         case 0x7f000000:
6202                             pkgname="app";
6203                             break;
6204                         case 0x01000000:
6205                             pkgname="android";
6206                             break;
6207                         default:
6208                             pkgname = r.getResourcePackageName(id);
6209                             break;
6210                     }
6211                     String typename = r.getResourceTypeName(id);
6212                     String entryname = r.getResourceEntryName(id);
6213                     out.append(" ");
6214                     out.append(pkgname);
6215                     out.append(":");
6216                     out.append(typename);
6217                     out.append("/");
6218                     out.append(entryname);
6219                 } catch (Resources.NotFoundException e) {
6220                 }
6221             }
6222         }
6223         if (mAutofillId != null) {
6224             out.append(" aid="); out.append(mAutofillId);
6225         }
6226         out.append("}");
6227         return out.toString();
6228     }
6229 
6230     /**
6231      * <p>
6232      * Initializes the fading edges from a given set of styled attributes. This
6233      * method should be called by subclasses that need fading edges and when an
6234      * instance of these subclasses is created programmatically rather than
6235      * being inflated from XML. This method is automatically called when the XML
6236      * is inflated.
6237      * </p>
6238      *
6239      * @param a the styled attributes set to initialize the fading edges from
6240      *
6241      * @removed
6242      */
6243     protected void initializeFadingEdge(TypedArray a) {
6244         // This method probably shouldn't have been included in the SDK to begin with.
6245         // It relies on 'a' having been initialized using an attribute filter array that is
6246         // not publicly available to the SDK. The old method has been renamed
6247         // to initializeFadingEdgeInternal and hidden for framework use only;
6248         // this one initializes using defaults to make it safe to call for apps.
6249 
6250         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
6251 
6252         initializeFadingEdgeInternal(arr);
6253 
6254         arr.recycle();
6255     }
6256 
6257     /**
6258      * <p>
6259      * Initializes the fading edges from a given set of styled attributes. This
6260      * method should be called by subclasses that need fading edges and when an
6261      * instance of these subclasses is created programmatically rather than
6262      * being inflated from XML. This method is automatically called when the XML
6263      * is inflated.
6264      * </p>
6265      *
6266      * @param a the styled attributes set to initialize the fading edges from
6267      * @hide This is the real method; the public one is shimmed to be safe to call from apps.
6268      */
6269     protected void initializeFadingEdgeInternal(TypedArray a) {
6270         initScrollCache();
6271 
6272         mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
6273                 R.styleable.View_fadingEdgeLength,
6274                 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
6275     }
6276 
6277     /**
6278      * Returns the size of the vertical faded edges used to indicate that more
6279      * content in this view is visible.
6280      *
6281      * @return The size in pixels of the vertical faded edge or 0 if vertical
6282      *         faded edges are not enabled for this view.
6283      * @attr ref android.R.styleable#View_fadingEdgeLength
6284      */
6285     public int getVerticalFadingEdgeLength() {
6286         if (isVerticalFadingEdgeEnabled()) {
6287             ScrollabilityCache cache = mScrollCache;
6288             if (cache != null) {
6289                 return cache.fadingEdgeLength;
6290             }
6291         }
6292         return 0;
6293     }
6294 
6295     /**
6296      * Set the size of the faded edge used to indicate that more content in this
6297      * view is available.  Will not change whether the fading edge is enabled; use
6298      * {@link #setVerticalFadingEdgeEnabled(boolean)} or
6299      * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
6300      * for the vertical or horizontal fading edges.
6301      *
6302      * @param length The size in pixels of the faded edge used to indicate that more
6303      *        content in this view is visible.
6304      */
6305     public void setFadingEdgeLength(int length) {
6306         initScrollCache();
6307         mScrollCache.fadingEdgeLength = length;
6308     }
6309 
6310     /**
6311      * Returns the size of the horizontal faded edges used to indicate that more
6312      * content in this view is visible.
6313      *
6314      * @return The size in pixels of the horizontal faded edge or 0 if horizontal
6315      *         faded edges are not enabled for this view.
6316      * @attr ref android.R.styleable#View_fadingEdgeLength
6317      */
6318     public int getHorizontalFadingEdgeLength() {
6319         if (isHorizontalFadingEdgeEnabled()) {
6320             ScrollabilityCache cache = mScrollCache;
6321             if (cache != null) {
6322                 return cache.fadingEdgeLength;
6323             }
6324         }
6325         return 0;
6326     }
6327 
6328     /**
6329      * Returns the width of the vertical scrollbar.
6330      *
6331      * @return The width in pixels of the vertical scrollbar or 0 if there
6332      *         is no vertical scrollbar.
6333      */
6334     public int getVerticalScrollbarWidth() {
6335         ScrollabilityCache cache = mScrollCache;
6336         if (cache != null) {
6337             ScrollBarDrawable scrollBar = cache.scrollBar;
6338             if (scrollBar != null) {
6339                 int size = scrollBar.getSize(true);
6340                 if (size <= 0) {
6341                     size = cache.scrollBarSize;
6342                 }
6343                 return size;
6344             }
6345             return 0;
6346         }
6347         return 0;
6348     }
6349 
6350     /**
6351      * Returns the height of the horizontal scrollbar.
6352      *
6353      * @return The height in pixels of the horizontal scrollbar or 0 if
6354      *         there is no horizontal scrollbar.
6355      */
6356     protected int getHorizontalScrollbarHeight() {
6357         ScrollabilityCache cache = mScrollCache;
6358         if (cache != null) {
6359             ScrollBarDrawable scrollBar = cache.scrollBar;
6360             if (scrollBar != null) {
6361                 int size = scrollBar.getSize(false);
6362                 if (size <= 0) {
6363                     size = cache.scrollBarSize;
6364                 }
6365                 return size;
6366             }
6367             return 0;
6368         }
6369         return 0;
6370     }
6371 
6372     /**
6373      * <p>
6374      * Initializes the scrollbars from a given set of styled attributes. This
6375      * method should be called by subclasses that need scrollbars and when an
6376      * instance of these subclasses is created programmatically rather than
6377      * being inflated from XML. This method is automatically called when the XML
6378      * is inflated.
6379      * </p>
6380      *
6381      * @param a the styled attributes set to initialize the scrollbars from
6382      *
6383      * @removed
6384      */
6385     protected void initializeScrollbars(TypedArray a) {
6386         // It's not safe to use this method from apps. The parameter 'a' must have been obtained
6387         // using the View filter array which is not available to the SDK. As such, internal
6388         // framework usage now uses initializeScrollbarsInternal and we grab a default
6389         // TypedArray with the right filter instead here.
6390         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
6391 
6392         initializeScrollbarsInternal(arr);
6393 
6394         // We ignored the method parameter. Recycle the one we actually did use.
6395         arr.recycle();
6396     }
6397 
6398     private void initializeScrollBarDrawable() {
6399         initScrollCache();
6400 
6401         if (mScrollCache.scrollBar == null) {
6402             mScrollCache.scrollBar = new ScrollBarDrawable();
6403             mScrollCache.scrollBar.setState(getDrawableState());
6404             mScrollCache.scrollBar.setCallback(this);
6405         }
6406     }
6407 
6408     /**
6409      * <p>
6410      * Initializes the scrollbars from a given set of styled attributes. This
6411      * method should be called by subclasses that need scrollbars and when an
6412      * instance of these subclasses is created programmatically rather than
6413      * being inflated from XML. This method is automatically called when the XML
6414      * is inflated.
6415      * </p>
6416      *
6417      * @param a the styled attributes set to initialize the scrollbars from
6418      * @hide
6419      */
6420     @UnsupportedAppUsage
6421     protected void initializeScrollbarsInternal(TypedArray a) {
6422         initScrollCache();
6423 
6424         final ScrollabilityCache scrollabilityCache = mScrollCache;
6425 
6426         if (scrollabilityCache.scrollBar == null) {
6427             scrollabilityCache.scrollBar = new ScrollBarDrawable();
6428             scrollabilityCache.scrollBar.setState(getDrawableState());
6429             scrollabilityCache.scrollBar.setCallback(this);
6430         }
6431 
6432         final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
6433 
6434         if (!fadeScrollbars) {
6435             scrollabilityCache.state = ScrollabilityCache.ON;
6436         }
6437         scrollabilityCache.fadeScrollBars = fadeScrollbars;
6438 
6439 
6440         scrollabilityCache.scrollBarFadeDuration = a.getInt(
6441                 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
6442                         .getScrollBarFadeDuration());
6443         scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
6444                 R.styleable.View_scrollbarDefaultDelayBeforeFade,
6445                 ViewConfiguration.getScrollDefaultDelay());
6446 
6447 
6448         scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
6449                 com.android.internal.R.styleable.View_scrollbarSize,
6450                 ViewConfiguration.get(mContext).getScaledScrollBarSize());
6451 
6452         Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
6453         scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
6454 
6455         Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
6456         if (thumb != null) {
6457             scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
6458         }
6459 
6460         boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
6461                 false);
6462         if (alwaysDraw) {
6463             scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
6464         }
6465 
6466         track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
6467         scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
6468 
6469         thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
6470         if (thumb != null) {
6471             scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
6472         }
6473 
6474         alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
6475                 false);
6476         if (alwaysDraw) {
6477             scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
6478         }
6479 
6480         // Apply layout direction to the new Drawables if needed
6481         final int layoutDirection = getLayoutDirection();
6482         if (track != null) {
6483             track.setLayoutDirection(layoutDirection);
6484         }
6485         if (thumb != null) {
6486             thumb.setLayoutDirection(layoutDirection);
6487         }
6488 
6489         // Re-apply user/background padding so that scrollbar(s) get added
6490         resolvePadding();
6491     }
6492 
6493     /**
6494      * Defines the vertical scrollbar thumb drawable
6495      * @attr ref android.R.styleable#View_scrollbarThumbVertical
6496      *
6497      * @see #awakenScrollBars(int)
6498      * @see #isVerticalScrollBarEnabled()
6499      * @see #setVerticalScrollBarEnabled(boolean)
6500      */
6501     public void setVerticalScrollbarThumbDrawable(@Nullable Drawable drawable) {
6502         initializeScrollBarDrawable();
6503         mScrollCache.scrollBar.setVerticalThumbDrawable(drawable);
6504     }
6505 
6506     /**
6507      * Defines the vertical scrollbar track drawable
6508      * @attr ref android.R.styleable#View_scrollbarTrackVertical
6509      *
6510      * @see #awakenScrollBars(int)
6511      * @see #isVerticalScrollBarEnabled()
6512      * @see #setVerticalScrollBarEnabled(boolean)
6513      */
6514     public void setVerticalScrollbarTrackDrawable(@Nullable Drawable drawable) {
6515         initializeScrollBarDrawable();
6516         mScrollCache.scrollBar.setVerticalTrackDrawable(drawable);
6517     }
6518 
6519     /**
6520      * Defines the horizontal thumb drawable
6521      * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
6522      *
6523      * @see #awakenScrollBars(int)
6524      * @see #isHorizontalScrollBarEnabled()
6525      * @see #setHorizontalScrollBarEnabled(boolean)
6526      */
6527     public void setHorizontalScrollbarThumbDrawable(@Nullable Drawable drawable) {
6528         initializeScrollBarDrawable();
6529         mScrollCache.scrollBar.setHorizontalThumbDrawable(drawable);
6530     }
6531 
6532     /**
6533      * Defines the horizontal track drawable
6534      * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
6535      *
6536      * @see #awakenScrollBars(int)
6537      * @see #isHorizontalScrollBarEnabled()
6538      * @see #setHorizontalScrollBarEnabled(boolean)
6539      */
6540     public void setHorizontalScrollbarTrackDrawable(@Nullable Drawable drawable) {
6541         initializeScrollBarDrawable();
6542         mScrollCache.scrollBar.setHorizontalTrackDrawable(drawable);
6543     }
6544 
6545     /**
6546      * Returns the currently configured Drawable for the thumb of the vertical scroll bar if it
6547      * exists, null otherwise.
6548      *
6549      * @see #awakenScrollBars(int)
6550      * @see #isVerticalScrollBarEnabled()
6551      * @see #setVerticalScrollBarEnabled(boolean)
6552      */
6553     public @Nullable Drawable getVerticalScrollbarThumbDrawable() {
6554         return mScrollCache != null ? mScrollCache.scrollBar.getVerticalThumbDrawable() : null;
6555     }
6556 
6557     /**
6558      * Returns the currently configured Drawable for the track of the vertical scroll bar if it
6559      * exists, null otherwise.
6560      *
6561      * @see #awakenScrollBars(int)
6562      * @see #isVerticalScrollBarEnabled()
6563      * @see #setVerticalScrollBarEnabled(boolean)
6564      */
6565     public @Nullable Drawable getVerticalScrollbarTrackDrawable() {
6566         return mScrollCache != null ? mScrollCache.scrollBar.getVerticalTrackDrawable() : null;
6567     }
6568 
6569     /**
6570      * Returns the currently configured Drawable for the thumb of the horizontal scroll bar if it
6571      * exists, null otherwise.
6572      *
6573      * @see #awakenScrollBars(int)
6574      * @see #isHorizontalScrollBarEnabled()
6575      * @see #setHorizontalScrollBarEnabled(boolean)
6576      */
6577     public @Nullable Drawable getHorizontalScrollbarThumbDrawable() {
6578         return mScrollCache != null ? mScrollCache.scrollBar.getHorizontalThumbDrawable() : null;
6579     }
6580 
6581     /**
6582      * Returns the currently configured Drawable for the track of the horizontal scroll bar if it
6583      * exists, null otherwise.
6584      *
6585      * @see #awakenScrollBars(int)
6586      * @see #isHorizontalScrollBarEnabled()
6587      * @see #setHorizontalScrollBarEnabled(boolean)
6588      */
6589     public @Nullable Drawable getHorizontalScrollbarTrackDrawable() {
6590         return mScrollCache != null ? mScrollCache.scrollBar.getHorizontalTrackDrawable() : null;
6591     }
6592 
6593     private void initializeScrollIndicatorsInternal() {
6594         // Some day maybe we'll break this into top/left/start/etc. and let the
6595         // client control it. Until then, you can have any scroll indicator you
6596         // want as long as it's a 1dp foreground-colored rectangle.
6597         if (mScrollIndicatorDrawable == null) {
6598             mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
6599         }
6600     }
6601 
6602     /**
6603      * <p>
6604      * Initalizes the scrollability cache if necessary.
6605      * </p>
6606      */
6607     private void initScrollCache() {
6608         if (mScrollCache == null) {
6609             mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
6610         }
6611     }
6612 
6613     @UnsupportedAppUsage
6614     private ScrollabilityCache getScrollCache() {
6615         initScrollCache();
6616         return mScrollCache;
6617     }
6618 
6619     /**
6620      * Set the position of the vertical scroll bar. Should be one of
6621      * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
6622      * {@link #SCROLLBAR_POSITION_RIGHT}.
6623      *
6624      * @param position Where the vertical scroll bar should be positioned.
6625      */
6626     public void setVerticalScrollbarPosition(int position) {
6627         if (mVerticalScrollbarPosition != position) {
6628             mVerticalScrollbarPosition = position;
6629             computeOpaqueFlags();
6630             resolvePadding();
6631         }
6632     }
6633 
6634     /**
6635      * @return The position where the vertical scroll bar will show, if applicable.
6636      * @see #setVerticalScrollbarPosition(int)
6637      */
6638     public int getVerticalScrollbarPosition() {
6639         return mVerticalScrollbarPosition;
6640     }
6641 
6642     boolean isOnScrollbar(float x, float y) {
6643         if (mScrollCache == null) {
6644             return false;
6645         }
6646         x += getScrollX();
6647         y += getScrollY();
6648         final boolean canScrollVertically =
6649                 computeVerticalScrollRange() > computeVerticalScrollExtent();
6650         if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden() && canScrollVertically) {
6651             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
6652             getVerticalScrollBarBounds(null, touchBounds);
6653             if (touchBounds.contains((int) x, (int) y)) {
6654                 return true;
6655             }
6656         }
6657         final boolean canScrollHorizontally =
6658                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
6659         if (isHorizontalScrollBarEnabled() && canScrollHorizontally) {
6660             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
6661             getHorizontalScrollBarBounds(null, touchBounds);
6662             if (touchBounds.contains((int) x, (int) y)) {
6663                 return true;
6664             }
6665         }
6666         return false;
6667     }
6668 
6669     @UnsupportedAppUsage
6670     boolean isOnScrollbarThumb(float x, float y) {
6671         return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
6672     }
6673 
6674     private boolean isOnVerticalScrollbarThumb(float x, float y) {
6675         if (mScrollCache == null || !isVerticalScrollBarEnabled() || isVerticalScrollBarHidden()) {
6676             return false;
6677         }
6678         final int range = computeVerticalScrollRange();
6679         final int extent = computeVerticalScrollExtent();
6680         if (range > extent) {
6681             x += getScrollX();
6682             y += getScrollY();
6683             final Rect bounds = mScrollCache.mScrollBarBounds;
6684             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
6685             getVerticalScrollBarBounds(bounds, touchBounds);
6686             final int offset = computeVerticalScrollOffset();
6687             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
6688                     extent, range);
6689             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
6690                     extent, range, offset);
6691             final int thumbTop = bounds.top + thumbOffset;
6692             final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
6693             if (x >= touchBounds.left && x <= touchBounds.right
6694                     && y >= thumbTop - adjust && y <= thumbTop + thumbLength + adjust) {
6695                 return true;
6696             }
6697         }
6698         return false;
6699     }
6700 
6701     private boolean isOnHorizontalScrollbarThumb(float x, float y) {
6702         if (mScrollCache == null || !isHorizontalScrollBarEnabled()) {
6703             return false;
6704         }
6705         final int range = computeHorizontalScrollRange();
6706         final int extent = computeHorizontalScrollExtent();
6707         if (range > extent) {
6708             x += getScrollX();
6709             y += getScrollY();
6710             final Rect bounds = mScrollCache.mScrollBarBounds;
6711             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
6712             getHorizontalScrollBarBounds(bounds, touchBounds);
6713             final int offset = computeHorizontalScrollOffset();
6714 
6715             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
6716                     extent, range);
6717             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
6718                     extent, range, offset);
6719             final int thumbLeft = bounds.left + thumbOffset;
6720             final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
6721             if (x >= thumbLeft - adjust && x <= thumbLeft + thumbLength + adjust
6722                     && y >= touchBounds.top && y <= touchBounds.bottom) {
6723                 return true;
6724             }
6725         }
6726         return false;
6727     }
6728 
6729     @UnsupportedAppUsage
6730     boolean isDraggingScrollBar() {
6731         return mScrollCache != null
6732                 && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
6733     }
6734 
6735     /**
6736      * Sets the state of all scroll indicators.
6737      * <p>
6738      * See {@link #setScrollIndicators(int, int)} for usage information.
6739      *
6740      * @param indicators a bitmask of indicators that should be enabled, or
6741      *                   {@code 0} to disable all indicators
6742      * @see #setScrollIndicators(int, int)
6743      * @see #getScrollIndicators()
6744      * @attr ref android.R.styleable#View_scrollIndicators
6745      */
6746     public void setScrollIndicators(@ScrollIndicators int indicators) {
6747         setScrollIndicators(indicators,
6748                 SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
6749     }
6750 
6751     /**
6752      * Sets the state of the scroll indicators specified by the mask. To change
6753      * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
6754      * <p>
6755      * When a scroll indicator is enabled, it will be displayed if the view
6756      * can scroll in the direction of the indicator.
6757      * <p>
6758      * Multiple indicator types may be enabled or disabled by passing the
6759      * logical OR of the desired types. If multiple types are specified, they
6760      * will all be set to the same enabled state.
6761      * <p>
6762      * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
6763      *
6764      * @param indicators the indicator direction, or the logical OR of multiple
6765      *             indicator directions. One or more of:
6766      *             <ul>
6767      *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
6768      *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
6769      *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
6770      *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
6771      *               <li>{@link #SCROLL_INDICATOR_START}</li>
6772      *               <li>{@link #SCROLL_INDICATOR_END}</li>
6773      *             </ul>
6774      * @see #setScrollIndicators(int)
6775      * @see #getScrollIndicators()
6776      * @attr ref android.R.styleable#View_scrollIndicators
6777      */
6778     public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
6779         // Shift and sanitize mask.
6780         mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
6781         mask &= SCROLL_INDICATORS_PFLAG3_MASK;
6782 
6783         // Shift and mask indicators.
6784         indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
6785         indicators &= mask;
6786 
6787         // Merge with non-masked flags.
6788         final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
6789 
6790         if (mPrivateFlags3 != updatedFlags) {
6791             mPrivateFlags3 = updatedFlags;
6792 
6793             if (indicators != 0) {
6794                 initializeScrollIndicatorsInternal();
6795             }
6796             invalidate();
6797         }
6798     }
6799 
6800     /**
6801      * Returns a bitmask representing the enabled scroll indicators.
6802      * <p>
6803      * For example, if the top and left scroll indicators are enabled and all
6804      * other indicators are disabled, the return value will be
6805      * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
6806      * <p>
6807      * To check whether the bottom scroll indicator is enabled, use the value
6808      * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
6809      *
6810      * @return a bitmask representing the enabled scroll indicators
6811      */
6812     @InspectableProperty(flagMapping = {
6813             @FlagEntry(target = SCROLL_INDICATORS_NONE, mask = 0xffff_ffff, name = "none"),
6814             @FlagEntry(target = SCROLL_INDICATOR_TOP, name = "top"),
6815             @FlagEntry(target = SCROLL_INDICATOR_BOTTOM, name = "bottom"),
6816             @FlagEntry(target = SCROLL_INDICATOR_LEFT, name = "left"),
6817             @FlagEntry(target = SCROLL_INDICATOR_RIGHT, name = "right"),
6818             @FlagEntry(target = SCROLL_INDICATOR_START, name = "start"),
6819             @FlagEntry(target = SCROLL_INDICATOR_END, name = "end")
6820     })
6821     @ScrollIndicators
6822     public int getScrollIndicators() {
6823         return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
6824                 >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
6825     }
6826 
6827     @UnsupportedAppUsage
6828     ListenerInfo getListenerInfo() {
6829         if (mListenerInfo != null) {
6830             return mListenerInfo;
6831         }
6832         mListenerInfo = new ListenerInfo();
6833         return mListenerInfo;
6834     }
6835 
6836     /**
6837      * Register a callback to be invoked when the scroll X or Y positions of
6838      * this view change.
6839      * <p>
6840      * <b>Note:</b> Some views handle scrolling independently from View and may
6841      * have their own separate listeners for scroll-type events. For example,
6842      * {@link android.widget.ListView ListView} allows clients to register an
6843      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
6844      * to listen for changes in list scroll position.
6845      *
6846      * @param l The listener to notify when the scroll X or Y position changes.
6847      * @see android.view.View#getScrollX()
6848      * @see android.view.View#getScrollY()
6849      */
6850     public void setOnScrollChangeListener(OnScrollChangeListener l) {
6851         getListenerInfo().mOnScrollChangeListener = l;
6852     }
6853 
6854     /**
6855      * Register a callback to be invoked when focus of this view changed.
6856      *
6857      * @param l The callback that will run.
6858      */
6859     public void setOnFocusChangeListener(OnFocusChangeListener l) {
6860         getListenerInfo().mOnFocusChangeListener = l;
6861     }
6862 
6863     /**
6864      * Add a listener that will be called when the bounds of the view change due to
6865      * layout processing.
6866      *
6867      * @param listener The listener that will be called when layout bounds change.
6868      */
6869     public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
6870         ListenerInfo li = getListenerInfo();
6871         if (li.mOnLayoutChangeListeners == null) {
6872             li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
6873         }
6874         if (!li.mOnLayoutChangeListeners.contains(listener)) {
6875             li.mOnLayoutChangeListeners.add(listener);
6876         }
6877     }
6878 
6879     /**
6880      * Remove a listener for layout changes.
6881      *
6882      * @param listener The listener for layout bounds change.
6883      */
6884     public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
6885         ListenerInfo li = mListenerInfo;
6886         if (li == null || li.mOnLayoutChangeListeners == null) {
6887             return;
6888         }
6889         li.mOnLayoutChangeListeners.remove(listener);
6890     }
6891 
6892     /**
6893      * Add a listener for attach state changes.
6894      *
6895      * This listener will be called whenever this view is attached or detached
6896      * from a window. Remove the listener using
6897      * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
6898      *
6899      * @param listener Listener to attach
6900      * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
6901      */
6902     public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
6903         ListenerInfo li = getListenerInfo();
6904         if (li.mOnAttachStateChangeListeners == null) {
6905             li.mOnAttachStateChangeListeners
6906                     = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
6907         }
6908         li.mOnAttachStateChangeListeners.add(listener);
6909     }
6910 
6911     /**
6912      * Remove a listener for attach state changes. The listener will receive no further
6913      * notification of window attach/detach events.
6914      *
6915      * @param listener Listener to remove
6916      * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
6917      */
6918     public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
6919         ListenerInfo li = mListenerInfo;
6920         if (li == null || li.mOnAttachStateChangeListeners == null) {
6921             return;
6922         }
6923         li.mOnAttachStateChangeListeners.remove(listener);
6924     }
6925 
6926     /**
6927      * Returns the focus-change callback registered for this view.
6928      *
6929      * @return The callback, or null if one is not registered.
6930      */
6931     public OnFocusChangeListener getOnFocusChangeListener() {
6932         ListenerInfo li = mListenerInfo;
6933         return li != null ? li.mOnFocusChangeListener : null;
6934     }
6935 
6936     /**
6937      * Register a callback to be invoked when this view is clicked. If this view is not
6938      * clickable, it becomes clickable.
6939      *
6940      * @param l The callback that will run
6941      *
6942      * @see #setClickable(boolean)
6943      */
6944     public void setOnClickListener(@Nullable OnClickListener l) {
6945         if (!isClickable()) {
6946             setClickable(true);
6947         }
6948         getListenerInfo().mOnClickListener = l;
6949     }
6950 
6951     /**
6952      * Return whether this view has an attached OnClickListener.  Returns
6953      * true if there is a listener, false if there is none.
6954      */
6955     public boolean hasOnClickListeners() {
6956         ListenerInfo li = mListenerInfo;
6957         return (li != null && li.mOnClickListener != null);
6958     }
6959 
6960     /**
6961      * Register a callback to be invoked when this view is clicked and held. If this view is not
6962      * long clickable, it becomes long clickable.
6963      *
6964      * @param l The callback that will run
6965      *
6966      * @see #setLongClickable(boolean)
6967      */
6968     public void setOnLongClickListener(@Nullable OnLongClickListener l) {
6969         if (!isLongClickable()) {
6970             setLongClickable(true);
6971         }
6972         getListenerInfo().mOnLongClickListener = l;
6973     }
6974 
6975     /**
6976      * Register a callback to be invoked when this view is context clicked. If the view is not
6977      * context clickable, it becomes context clickable.
6978      *
6979      * @param l The callback that will run
6980      * @see #setContextClickable(boolean)
6981      */
6982     public void setOnContextClickListener(@Nullable OnContextClickListener l) {
6983         if (!isContextClickable()) {
6984             setContextClickable(true);
6985         }
6986         getListenerInfo().mOnContextClickListener = l;
6987     }
6988 
6989     /**
6990      * Register a callback to be invoked when the context menu for this view is
6991      * being built. If this view is not long clickable, it becomes long clickable.
6992      *
6993      * @param l The callback that will run
6994      *
6995      */
6996     public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
6997         if (!isLongClickable()) {
6998             setLongClickable(true);
6999         }
7000         getListenerInfo().mOnCreateContextMenuListener = l;
7001     }
7002 
7003     /**
7004      * Set an observer to collect stats for each frame rendered for this view.
7005      *
7006      * @hide
7007      */
7008     public void addFrameMetricsListener(Window window,
7009             Window.OnFrameMetricsAvailableListener listener,
7010             Handler handler) {
7011         if (mAttachInfo != null) {
7012             if (mAttachInfo.mThreadedRenderer != null) {
7013                 if (mFrameMetricsObservers == null) {
7014                     mFrameMetricsObservers = new ArrayList<>();
7015                 }
7016 
7017                 FrameMetricsObserver fmo = new FrameMetricsObserver(window,
7018                         handler.getLooper(), listener);
7019                 mFrameMetricsObservers.add(fmo);
7020                 mAttachInfo.mThreadedRenderer.addFrameMetricsObserver(fmo);
7021             } else {
7022                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
7023             }
7024         } else {
7025             if (mFrameMetricsObservers == null) {
7026                 mFrameMetricsObservers = new ArrayList<>();
7027             }
7028 
7029             FrameMetricsObserver fmo = new FrameMetricsObserver(window,
7030                     handler.getLooper(), listener);
7031             mFrameMetricsObservers.add(fmo);
7032         }
7033     }
7034 
7035     /**
7036      * Remove observer configured to collect frame stats for this view.
7037      *
7038      * @hide
7039      */
7040     public void removeFrameMetricsListener(
7041             Window.OnFrameMetricsAvailableListener listener) {
7042         ThreadedRenderer renderer = getThreadedRenderer();
7043         FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
7044         if (fmo == null) {
7045             throw new IllegalArgumentException(
7046                     "attempt to remove OnFrameMetricsAvailableListener that was never added");
7047         }
7048 
7049         if (mFrameMetricsObservers != null) {
7050             mFrameMetricsObservers.remove(fmo);
7051             if (renderer != null) {
7052                 renderer.removeFrameMetricsObserver(fmo);
7053             }
7054         }
7055     }
7056 
7057     private void registerPendingFrameMetricsObservers() {
7058         if (mFrameMetricsObservers != null) {
7059             ThreadedRenderer renderer = getThreadedRenderer();
7060             if (renderer != null) {
7061                 for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
7062                     renderer.addFrameMetricsObserver(fmo);
7063                 }
7064             } else {
7065                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
7066             }
7067         }
7068     }
7069 
7070     private FrameMetricsObserver findFrameMetricsObserver(
7071             Window.OnFrameMetricsAvailableListener listener) {
7072         if (mFrameMetricsObservers != null) {
7073             for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
7074                 FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
7075                 if (observer.mListener == listener) {
7076                     return observer;
7077                 }
7078             }
7079         }
7080 
7081         return null;
7082     }
7083 
7084     /** @hide */
7085     public void setNotifyAutofillManagerOnClick(boolean notify) {
7086         if (notify) {
7087             mPrivateFlags |= PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
7088         } else {
7089             mPrivateFlags &= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
7090         }
7091     }
7092 
7093     private void notifyAutofillManagerOnClick() {
7094         if ((mPrivateFlags & PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK) != 0) {
7095             try {
7096                 getAutofillManager().notifyViewClicked(this);
7097             } finally {
7098                 // Set it to already called so it's not called twice when called by
7099                 // performClickInternal()
7100                 mPrivateFlags &= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
7101             }
7102         }
7103     }
7104 
7105     /**
7106      * Entry point for {@link #performClick()} - other methods on View should call it instead of
7107      * {@code performClick()} directly to make sure the autofill manager is notified when
7108      * necessary (as subclasses could extend {@code performClick()} without calling the parent's
7109      * method).
7110      */
7111     private boolean performClickInternal() {
7112         // Must notify autofill manager before performing the click actions to avoid scenarios where
7113         // the app has a click listener that changes the state of views the autofill service might
7114         // be interested on.
7115         notifyAutofillManagerOnClick();
7116 
7117         return performClick();
7118     }
7119 
7120     /**
7121      * Call this view's OnClickListener, if it is defined.  Performs all normal
7122      * actions associated with clicking: reporting accessibility event, playing
7123      * a sound, etc.
7124      *
7125      * @return True there was an assigned OnClickListener that was called, false
7126      *         otherwise is returned.
7127      */
7128     // NOTE: other methods on View should not call this method directly, but performClickInternal()
7129     // instead, to guarantee that the autofill manager is notified when necessary (as subclasses
7130     // could extend this method without calling super.performClick()).
7131     public boolean performClick() {
7132         // We still need to call this method to handle the cases where performClick() was called
7133         // externally, instead of through performClickInternal()
7134         notifyAutofillManagerOnClick();
7135 
7136         final boolean result;
7137         final ListenerInfo li = mListenerInfo;
7138         if (li != null && li.mOnClickListener != null) {
7139             playSoundEffect(SoundEffectConstants.CLICK);
7140             li.mOnClickListener.onClick(this);
7141             result = true;
7142         } else {
7143             result = false;
7144         }
7145 
7146         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
7147 
7148         notifyEnterOrExitForAutoFillIfNeeded(true);
7149 
7150         return result;
7151     }
7152 
7153     /**
7154      * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
7155      * this only calls the listener, and does not do any associated clicking
7156      * actions like reporting an accessibility event.
7157      *
7158      * @return True there was an assigned OnClickListener that was called, false
7159      *         otherwise is returned.
7160      */
7161     public boolean callOnClick() {
7162         ListenerInfo li = mListenerInfo;
7163         if (li != null && li.mOnClickListener != null) {
7164             li.mOnClickListener.onClick(this);
7165             return true;
7166         }
7167         return false;
7168     }
7169 
7170     /**
7171      * Calls this view's OnLongClickListener, if it is defined. Invokes the
7172      * context menu if the OnLongClickListener did not consume the event.
7173      *
7174      * @return {@code true} if one of the above receivers consumed the event,
7175      *         {@code false} otherwise
7176      */
7177     public boolean performLongClick() {
7178         return performLongClickInternal(mLongClickX, mLongClickY);
7179     }
7180 
7181     /**
7182      * Calls this view's OnLongClickListener, if it is defined. Invokes the
7183      * context menu if the OnLongClickListener did not consume the event,
7184      * anchoring it to an (x,y) coordinate.
7185      *
7186      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
7187      *          to disable anchoring
7188      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
7189      *          to disable anchoring
7190      * @return {@code true} if one of the above receivers consumed the event,
7191      *         {@code false} otherwise
7192      */
7193     public boolean performLongClick(float x, float y) {
7194         mLongClickX = x;
7195         mLongClickY = y;
7196         final boolean handled = performLongClick();
7197         mLongClickX = Float.NaN;
7198         mLongClickY = Float.NaN;
7199         return handled;
7200     }
7201 
7202     /**
7203      * Calls this view's OnLongClickListener, if it is defined. Invokes the
7204      * context menu if the OnLongClickListener did not consume the event,
7205      * optionally anchoring it to an (x,y) coordinate.
7206      *
7207      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
7208      *          to disable anchoring
7209      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
7210      *          to disable anchoring
7211      * @return {@code true} if one of the above receivers consumed the event,
7212      *         {@code false} otherwise
7213      */
7214     private boolean performLongClickInternal(float x, float y) {
7215         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
7216 
7217         boolean handled = false;
7218         final ListenerInfo li = mListenerInfo;
7219         if (li != null && li.mOnLongClickListener != null) {
7220             handled = li.mOnLongClickListener.onLongClick(View.this);
7221         }
7222         if (!handled) {
7223             final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
7224             handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
7225         }
7226         if ((mViewFlags & TOOLTIP) == TOOLTIP) {
7227             if (!handled) {
7228                 handled = showLongClickTooltip((int) x, (int) y);
7229             }
7230         }
7231         if (handled) {
7232             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
7233         }
7234         return handled;
7235     }
7236 
7237     /**
7238      * Call this view's OnContextClickListener, if it is defined.
7239      *
7240      * @param x the x coordinate of the context click
7241      * @param y the y coordinate of the context click
7242      * @return True if there was an assigned OnContextClickListener that consumed the event, false
7243      *         otherwise.
7244      */
7245     public boolean performContextClick(float x, float y) {
7246         return performContextClick();
7247     }
7248 
7249     /**
7250      * Call this view's OnContextClickListener, if it is defined.
7251      *
7252      * @return True if there was an assigned OnContextClickListener that consumed the event, false
7253      *         otherwise.
7254      */
7255     public boolean performContextClick() {
7256         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
7257 
7258         boolean handled = false;
7259         ListenerInfo li = mListenerInfo;
7260         if (li != null && li.mOnContextClickListener != null) {
7261             handled = li.mOnContextClickListener.onContextClick(View.this);
7262         }
7263         if (handled) {
7264             performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
7265         }
7266         return handled;
7267     }
7268 
7269     /**
7270      * Performs button-related actions during a touch down event.
7271      *
7272      * @param event The event.
7273      * @return True if the down was consumed.
7274      *
7275      * @hide
7276      */
7277     protected boolean performButtonActionOnTouchDown(MotionEvent event) {
7278         if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
7279             (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
7280             showContextMenu(event.getX(), event.getY());
7281             mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
7282             return true;
7283         }
7284         return false;
7285     }
7286 
7287     /**
7288      * Shows the context menu for this view.
7289      *
7290      * @return {@code true} if the context menu was shown, {@code false}
7291      *         otherwise
7292      * @see #showContextMenu(float, float)
7293      */
7294     public boolean showContextMenu() {
7295         return getParent().showContextMenuForChild(this);
7296     }
7297 
7298     /**
7299      * Shows the context menu for this view anchored to the specified
7300      * view-relative coordinate.
7301      *
7302      * @param x the X coordinate in pixels relative to the view to which the
7303      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
7304      * @param y the Y coordinate in pixels relative to the view to which the
7305      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
7306      * @return {@code true} if the context menu was shown, {@code false}
7307      *         otherwise
7308      */
7309     public boolean showContextMenu(float x, float y) {
7310         return getParent().showContextMenuForChild(this, x, y);
7311     }
7312 
7313     /**
7314      * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
7315      *
7316      * @param callback Callback that will control the lifecycle of the action mode
7317      * @return The new action mode if it is started, null otherwise
7318      *
7319      * @see ActionMode
7320      * @see #startActionMode(android.view.ActionMode.Callback, int)
7321      */
7322     public ActionMode startActionMode(ActionMode.Callback callback) {
7323         return startActionMode(callback, ActionMode.TYPE_PRIMARY);
7324     }
7325 
7326     /**
7327      * Start an action mode with the given type.
7328      *
7329      * @param callback Callback that will control the lifecycle of the action mode
7330      * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
7331      * @return The new action mode if it is started, null otherwise
7332      *
7333      * @see ActionMode
7334      */
7335     public ActionMode startActionMode(ActionMode.Callback callback, int type) {
7336         ViewParent parent = getParent();
7337         if (parent == null) return null;
7338         try {
7339             return parent.startActionModeForChild(this, callback, type);
7340         } catch (AbstractMethodError ame) {
7341             // Older implementations of custom views might not implement this.
7342             return parent.startActionModeForChild(this, callback);
7343         }
7344     }
7345 
7346     /**
7347      * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
7348      * Context, creating a unique View identifier to retrieve the result.
7349      *
7350      * @param intent The Intent to be started.
7351      * @param requestCode The request code to use.
7352      * @hide
7353      */
7354     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
7355     public void startActivityForResult(Intent intent, int requestCode) {
7356         mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
7357         getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
7358     }
7359 
7360     /**
7361      * If this View corresponds to the calling who, dispatches the activity result.
7362      * @param who The identifier for the targeted View to receive the result.
7363      * @param requestCode The integer request code originally supplied to
7364      *                    startActivityForResult(), allowing you to identify who this
7365      *                    result came from.
7366      * @param resultCode The integer result code returned by the child activity
7367      *                   through its setResult().
7368      * @param data An Intent, which can return result data to the caller
7369      *               (various data can be attached to Intent "extras").
7370      * @return {@code true} if the activity result was dispatched.
7371      * @hide
7372      */
7373     public boolean dispatchActivityResult(
7374             String who, int requestCode, int resultCode, Intent data) {
7375         if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
7376             onActivityResult(requestCode, resultCode, data);
7377             mStartActivityRequestWho = null;
7378             return true;
7379         }
7380         return false;
7381     }
7382 
7383     /**
7384      * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
7385      *
7386      * @param requestCode The integer request code originally supplied to
7387      *                    startActivityForResult(), allowing you to identify who this
7388      *                    result came from.
7389      * @param resultCode The integer result code returned by the child activity
7390      *                   through its setResult().
7391      * @param data An Intent, which can return result data to the caller
7392      *               (various data can be attached to Intent "extras").
7393      * @hide
7394      */
7395     public void onActivityResult(int requestCode, int resultCode, Intent data) {
7396         // Do nothing.
7397     }
7398 
7399     /**
7400      * Register a callback to be invoked when a hardware key is pressed in this view.
7401      * Key presses in software input methods will generally not trigger the methods of
7402      * this listener.
7403      * @param l the key listener to attach to this view
7404      */
7405     public void setOnKeyListener(OnKeyListener l) {
7406         getListenerInfo().mOnKeyListener = l;
7407     }
7408 
7409     /**
7410      * Register a callback to be invoked when a touch event is sent to this view.
7411      * @param l the touch listener to attach to this view
7412      */
7413     public void setOnTouchListener(OnTouchListener l) {
7414         getListenerInfo().mOnTouchListener = l;
7415     }
7416 
7417     /**
7418      * Register a callback to be invoked when a generic motion event is sent to this view.
7419      * @param l the generic motion listener to attach to this view
7420      */
7421     public void setOnGenericMotionListener(OnGenericMotionListener l) {
7422         getListenerInfo().mOnGenericMotionListener = l;
7423     }
7424 
7425     /**
7426      * Register a callback to be invoked when a hover event is sent to this view.
7427      * @param l the hover listener to attach to this view
7428      */
7429     public void setOnHoverListener(OnHoverListener l) {
7430         getListenerInfo().mOnHoverListener = l;
7431     }
7432 
7433     /**
7434      * Register a drag event listener callback object for this View. The parameter is
7435      * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
7436      * View, the system calls the
7437      * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
7438      * @param l An implementation of {@link android.view.View.OnDragListener}.
7439      */
7440     public void setOnDragListener(OnDragListener l) {
7441         getListenerInfo().mOnDragListener = l;
7442     }
7443 
7444     /**
7445      * Give this view focus. This will cause
7446      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
7447      *
7448      * Note: this does not check whether this {@link View} should get focus, it just
7449      * gives it focus no matter what.  It should only be called internally by framework
7450      * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
7451      *
7452      * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
7453      *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
7454      *        focus moved when requestFocus() is called. It may not always
7455      *        apply, in which case use the default View.FOCUS_DOWN.
7456      * @param previouslyFocusedRect The rectangle of the view that had focus
7457      *        prior in this View's coordinate system.
7458      */
7459     void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
7460         if (DBG) {
7461             System.out.println(this + " requestFocus()");
7462         }
7463 
7464         if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
7465             mPrivateFlags |= PFLAG_FOCUSED;
7466 
7467             View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
7468 
7469             if (mParent != null) {
7470                 mParent.requestChildFocus(this, this);
7471                 updateFocusedInCluster(oldFocus, direction);
7472             }
7473 
7474             if (mAttachInfo != null) {
7475                 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
7476             }
7477 
7478             onFocusChanged(true, direction, previouslyFocusedRect);
7479             refreshDrawableState();
7480         }
7481     }
7482 
7483     /**
7484      * Sets this view's preference for reveal behavior when it gains focus.
7485      *
7486      * <p>When set to true, this is a signal to ancestor views in the hierarchy that
7487      * this view would prefer to be brought fully into view when it gains focus.
7488      * For example, a text field that a user is meant to type into. Other views such
7489      * as scrolling containers may prefer to opt-out of this behavior.</p>
7490      *
7491      * <p>The default value for views is true, though subclasses may change this
7492      * based on their preferred behavior.</p>
7493      *
7494      * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
7495      *
7496      * @see #getRevealOnFocusHint()
7497      */
7498     public final void setRevealOnFocusHint(boolean revealOnFocus) {
7499         if (revealOnFocus) {
7500             mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
7501         } else {
7502             mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
7503         }
7504     }
7505 
7506     /**
7507      * Returns this view's preference for reveal behavior when it gains focus.
7508      *
7509      * <p>When this method returns true for a child view requesting focus, ancestor
7510      * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
7511      * should make a best effort to make the newly focused child fully visible to the user.
7512      * When it returns false, ancestor views should preferably not disrupt scroll positioning or
7513      * other properties affecting visibility to the user as part of the focus change.</p>
7514      *
7515      * @return true if this view would prefer to become fully visible when it gains focus,
7516      *         false if it would prefer not to disrupt scroll positioning
7517      *
7518      * @see #setRevealOnFocusHint(boolean)
7519      */
7520     public final boolean getRevealOnFocusHint() {
7521         return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
7522     }
7523 
7524     /**
7525      * Populates <code>outRect</code> with the hotspot bounds. By default,
7526      * the hotspot bounds are identical to the screen bounds.
7527      *
7528      * @param outRect rect to populate with hotspot bounds
7529      * @hide Only for internal use by views and widgets.
7530      */
7531     public void getHotspotBounds(Rect outRect) {
7532         final Drawable background = getBackground();
7533         if (background != null) {
7534             background.getHotspotBounds(outRect);
7535         } else {
7536             getBoundsOnScreen(outRect);
7537         }
7538     }
7539 
7540     /**
7541      * Request that a rectangle of this view be visible on the screen,
7542      * scrolling if necessary just enough.
7543      *
7544      * <p>A View should call this if it maintains some notion of which part
7545      * of its content is interesting.  For example, a text editing view
7546      * should call this when its cursor moves.
7547      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
7548      * It should not be affected by which part of the View is currently visible or its scroll
7549      * position.
7550      *
7551      * @param rectangle The rectangle in the View's content coordinate space
7552      * @return Whether any parent scrolled.
7553      */
7554     public boolean requestRectangleOnScreen(Rect rectangle) {
7555         return requestRectangleOnScreen(rectangle, false);
7556     }
7557 
7558     /**
7559      * Request that a rectangle of this view be visible on the screen,
7560      * scrolling if necessary just enough.
7561      *
7562      * <p>A View should call this if it maintains some notion of which part
7563      * of its content is interesting.  For example, a text editing view
7564      * should call this when its cursor moves.
7565      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
7566      * It should not be affected by which part of the View is currently visible or its scroll
7567      * position.
7568      * <p>When <code>immediate</code> is set to true, scrolling will not be
7569      * animated.
7570      *
7571      * @param rectangle The rectangle in the View's content coordinate space
7572      * @param immediate True to forbid animated scrolling, false otherwise
7573      * @return Whether any parent scrolled.
7574      */
7575     public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
7576         if (mParent == null) {
7577             return false;
7578         }
7579 
7580         View child = this;
7581 
7582         RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
7583         position.set(rectangle);
7584 
7585         ViewParent parent = mParent;
7586         boolean scrolled = false;
7587         while (parent != null) {
7588             rectangle.set((int) position.left, (int) position.top,
7589                     (int) position.right, (int) position.bottom);
7590 
7591             scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
7592 
7593             if (!(parent instanceof View)) {
7594                 break;
7595             }
7596 
7597             // move it from child's content coordinate space to parent's content coordinate space
7598             position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
7599 
7600             child = (View) parent;
7601             parent = child.getParent();
7602         }
7603 
7604         return scrolled;
7605     }
7606 
7607     /**
7608      * Called when this view wants to give up focus. If focus is cleared
7609      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
7610      * <p>
7611      * <strong>Note:</strong> When not in touch-mode, the framework will try to give focus
7612      * to the first focusable View from the top after focus is cleared. Hence, if this
7613      * View is the first from the top that can take focus, then all callbacks
7614      * related to clearing focus will be invoked after which the framework will
7615      * give focus to this view.
7616      * </p>
7617      */
7618     public void clearFocus() {
7619         if (DBG) {
7620             System.out.println(this + " clearFocus()");
7621         }
7622 
7623         final boolean refocus = sAlwaysAssignFocus || !isInTouchMode();
7624         clearFocusInternal(null, true, refocus);
7625     }
7626 
7627     /**
7628      * Clears focus from the view, optionally propagating the change up through
7629      * the parent hierarchy and requesting that the root view place new focus.
7630      *
7631      * @param propagate whether to propagate the change up through the parent
7632      *            hierarchy
7633      * @param refocus when propagate is true, specifies whether to request the
7634      *            root view place new focus
7635      */
7636     void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
7637         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
7638             mPrivateFlags &= ~PFLAG_FOCUSED;
7639             clearParentsWantFocus();
7640 
7641             if (propagate && mParent != null) {
7642                 mParent.clearChildFocus(this);
7643             }
7644 
7645             onFocusChanged(false, 0, null);
7646             refreshDrawableState();
7647 
7648             if (propagate && (!refocus || !rootViewRequestFocus())) {
7649                 notifyGlobalFocusCleared(this);
7650             }
7651         }
7652     }
7653 
7654     void notifyGlobalFocusCleared(View oldFocus) {
7655         if (oldFocus != null && mAttachInfo != null) {
7656             mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
7657         }
7658     }
7659 
7660     boolean rootViewRequestFocus() {
7661         final View root = getRootView();
7662         return root != null && root.requestFocus();
7663     }
7664 
7665     /**
7666      * Called internally by the view system when a new view is getting focus.
7667      * This is what clears the old focus.
7668      * <p>
7669      * <b>NOTE:</b> The parent view's focused child must be updated manually
7670      * after calling this method. Otherwise, the view hierarchy may be left in
7671      * an inconstent state.
7672      */
7673     void unFocus(View focused) {
7674         if (DBG) {
7675             System.out.println(this + " unFocus()");
7676         }
7677 
7678         clearFocusInternal(focused, false, false);
7679     }
7680 
7681     /**
7682      * Returns true if this view has focus itself, or is the ancestor of the
7683      * view that has focus.
7684      *
7685      * @return True if this view has or contains focus, false otherwise.
7686      */
7687     @ViewDebug.ExportedProperty(category = "focus")
7688     public boolean hasFocus() {
7689         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
7690     }
7691 
7692     /**
7693      * Returns true if this view is focusable or if it contains a reachable View
7694      * for which {@link #hasFocusable()} returns {@code true}. A "reachable hasFocusable()"
7695      * is a view whose parents do not block descendants focus.
7696      * Only {@link #VISIBLE} views are considered focusable.
7697      *
7698      * <p>As of {@link Build.VERSION_CODES#O} views that are determined to be focusable
7699      * through {@link #FOCUSABLE_AUTO} will also cause this method to return {@code true}.
7700      * Apps that declare a {@link android.content.pm.ApplicationInfo#targetSdkVersion} of
7701      * earlier than {@link Build.VERSION_CODES#O} will continue to see this method return
7702      * {@code false} for views not explicitly marked as focusable.
7703      * Use {@link #hasExplicitFocusable()} if you require the pre-{@link Build.VERSION_CODES#O}
7704      * behavior.</p>
7705      *
7706      * @return {@code true} if the view is focusable or if the view contains a focusable
7707      *         view, {@code false} otherwise
7708      *
7709      * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
7710      * @see ViewGroup#getTouchscreenBlocksFocus()
7711      * @see #hasExplicitFocusable()
7712      */
7713     public boolean hasFocusable() {
7714         return hasFocusable(!sHasFocusableExcludeAutoFocusable, false);
7715     }
7716 
7717     /**
7718      * Returns true if this view is focusable or if it contains a reachable View
7719      * for which {@link #hasExplicitFocusable()} returns {@code true}.
7720      * A "reachable hasExplicitFocusable()" is a view whose parents do not block descendants focus.
7721      * Only {@link #VISIBLE} views for which {@link #getFocusable()} would return
7722      * {@link #FOCUSABLE} are considered focusable.
7723      *
7724      * <p>This method preserves the pre-{@link Build.VERSION_CODES#O} behavior of
7725      * {@link #hasFocusable()} in that only views explicitly set focusable will cause
7726      * this method to return true. A view set to {@link #FOCUSABLE_AUTO} that resolves
7727      * to focusable will not.</p>
7728      *
7729      * @return {@code true} if the view is focusable or if the view contains a focusable
7730      *         view, {@code false} otherwise
7731      *
7732      * @see #hasFocusable()
7733      */
7734     public boolean hasExplicitFocusable() {
7735         return hasFocusable(false, true);
7736     }
7737 
7738     boolean hasFocusable(boolean allowAutoFocus, boolean dispatchExplicit) {
7739         if (!isFocusableInTouchMode()) {
7740             for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
7741                 final ViewGroup g = (ViewGroup) p;
7742                 if (g.shouldBlockFocusForTouchscreen()) {
7743                     return false;
7744                 }
7745             }
7746         }
7747 
7748         // Invisible, gone, or disabled views are never focusable.
7749         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE
7750                 || (mViewFlags & ENABLED_MASK) != ENABLED) {
7751             return false;
7752         }
7753 
7754         // Only use effective focusable value when allowed.
7755         if ((allowAutoFocus || getFocusable() != FOCUSABLE_AUTO) && isFocusable()) {
7756             return true;
7757         }
7758 
7759         return false;
7760     }
7761 
7762     /**
7763      * Called by the view system when the focus state of this view changes.
7764      * When the focus change event is caused by directional navigation, direction
7765      * and previouslyFocusedRect provide insight into where the focus is coming from.
7766      * When overriding, be sure to call up through to the super class so that
7767      * the standard focus handling will occur.
7768      *
7769      * @param gainFocus True if the View has focus; false otherwise.
7770      * @param direction The direction focus has moved when requestFocus()
7771      *                  is called to give this view focus. Values are
7772      *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
7773      *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
7774      *                  It may not always apply, in which case use the default.
7775      * @param previouslyFocusedRect The rectangle, in this view's coordinate
7776      *        system, of the previously focused view.  If applicable, this will be
7777      *        passed in as finer grained information about where the focus is coming
7778      *        from (in addition to direction).  Will be <code>null</code> otherwise.
7779      */
7780     @CallSuper
7781     protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
7782             @Nullable Rect previouslyFocusedRect) {
7783         if (gainFocus) {
7784             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
7785         } else {
7786             notifyViewAccessibilityStateChangedIfNeeded(
7787                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7788         }
7789 
7790         // Here we check whether we still need the default focus highlight, and switch it on/off.
7791         switchDefaultFocusHighlight();
7792 
7793         if (!gainFocus) {
7794             if (isPressed()) {
7795                 setPressed(false);
7796             }
7797             if (mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
7798                 notifyFocusChangeToInputMethodManager(false /* hasFocus */);
7799             }
7800             onFocusLost();
7801         } else if (mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
7802             notifyFocusChangeToInputMethodManager(true /* hasFocus */);
7803         }
7804 
7805         invalidate(true);
7806         ListenerInfo li = mListenerInfo;
7807         if (li != null && li.mOnFocusChangeListener != null) {
7808             li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
7809         }
7810 
7811         if (mAttachInfo != null) {
7812             mAttachInfo.mKeyDispatchState.reset(this);
7813         }
7814 
7815         notifyEnterOrExitForAutoFillIfNeeded(gainFocus);
7816     }
7817 
7818     /**
7819      * Notify {@link InputMethodManager} about the focus change of the {@link View}.
7820      *
7821      * <p>Does nothing when {@link InputMethodManager} is not available.</p>
7822      *
7823      * @param hasFocus {@code true} when the {@link View} is being focused.
7824      */
7825     private void notifyFocusChangeToInputMethodManager(boolean hasFocus) {
7826         final InputMethodManager imm =
7827                 getContext().getSystemService(InputMethodManager.class);
7828         if (imm == null) {
7829             return;
7830         }
7831         if (hasFocus) {
7832             imm.focusIn(this);
7833         } else {
7834             imm.focusOut(this);
7835         }
7836     }
7837 
7838     /** @hide */
7839     public void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {
7840         if (canNotifyAutofillEnterExitEvent()) {
7841             AutofillManager afm = getAutofillManager();
7842             if (afm != null) {
7843                 if (enter && isFocused()) {
7844                     // We have not been laid out yet, hence cannot evaluate
7845                     // whether this view is visible to the user, we will do
7846                     // the evaluation once layout is complete.
7847                     if (!isLaidOut()) {
7848                         mPrivateFlags3 |= PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
7849                     } else if (isVisibleToUser()) {
7850                         // TODO This is a potential problem that View gets focus before it's visible
7851                         // to User. Ideally View should handle the event when isVisibleToUser()
7852                         // becomes true where it should issue notifyViewEntered().
7853                         afm.notifyViewEntered(this);
7854                     }
7855                 } else if (!enter && !isFocused()) {
7856                     afm.notifyViewExited(this);
7857                 }
7858             }
7859         }
7860     }
7861 
7862     /**
7863      * Visually distinct portion of a window with window-like semantics are considered panes for
7864      * accessibility purposes. One example is the content view of a fragment that is replaced.
7865      * In order for accessibility services to understand a pane's window-like behavior, panes
7866      * should have descriptive titles. Views with pane titles produce {@link AccessibilityEvent}s
7867      * when they appear, disappear, or change title.
7868      *
7869      * @param accessibilityPaneTitle The pane's title. Setting to {@code null} indicates that this
7870      *                               View is not a pane.
7871      *
7872      * {@see AccessibilityNodeInfo#setPaneTitle(CharSequence)}
7873      *
7874      * @attr ref android.R.styleable#View_accessibilityPaneTitle
7875      */
7876     public void setAccessibilityPaneTitle(@Nullable CharSequence accessibilityPaneTitle) {
7877         if (!TextUtils.equals(accessibilityPaneTitle, mAccessibilityPaneTitle)) {
7878             mAccessibilityPaneTitle = accessibilityPaneTitle;
7879             notifyViewAccessibilityStateChangedIfNeeded(
7880                     AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_TITLE);
7881         }
7882     }
7883 
7884     /**
7885      * Get the title of the pane for purposes of accessibility.
7886      *
7887      * @return The current pane title.
7888      *
7889      * {@see #setAccessibilityPaneTitle}.
7890      *
7891      * @attr ref android.R.styleable#View_accessibilityPaneTitle
7892      */
7893     @InspectableProperty
7894     @Nullable
7895     public CharSequence getAccessibilityPaneTitle() {
7896         return mAccessibilityPaneTitle;
7897     }
7898 
7899     private boolean isAccessibilityPane() {
7900         return mAccessibilityPaneTitle != null;
7901     }
7902 
7903     /**
7904      * Sends an accessibility event of the given type. If accessibility is
7905      * not enabled this method has no effect. The default implementation calls
7906      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
7907      * to populate information about the event source (this View), then calls
7908      * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
7909      * populate the text content of the event source including its descendants,
7910      * and last calls
7911      * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
7912      * on its parent to request sending of the event to interested parties.
7913      * <p>
7914      * If an {@link AccessibilityDelegate} has been specified via calling
7915      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7916      * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
7917      * responsible for handling this call.
7918      * </p>
7919      *
7920      * @param eventType The type of the event to send, as defined by several types from
7921      * {@link android.view.accessibility.AccessibilityEvent}, such as
7922      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
7923      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
7924      *
7925      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
7926      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7927      * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
7928      * @see AccessibilityDelegate
7929      */
7930     public void sendAccessibilityEvent(int eventType) {
7931         if (mAccessibilityDelegate != null) {
7932             mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
7933         } else {
7934             sendAccessibilityEventInternal(eventType);
7935         }
7936     }
7937 
7938     /**
7939      * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
7940      * {@link AccessibilityEvent} to suggest that an accessibility service announce the
7941      * specified text to its users.
7942      * <p>
7943      * Note: The event generated with this API carries no semantic meaning, and is appropriate only
7944      * in exceptional situations. Apps can generally achieve correct behavior for accessibility by
7945      * accurately supplying the semantics of their UI.
7946      * They should not need to specify what exactly is announced to users.
7947      *
7948      * @param text The announcement text.
7949      */
7950     public void announceForAccessibility(CharSequence text) {
7951         if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
7952             AccessibilityEvent event = AccessibilityEvent.obtain(
7953                     AccessibilityEvent.TYPE_ANNOUNCEMENT);
7954             onInitializeAccessibilityEvent(event);
7955             event.getText().add(text);
7956             event.setContentDescription(null);
7957             mParent.requestSendAccessibilityEvent(this, event);
7958         }
7959     }
7960 
7961     /**
7962      * @see #sendAccessibilityEvent(int)
7963      *
7964      * Note: Called from the default {@link AccessibilityDelegate}.
7965      *
7966      * @hide
7967      */
7968     public void sendAccessibilityEventInternal(int eventType) {
7969         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
7970             sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
7971         }
7972     }
7973 
7974     /**
7975      * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
7976      * takes as an argument an empty {@link AccessibilityEvent} and does not
7977      * perform a check whether accessibility is enabled.
7978      * <p>
7979      * If an {@link AccessibilityDelegate} has been specified via calling
7980      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7981      * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
7982      * is responsible for handling this call.
7983      * </p>
7984      *
7985      * @param event The event to send.
7986      *
7987      * @see #sendAccessibilityEvent(int)
7988      */
7989     public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
7990         if (mAccessibilityDelegate != null) {
7991             mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
7992         } else {
7993             sendAccessibilityEventUncheckedInternal(event);
7994         }
7995     }
7996 
7997     /**
7998      * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
7999      *
8000      * Note: Called from the default {@link AccessibilityDelegate}.
8001      *
8002      * @hide
8003      */
8004     public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
8005         // Panes disappearing are relevant even if though the view is no longer visible.
8006         boolean isWindowStateChanged =
8007                 (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
8008         boolean isWindowDisappearedEvent = isWindowStateChanged && ((event.getContentChangeTypes()
8009                 & AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED) != 0);
8010         if (!isShown() && !isWindowDisappearedEvent) {
8011             return;
8012         }
8013         onInitializeAccessibilityEvent(event);
8014         // Only a subset of accessibility events populates text content.
8015         if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
8016             dispatchPopulateAccessibilityEvent(event);
8017         }
8018         // In the beginning we called #isShown(), so we know that getParent() is not null.
8019         ViewParent parent = getParent();
8020         if (parent != null) {
8021             getParent().requestSendAccessibilityEvent(this, event);
8022         }
8023     }
8024 
8025     /**
8026      * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
8027      * to its children for adding their text content to the event. Note that the
8028      * event text is populated in a separate dispatch path since we add to the
8029      * event not only the text of the source but also the text of all its descendants.
8030      * A typical implementation will call
8031      * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
8032      * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
8033      * on each child. Override this method if custom population of the event text
8034      * content is required.
8035      * <p>
8036      * If an {@link AccessibilityDelegate} has been specified via calling
8037      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8038      * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
8039      * is responsible for handling this call.
8040      * </p>
8041      * <p>
8042      * <em>Note:</em> Accessibility events of certain types are not dispatched for
8043      * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
8044      * </p>
8045      *
8046      * @param event The event.
8047      *
8048      * @return True if the event population was completed.
8049      */
8050     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
8051         if (mAccessibilityDelegate != null) {
8052             return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
8053         } else {
8054             return dispatchPopulateAccessibilityEventInternal(event);
8055         }
8056     }
8057 
8058     /**
8059      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
8060      *
8061      * Note: Called from the default {@link AccessibilityDelegate}.
8062      *
8063      * @hide
8064      */
8065     public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
8066         onPopulateAccessibilityEvent(event);
8067         return false;
8068     }
8069 
8070     /**
8071      * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
8072      * giving a chance to this View to populate the accessibility event with its
8073      * text content. While this method is free to modify event
8074      * attributes other than text content, doing so should normally be performed in
8075      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
8076      * <p>
8077      * Example: Adding formatted date string to an accessibility event in addition
8078      *          to the text added by the super implementation:
8079      * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
8080      *     super.onPopulateAccessibilityEvent(event);
8081      *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
8082      *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
8083      *         mCurrentDate.getTimeInMillis(), flags);
8084      *     event.getText().add(selectedDateUtterance);
8085      * }</pre>
8086      * <p>
8087      * If an {@link AccessibilityDelegate} has been specified via calling
8088      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8089      * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
8090      * is responsible for handling this call.
8091      * </p>
8092      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
8093      * information to the event, in case the default implementation has basic information to add.
8094      * </p>
8095      *
8096      * @param event The accessibility event which to populate.
8097      *
8098      * @see #sendAccessibilityEvent(int)
8099      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
8100      */
8101     @CallSuper
8102     public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
8103         if (mAccessibilityDelegate != null) {
8104             mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
8105         } else {
8106             onPopulateAccessibilityEventInternal(event);
8107         }
8108     }
8109 
8110     /**
8111      * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
8112      *
8113      * Note: Called from the default {@link AccessibilityDelegate}.
8114      *
8115      * @hide
8116      */
8117     public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
8118         if ((event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED)
8119                 && isAccessibilityPane()) {
8120             event.getText().add(getAccessibilityPaneTitle());
8121         }
8122     }
8123 
8124     /**
8125      * Initializes an {@link AccessibilityEvent} with information about
8126      * this View which is the event source. In other words, the source of
8127      * an accessibility event is the view whose state change triggered firing
8128      * the event.
8129      * <p>
8130      * Example: Setting the password property of an event in addition
8131      *          to properties set by the super implementation:
8132      * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
8133      *     super.onInitializeAccessibilityEvent(event);
8134      *     event.setPassword(true);
8135      * }</pre>
8136      * <p>
8137      * If an {@link AccessibilityDelegate} has been specified via calling
8138      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8139      * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
8140      * is responsible for handling this call.
8141      * </p>
8142      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
8143      * information to the event, in case the default implementation has basic information to add.
8144      * </p>
8145      * @param event The event to initialize.
8146      *
8147      * @see #sendAccessibilityEvent(int)
8148      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
8149      */
8150     @CallSuper
8151     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
8152         if (mAccessibilityDelegate != null) {
8153             mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
8154         } else {
8155             onInitializeAccessibilityEventInternal(event);
8156         }
8157     }
8158 
8159     /**
8160      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
8161      *
8162      * Note: Called from the default {@link AccessibilityDelegate}.
8163      *
8164      * @hide
8165      */
8166     @UnsupportedAppUsage
8167     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
8168         event.setSource(this);
8169         event.setClassName(getAccessibilityClassName());
8170         event.setPackageName(getContext().getPackageName());
8171         event.setEnabled(isEnabled());
8172         event.setContentDescription(mContentDescription);
8173 
8174         switch (event.getEventType()) {
8175             case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
8176                 ArrayList<View> focusablesTempList = (mAttachInfo != null)
8177                         ? mAttachInfo.mTempArrayList : new ArrayList<View>();
8178                 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
8179                 event.setItemCount(focusablesTempList.size());
8180                 event.setCurrentItemIndex(focusablesTempList.indexOf(this));
8181                 if (mAttachInfo != null) {
8182                     focusablesTempList.clear();
8183                 }
8184             } break;
8185             case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
8186                 CharSequence text = getIterableTextForAccessibility();
8187                 if (text != null && text.length() > 0) {
8188                     event.setFromIndex(getAccessibilitySelectionStart());
8189                     event.setToIndex(getAccessibilitySelectionEnd());
8190                     event.setItemCount(text.length());
8191                 }
8192             } break;
8193         }
8194     }
8195 
8196     /**
8197      * Returns an {@link AccessibilityNodeInfo} representing this view from the
8198      * point of view of an {@link android.accessibilityservice.AccessibilityService}.
8199      * This method is responsible for obtaining an accessibility node info from a
8200      * pool of reusable instances and calling
8201      * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
8202      * initialize the former.
8203      * <p>
8204      * Note: The client is responsible for recycling the obtained instance by calling
8205      *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
8206      * </p>
8207      *
8208      * @return A populated {@link AccessibilityNodeInfo}.
8209      *
8210      * @see AccessibilityNodeInfo
8211      */
8212     public AccessibilityNodeInfo createAccessibilityNodeInfo() {
8213         if (mAccessibilityDelegate != null) {
8214             return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
8215         } else {
8216             return createAccessibilityNodeInfoInternal();
8217         }
8218     }
8219 
8220     /**
8221      * @see #createAccessibilityNodeInfo()
8222      *
8223      * @hide
8224      */
8225     public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
8226         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
8227         if (provider != null) {
8228             return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
8229         } else {
8230             AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
8231             onInitializeAccessibilityNodeInfo(info);
8232             return info;
8233         }
8234     }
8235 
8236     /**
8237      * Initializes an {@link AccessibilityNodeInfo} with information about this view.
8238      * The base implementation sets:
8239      * <ul>
8240      *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
8241      *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
8242      *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
8243      *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
8244      *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
8245      *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
8246      *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
8247      *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
8248      *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
8249      *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
8250      *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
8251      *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
8252      *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
8253      * </ul>
8254      * <p>
8255      * Subclasses should override this method, call the super implementation,
8256      * and set additional attributes.
8257      * </p>
8258      * <p>
8259      * If an {@link AccessibilityDelegate} has been specified via calling
8260      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8261      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
8262      * is responsible for handling this call.
8263      * </p>
8264      *
8265      * @param info The instance to initialize.
8266      */
8267     @CallSuper
8268     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
8269         if (mAccessibilityDelegate != null) {
8270             mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
8271         } else {
8272             onInitializeAccessibilityNodeInfoInternal(info);
8273         }
8274     }
8275 
8276     /**
8277      * Gets the location of this view in screen coordinates.
8278      *
8279      * @param outRect The output location
8280      * @hide
8281      */
8282     @UnsupportedAppUsage
8283     public void getBoundsOnScreen(Rect outRect) {
8284         getBoundsOnScreen(outRect, false);
8285     }
8286 
8287     /**
8288      * Gets the location of this view in screen coordinates.
8289      *
8290      * @param outRect The output location
8291      * @param clipToParent Whether to clip child bounds to the parent ones.
8292      * @hide
8293      */
8294     @UnsupportedAppUsage
8295     public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
8296         if (mAttachInfo == null) {
8297             return;
8298         }
8299 
8300         RectF position = mAttachInfo.mTmpTransformRect;
8301         position.set(0, 0, mRight - mLeft, mBottom - mTop);
8302         mapRectFromViewToScreenCoords(position, clipToParent);
8303         outRect.set(Math.round(position.left), Math.round(position.top),
8304                 Math.round(position.right), Math.round(position.bottom));
8305     }
8306 
8307     /**
8308      * Map a rectangle from view-relative coordinates to screen-relative coordinates
8309      *
8310      * @param rect The rectangle to be mapped
8311      * @param clipToParent Whether to clip child bounds to the parent ones.
8312      * @hide
8313      */
8314     public void mapRectFromViewToScreenCoords(RectF rect, boolean clipToParent) {
8315         if (!hasIdentityMatrix()) {
8316             getMatrix().mapRect(rect);
8317         }
8318 
8319         rect.offset(mLeft, mTop);
8320 
8321         ViewParent parent = mParent;
8322         while (parent instanceof View) {
8323             View parentView = (View) parent;
8324 
8325             rect.offset(-parentView.mScrollX, -parentView.mScrollY);
8326 
8327             if (clipToParent) {
8328                 rect.left = Math.max(rect.left, 0);
8329                 rect.top = Math.max(rect.top, 0);
8330                 rect.right = Math.min(rect.right, parentView.getWidth());
8331                 rect.bottom = Math.min(rect.bottom, parentView.getHeight());
8332             }
8333 
8334             if (!parentView.hasIdentityMatrix()) {
8335                 parentView.getMatrix().mapRect(rect);
8336             }
8337 
8338             rect.offset(parentView.mLeft, parentView.mTop);
8339 
8340             parent = parentView.mParent;
8341         }
8342 
8343         if (parent instanceof ViewRootImpl) {
8344             ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
8345             rect.offset(0, -viewRootImpl.mCurScrollY);
8346         }
8347 
8348         rect.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
8349     }
8350 
8351     /**
8352      * Return the class name of this object to be used for accessibility purposes.
8353      * Subclasses should only override this if they are implementing something that
8354      * should be seen as a completely new class of view when used by accessibility,
8355      * unrelated to the class it is deriving from.  This is used to fill in
8356      * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
8357      */
8358     public CharSequence getAccessibilityClassName() {
8359         return View.class.getName();
8360     }
8361 
8362     /**
8363      * Called when assist structure is being retrieved from a view as part of
8364      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
8365      * @param structure Fill in with structured view data.  The default implementation
8366      * fills in all data that can be inferred from the view itself.
8367      */
8368     public void onProvideStructure(ViewStructure structure) {
8369         onProvideStructure(structure, VIEW_STRUCTURE_FOR_ASSIST, /* flags= */ 0);
8370     }
8371 
8372     /**
8373      * Populates a {@link ViewStructure} to fullfil an autofill request.
8374      *
8375      * <p>The structure should contain at least the following properties:
8376      * <ul>
8377      *   <li>Autofill id ({@link ViewStructure#setAutofillId(AutofillId, int)}).
8378      *   <li>Autofill type ({@link ViewStructure#setAutofillType(int)}).
8379      *   <li>Autofill value ({@link ViewStructure#setAutofillValue(AutofillValue)}).
8380      *   <li>Whether the data is sensitive ({@link ViewStructure#setDataIsSensitive(boolean)}).
8381      * </ul>
8382      *
8383      * <p>It's also recommended to set the following properties - the more properties the structure
8384      * has, the higher the changes of an {@link android.service.autofill.AutofillService} properly
8385      * using the structure:
8386      *
8387      * <ul>
8388      *   <li>Autofill hints ({@link ViewStructure#setAutofillHints(String[])}).
8389      *   <li>Autofill options ({@link ViewStructure#setAutofillOptions(CharSequence[])}) when the
8390      *       view can only be filled with predefined values (typically used when the autofill type
8391      *       is {@link #AUTOFILL_TYPE_LIST}).
8392      *   <li>Resource id ({@link ViewStructure#setId(int, String, String, String)}).
8393      *   <li>Class name ({@link ViewStructure#setClassName(String)}).
8394      *   <li>Content description ({@link ViewStructure#setContentDescription(CharSequence)}).
8395      *   <li>Visual properties such as visibility ({@link ViewStructure#setVisibility(int)}),
8396      *       dimensions ({@link ViewStructure#setDimens(int, int, int, int, int, int)}), and
8397      *       opacity ({@link ViewStructure#setOpaque(boolean)}).
8398      *   <li>For views representing text fields, text properties such as the text itself
8399      *       ({@link ViewStructure#setText(CharSequence)}), text hints
8400      *       ({@link ViewStructure#setHint(CharSequence)}, input type
8401      *       ({@link ViewStructure#setInputType(int)}),
8402      *   <li>For views representing HTML nodes, its web domain
8403      *       ({@link ViewStructure#setWebDomain(String)}) and HTML properties
8404      *       (({@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}).
8405      * </ul>
8406      *
8407      * <p>The default implementation of this method already sets most of these properties based on
8408      * related {@link View} methods (for example, the autofill id is set using
8409      * {@link #getAutofillId()}, the autofill type set using {@link #getAutofillType()}, etc.),
8410      * and views in the standard Android widgets library also override it to set their
8411      * relevant properties (for example, {@link android.widget.TextView} already sets the text
8412      * properties), so it's recommended to only override this method
8413      * (and call {@code super.onProvideAutofillStructure()}) when:
8414      *
8415      * <ul>
8416      *   <li>The view contents does not include PII (Personally Identifiable Information), so it
8417      *       can call {@link ViewStructure#setDataIsSensitive(boolean)} passing {@code false}.
8418      *   <li>The view can only be autofilled with predefined options, so it can call
8419      *       {@link ViewStructure#setAutofillOptions(CharSequence[])}.
8420      * </ul>
8421      *
8422      * <p><b>Note:</b> The {@code left} and {@code top} values set in
8423      * {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the next
8424      * {@link ViewGroup#isImportantForAutofill()} predecessor view included in the structure.
8425      *
8426      * <p>Views support the Autofill Framework mainly by:
8427      * <ul>
8428      *   <li>Providing the metadata defining what the view means and how it can be autofilled.
8429      *   <li>Notifying the Android System when the view value changed by calling
8430      *       {@link AutofillManager#notifyValueChanged(View)}.
8431      *   <li>Implementing the methods that autofill the view.
8432      * </ul>
8433      * <p>This method is responsible for the former; {@link #autofill(AutofillValue)} is responsible
8434      * for the latter.
8435      *
8436      * @param structure fill in with structured view data for autofill purposes.
8437      * @param flags optional flags.
8438      *
8439      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
8440      */
8441     public void onProvideAutofillStructure(ViewStructure structure, @AutofillFlags int flags) {
8442         onProvideStructure(structure, VIEW_STRUCTURE_FOR_AUTOFILL, flags);
8443     }
8444 
8445     /** @hide */
8446     protected void onProvideStructure(@NonNull ViewStructure structure,
8447             @ViewStructureType int viewFor, int flags) {
8448         final int id = mID;
8449         if (id != NO_ID && !isViewIdGenerated(id)) {
8450             String pkg, type, entry;
8451             try {
8452                 final Resources res = getResources();
8453                 entry = res.getResourceEntryName(id);
8454                 type = res.getResourceTypeName(id);
8455                 pkg = res.getResourcePackageName(id);
8456             } catch (Resources.NotFoundException e) {
8457                 entry = type = pkg = null;
8458             }
8459             structure.setId(id, pkg, type, entry);
8460         } else {
8461             structure.setId(id, null, null, null);
8462         }
8463 
8464         if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
8465                 || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
8466             final @AutofillType int autofillType = getAutofillType();
8467             // Don't need to fill autofill info if view does not support it.
8468             // For example, only TextViews that are editable support autofill
8469             if (autofillType != AUTOFILL_TYPE_NONE) {
8470                 structure.setAutofillType(autofillType);
8471                 structure.setAutofillHints(getAutofillHints());
8472                 structure.setAutofillValue(getAutofillValue());
8473             }
8474             structure.setImportantForAutofill(getImportantForAutofill());
8475         }
8476 
8477         int ignoredParentLeft = 0;
8478         int ignoredParentTop = 0;
8479         if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
8480                 && (flags & AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) {
8481             View parentGroup = null;
8482 
8483             ViewParent viewParent = getParent();
8484             if (viewParent instanceof View) {
8485                 parentGroup = (View) viewParent;
8486             }
8487 
8488             while (parentGroup != null && !parentGroup.isImportantForAutofill()) {
8489                 ignoredParentLeft += parentGroup.mLeft;
8490                 ignoredParentTop += parentGroup.mTop;
8491 
8492                 viewParent = parentGroup.getParent();
8493                 if (viewParent instanceof View) {
8494                     parentGroup = (View) viewParent;
8495                 } else {
8496                     break;
8497                 }
8498             }
8499         }
8500 
8501         structure.setDimens(ignoredParentLeft + mLeft, ignoredParentTop + mTop, mScrollX, mScrollY,
8502                 mRight - mLeft, mBottom - mTop);
8503         if (viewFor == VIEW_STRUCTURE_FOR_ASSIST) {
8504             if (!hasIdentityMatrix()) {
8505                 structure.setTransformation(getMatrix());
8506             }
8507             structure.setElevation(getZ());
8508         }
8509         structure.setVisibility(getVisibility());
8510         structure.setEnabled(isEnabled());
8511         if (isClickable()) {
8512             structure.setClickable(true);
8513         }
8514         if (isFocusable()) {
8515             structure.setFocusable(true);
8516         }
8517         if (isFocused()) {
8518             structure.setFocused(true);
8519         }
8520         if (isAccessibilityFocused()) {
8521             structure.setAccessibilityFocused(true);
8522         }
8523         if (isSelected()) {
8524             structure.setSelected(true);
8525         }
8526         if (isActivated()) {
8527             structure.setActivated(true);
8528         }
8529         if (isLongClickable()) {
8530             structure.setLongClickable(true);
8531         }
8532         if (this instanceof Checkable) {
8533             structure.setCheckable(true);
8534             if (((Checkable)this).isChecked()) {
8535                 structure.setChecked(true);
8536             }
8537         }
8538         if (isOpaque()) {
8539             structure.setOpaque(true);
8540         }
8541         if (isContextClickable()) {
8542             structure.setContextClickable(true);
8543         }
8544         structure.setClassName(getAccessibilityClassName().toString());
8545         structure.setContentDescription(getContentDescription());
8546     }
8547 
8548     /**
8549      * Called when assist structure is being retrieved from a view as part of
8550      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
8551      * generate additional virtual structure under this view.  The defaullt implementation
8552      * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
8553      * view's virtual accessibility nodes, if any.  You can override this for a more
8554      * optimal implementation providing this data.
8555      */
8556     public void onProvideVirtualStructure(ViewStructure structure) {
8557         onProvideVirtualStructureCompat(structure, false);
8558     }
8559 
8560     /**
8561      * Fallback implementation to populate a ViewStructure from accessibility state.
8562      *
8563      * @param structure The structure to populate.
8564      * @param forAutofill Whether the structure is needed for autofill.
8565      */
8566     private void onProvideVirtualStructureCompat(ViewStructure structure, boolean forAutofill) {
8567         final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
8568         if (provider != null) {
8569             if (forAutofill && Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
8570                 Log.v(AUTOFILL_LOG_TAG, "onProvideVirtualStructureCompat() for " + this);
8571             }
8572             final AccessibilityNodeInfo info = createAccessibilityNodeInfo();
8573             structure.setChildCount(1);
8574             final ViewStructure root = structure.newChild(0);
8575             populateVirtualStructure(root, provider, info, forAutofill);
8576             info.recycle();
8577         }
8578     }
8579 
8580     /**
8581      * Populates a {@link ViewStructure} containing virtual children to fullfil an autofill
8582      * request.
8583      *
8584      * <p>This method should be used when the view manages a virtual structure under this view. For
8585      * example, a view that draws input fields using {@link #draw(Canvas)}.
8586      *
8587      * <p>When implementing this method, subclasses must follow the rules below:
8588      *
8589      * <ul>
8590      *   <li>Add virtual children by calling the {@link ViewStructure#newChild(int)} or
8591      *       {@link ViewStructure#asyncNewChild(int)} methods, where the {@code id} is an unique id
8592      *       identifying the children in the virtual structure.
8593      *   <li>The children hierarchy can have multiple levels if necessary, but ideally it should
8594      *       exclude intermediate levels that are irrelevant for autofill; that would improve the
8595      *       autofill performance.
8596      *   <li>Also implement {@link #autofill(SparseArray)} to autofill the virtual
8597      *       children.
8598      *   <li>Set the autofill properties of the child structure as defined by
8599      *       {@link #onProvideAutofillStructure(ViewStructure, int)}, using
8600      *       {@link ViewStructure#setAutofillId(AutofillId, int)} to set its autofill id.
8601      *   <li>Call {@link android.view.autofill.AutofillManager#notifyViewEntered(View, int, Rect)}
8602      *       and/or {@link android.view.autofill.AutofillManager#notifyViewExited(View, int)}
8603      *       when the focused virtual child changed.
8604      *   <li>Override {@link #isVisibleToUserForAutofill(int)} to allow the platform to query
8605      *       whether a given virtual view is visible to the user in order to support triggering
8606      *       save when all views of interest go away.
8607      *   <li>Call
8608      *    {@link android.view.autofill.AutofillManager#notifyValueChanged(View, int, AutofillValue)}
8609      *       when the value of a virtual child changed.
8610      *   <li>Call {@link
8611      *    android.view.autofill.AutofillManager#notifyViewVisibilityChanged(View, int, boolean)}
8612      *       when the visibility of a virtual child changed.
8613      *   <li>Call
8614      *    {@link android.view.autofill.AutofillManager#notifyViewClicked(View, int)} when a virtual
8615      *       child is clicked.
8616      *   <li>Call {@link AutofillManager#commit()} when the autofill context of the view structure
8617      *       changed and the current context should be committed (for example, when the user tapped
8618      *       a {@code SUBMIT} button in an HTML page).
8619      *   <li>Call {@link AutofillManager#cancel()} when the autofill context of the view structure
8620      *       changed and the current context should be canceled (for example, when the user tapped
8621      *       a {@code CANCEL} button in an HTML page).
8622      *   <li>Provide ways for users to manually request autofill by calling
8623      *       {@link AutofillManager#requestAutofill(View, int, Rect)}.
8624      *   <li>The {@code left} and {@code top} values set in
8625      *       {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the
8626      *       next {@link ViewGroup#isImportantForAutofill()} predecessor view included in the
8627      *       structure.
8628      * </ul>
8629      *
8630      * <p>Views with virtual children support the Autofill Framework mainly by:
8631      * <ul>
8632      *   <li>Providing the metadata defining what the virtual children mean and how they can be
8633      *       autofilled.
8634      *   <li>Implementing the methods that autofill the virtual children.
8635      * </ul>
8636      * <p>This method is responsible for the former; {@link #autofill(SparseArray)} is responsible
8637      * for the latter.
8638      *
8639      * @param structure fill in with virtual children data for autofill purposes.
8640      * @param flags optional flags.
8641      *
8642      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
8643      */
8644     public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
8645         if (mContext.isAutofillCompatibilityEnabled()) {
8646             onProvideVirtualStructureCompat(structure, true);
8647         }
8648     }
8649 
8650     /**
8651      * Automatically fills the content of this view with the {@code value}.
8652      *
8653      * <p>Views support the Autofill Framework mainly by:
8654      * <ul>
8655      *   <li>Providing the metadata defining what the view means and how it can be autofilled.
8656      *   <li>Implementing the methods that autofill the view.
8657      * </ul>
8658      * <p>{@link #onProvideAutofillStructure(ViewStructure, int)} is responsible for the former,
8659      * this method is responsible for latter.
8660      *
8661      * <p>This method does nothing by default, but when overridden it typically:
8662      * <ol>
8663      *   <li>Checks if the provided value matches the expected type (which is defined by
8664      *       {@link #getAutofillType()}).
8665      *   <li>Checks if the view is editable - if it isn't, it should return right away.
8666      *   <li>Call the proper getter method on {@link AutofillValue} to fetch the actual value.
8667      *   <li>Pass the actual value to the equivalent setter in the view.
8668      * </ol>
8669      *
8670      * <p>For example, a text-field view could implement the method this way:
8671      *
8672      * <pre class="prettyprint">
8673      * &#64;Override
8674      * public void autofill(AutofillValue value) {
8675      *   if (!value.isText() || !this.isEditable()) {
8676      *      return;
8677      *   }
8678      *   CharSequence text = value.getTextValue();
8679      *   if (text != null) {
8680      *     this.setText(text);
8681      *   }
8682      * }
8683      * </pre>
8684      *
8685      * <p>If the value is updated asynchronously, the next call to
8686      * {@link AutofillManager#notifyValueChanged(View)} must happen <b>after</b> the value was
8687      * changed to the autofilled value. If not, the view will not be considered autofilled.
8688      *
8689      * <p><b>Note:</b> After this method is called, the value returned by
8690      * {@link #getAutofillValue()} must be equal to the {@code value} passed to it, otherwise the
8691      * view will not be highlighted as autofilled.
8692      *
8693      * @param value value to be autofilled.
8694      */
8695     public void autofill(@SuppressWarnings("unused") AutofillValue value) {
8696     }
8697 
8698     /**
8699      * Automatically fills the content of the virtual children within this view.
8700      *
8701      * <p>Views with virtual children support the Autofill Framework mainly by:
8702      * <ul>
8703      *   <li>Providing the metadata defining what the virtual children mean and how they can be
8704      *       autofilled.
8705      *   <li>Implementing the methods that autofill the virtual children.
8706      * </ul>
8707      * <p>{@link #onProvideAutofillVirtualStructure(ViewStructure, int)} is responsible for the
8708      * former, this method is responsible for the latter - see {@link #autofill(AutofillValue)} and
8709      * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} for more info about autofill.
8710      *
8711      * <p>If a child value is updated asynchronously, the next call to
8712      * {@link AutofillManager#notifyValueChanged(View, int, AutofillValue)} must happen
8713      * <b>after</b> the value was changed to the autofilled value. If not, the child will not be
8714      * considered autofilled.
8715      *
8716      * <p><b>Note:</b> To indicate that a virtual view was autofilled,
8717      * <code>?android:attr/autofilledHighlight</code> should be drawn over it until the data
8718      * changes.
8719      *
8720      * @param values map of values to be autofilled, keyed by virtual child id.
8721      *
8722      * @attr ref android.R.styleable#Theme_autofilledHighlight
8723      */
8724     public void autofill(@NonNull @SuppressWarnings("unused") SparseArray<AutofillValue> values) {
8725         if (!mContext.isAutofillCompatibilityEnabled()) {
8726             return;
8727         }
8728         final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
8729         if (provider == null) {
8730             return;
8731         }
8732         final int valueCount = values.size();
8733         for (int i = 0; i < valueCount; i++) {
8734             final AutofillValue value = values.valueAt(i);
8735             if (value.isText()) {
8736                 final int virtualId = values.keyAt(i);
8737                 final CharSequence text = value.getTextValue();
8738                 final Bundle arguments = new Bundle();
8739                 arguments.putCharSequence(
8740                         AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text);
8741                 provider.performAction(virtualId, AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
8742             }
8743         }
8744     }
8745 
8746     /**
8747      * Gets the unique, logical identifier of this view in the activity, for autofill purposes.
8748      *
8749      * <p>The autofill id is created on demand, unless it is explicitly set by
8750      * {@link #setAutofillId(AutofillId)}.
8751      *
8752      * <p>See {@link #setAutofillId(AutofillId)} for more info.
8753      *
8754      * @return The View's autofill id.
8755      */
8756     public final AutofillId getAutofillId() {
8757         if (mAutofillId == null) {
8758             // The autofill id needs to be unique, but its value doesn't matter,
8759             // so it's better to reuse the accessibility id to save space.
8760             mAutofillId = new AutofillId(getAutofillViewId());
8761         }
8762         return mAutofillId;
8763     }
8764 
8765     /**
8766      * Sets the unique, logical identifier of this view in the activity, for autofill purposes.
8767      *
8768      * <p>The autofill id is created on demand, and this method should only be called when a view is
8769      * reused after {@link #dispatchProvideAutofillStructure(ViewStructure, int)} is called, as
8770      * that method creates a snapshot of the view that is passed along to the autofill service.
8771      *
8772      * <p>This method is typically used when view subtrees are recycled to represent different
8773      * content* &mdash;in this case, the autofill id can be saved before the view content is swapped
8774      * out, and restored later when it's swapped back in. For example:
8775      *
8776      * <pre>
8777      * EditText reusableView = ...;
8778      * ViewGroup parentView = ...;
8779      * AutofillManager afm = ...;
8780      *
8781      * // Swap out the view and change its contents
8782      * AutofillId oldId = reusableView.getAutofillId();
8783      * CharSequence oldText = reusableView.getText();
8784      * parentView.removeView(reusableView);
8785      * AutofillId newId = afm.getNextAutofillId();
8786      * reusableView.setText("New I am");
8787      * reusableView.setAutofillId(newId);
8788      * parentView.addView(reusableView);
8789      *
8790      * // Later, swap the old content back in
8791      * parentView.removeView(reusableView);
8792      * reusableView.setAutofillId(oldId);
8793      * reusableView.setText(oldText);
8794      * parentView.addView(reusableView);
8795      * </pre>
8796      *
8797      * @param id an autofill ID that is unique in the {@link android.app.Activity} hosting the view,
8798      * or {@code null} to reset it. Usually it's an id previously allocated to another view (and
8799      * obtained through {@link #getAutofillId()}), or a new value obtained through
8800      * {@link AutofillManager#getNextAutofillId()}.
8801      *
8802      * @throws IllegalStateException if the view is already {@link #isAttachedToWindow() attached to
8803      * a window}.
8804      *
8805      * @throws IllegalArgumentException if the id is an autofill id associated with a virtual view.
8806      */
8807     public void setAutofillId(@Nullable AutofillId id) {
8808         // TODO(b/37566627): add unit / CTS test for all possible combinations below
8809         if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
8810             Log.v(AUTOFILL_LOG_TAG, "setAutofill(): from " + mAutofillId + " to " + id);
8811         }
8812         if (isAttachedToWindow()) {
8813             throw new IllegalStateException("Cannot set autofill id when view is attached");
8814         }
8815         if (id != null && !id.isNonVirtual()) {
8816             throw new IllegalStateException("Cannot set autofill id assigned to virtual views");
8817         }
8818         if (id == null && (mPrivateFlags3 & PFLAG3_AUTOFILLID_EXPLICITLY_SET) == 0) {
8819             // Ignore reset because it was never explicitly set before.
8820             return;
8821         }
8822         mAutofillId = id;
8823         if (id != null) {
8824             mAutofillViewId = id.getViewId();
8825             mPrivateFlags3 |= PFLAG3_AUTOFILLID_EXPLICITLY_SET;
8826         } else {
8827             mAutofillViewId = NO_ID;
8828             mPrivateFlags3 &= ~PFLAG3_AUTOFILLID_EXPLICITLY_SET;
8829         }
8830     }
8831 
8832     /**
8833      * Describes the autofill type of this view, so an
8834      * {@link android.service.autofill.AutofillService} can create the proper {@link AutofillValue}
8835      * when autofilling the view.
8836      *
8837      * <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it to properly
8838      * support the Autofill Framework.
8839      *
8840      * @return either {@link #AUTOFILL_TYPE_NONE}, {@link #AUTOFILL_TYPE_TEXT},
8841      * {@link #AUTOFILL_TYPE_LIST}, {@link #AUTOFILL_TYPE_DATE}, or {@link #AUTOFILL_TYPE_TOGGLE}.
8842      *
8843      * @see #onProvideAutofillStructure(ViewStructure, int)
8844      * @see #autofill(AutofillValue)
8845      */
8846     public @AutofillType int getAutofillType() {
8847         return AUTOFILL_TYPE_NONE;
8848     }
8849 
8850     /**
8851      * Gets the hints that help an {@link android.service.autofill.AutofillService} determine how
8852      * to autofill the view with the user's data.
8853      *
8854      * <p>See {@link #setAutofillHints(String...)} for more info about these hints.
8855      *
8856      * @return The hints set via the attribute or {@link #setAutofillHints(String...)}, or
8857      * {@code null} if no hints were set.
8858      *
8859      * @attr ref android.R.styleable#View_autofillHints
8860      */
8861     @ViewDebug.ExportedProperty()
8862     @InspectableProperty
8863     @Nullable public String[] getAutofillHints() {
8864         return mAutofillHints;
8865     }
8866 
8867     /**
8868      * @hide
8869      */
8870     @TestApi
8871     public boolean isAutofilled() {
8872         return (mPrivateFlags3 & PFLAG3_IS_AUTOFILLED) != 0;
8873     }
8874 
8875     /**
8876      * Gets the {@link View}'s current autofill value.
8877      *
8878      * <p>By default returns {@code null}, but subclasses should override it and return an
8879      * appropriate value to properly support the Autofill Framework.
8880      *
8881      * @see #onProvideAutofillStructure(ViewStructure, int)
8882      * @see #autofill(AutofillValue)
8883      */
8884     @Nullable
8885     public AutofillValue getAutofillValue() {
8886         return null;
8887     }
8888 
8889     /**
8890      * Gets the mode for determining whether this view is important for autofill.
8891      *
8892      * <p>See {@link #setImportantForAutofill(int)} and {@link #isImportantForAutofill()} for more
8893      * info about this mode.
8894      *
8895      * @return {@link #IMPORTANT_FOR_AUTOFILL_AUTO} by default, or value passed to
8896      * {@link #setImportantForAutofill(int)}.
8897      *
8898      * @attr ref android.R.styleable#View_importantForAutofill
8899      */
8900     @ViewDebug.ExportedProperty(mapping = {
8901             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_AUTO, to = "auto"),
8902             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES, to = "yes"),
8903             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO, to = "no"),
8904             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
8905                 to = "yesExcludeDescendants"),
8906             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
8907                 to = "noExcludeDescendants")})
8908     @InspectableProperty(enumMapping = {
8909             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_AUTO, name = "auto"),
8910             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_YES, name = "yes"),
8911             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_NO, name = "no"),
8912             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
8913                     name = "yesExcludeDescendants"),
8914             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
8915                     name = "noExcludeDescendants"),
8916     })
8917     public @AutofillImportance int getImportantForAutofill() {
8918         return (mPrivateFlags3
8919                 & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK) >> PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
8920     }
8921 
8922     /**
8923      * Sets the mode for determining whether this view is considered important for autofill.
8924      *
8925      * <p>The platform determines the importance for autofill automatically but you
8926      * can use this method to customize the behavior. For example:
8927      *
8928      * <ol>
8929      *   <li>When the view contents is irrelevant for autofill (for example, a text field used in a
8930      *       "Captcha" challenge), it should be {@link #IMPORTANT_FOR_AUTOFILL_NO}.
8931      *   <li>When both the view and its children are irrelevant for autofill (for example, the root
8932      *       view of an activity containing a spreadhseet editor), it should be
8933      *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
8934      *   <li>When the view content is relevant for autofill but its children aren't (for example,
8935      *       a credit card expiration date represented by a custom view that overrides the proper
8936      *       autofill methods and has 2 children representing the month and year), it should
8937      *       be {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}.
8938      * </ol>
8939      *
8940      * <p><b>Note:</b> Setting the mode as {@link #IMPORTANT_FOR_AUTOFILL_NO} or
8941      * {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS} does not guarantee the view (and its
8942      * children) will be always be considered not important; for example, when the user explicitly
8943      * makes an autofill request, all views are considered important. See
8944      * {@link #isImportantForAutofill()} for more details about how the View's importance for
8945      * autofill is used.
8946      *
8947      * @param mode {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, {@link #IMPORTANT_FOR_AUTOFILL_YES},
8948      * {@link #IMPORTANT_FOR_AUTOFILL_NO}, {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS},
8949      * or {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
8950      *
8951      * @attr ref android.R.styleable#View_importantForAutofill
8952      */
8953     public void setImportantForAutofill(@AutofillImportance int mode) {
8954         mPrivateFlags3 &= ~PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
8955         mPrivateFlags3 |= (mode << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT)
8956                 & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
8957     }
8958 
8959     /**
8960      * Hints the Android System whether the {@link android.app.assist.AssistStructure.ViewNode}
8961      * associated with this view is considered important for autofill purposes.
8962      *
8963      * <p>Generally speaking, a view is important for autofill if:
8964      * <ol>
8965      * <li>The view can be autofilled by an {@link android.service.autofill.AutofillService}.
8966      * <li>The view contents can help an {@link android.service.autofill.AutofillService}
8967      *     determine how other views can be autofilled.
8968      * <ol>
8969      *
8970      * <p>For example, view containers should typically return {@code false} for performance reasons
8971      * (since the important info is provided by their children), but if its properties have relevant
8972      * information (for example, a resource id called {@code credentials}, it should return
8973      * {@code true}. On the other hand, views representing labels or editable fields should
8974      * typically return {@code true}, but in some cases they could return {@code false}
8975      * (for example, if they're part of a "Captcha" mechanism).
8976      *
8977      * <p>The value returned by this method depends on the value returned by
8978      * {@link #getImportantForAutofill()}:
8979      *
8980      * <ol>
8981      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_YES} or
8982      *       {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}, then it returns {@code true}
8983      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_NO} or
8984      *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}, then it returns {@code false}
8985      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, then it uses some simple heuristics
8986      *       that can return {@code true} in some cases (like a container with a resource id),
8987      *       but {@code false} in most.
8988      *   <li>otherwise, it returns {@code false}.
8989      * </ol>
8990      *
8991      * <p>When a view is considered important for autofill:
8992      * <ul>
8993      *   <li>The view might automatically trigger an autofill request when focused on.
8994      *   <li>The contents of the view are included in the {@link ViewStructure} used in an autofill
8995      *       request.
8996      * </ul>
8997      *
8998      * <p>On the other hand, when a view is considered not important for autofill:
8999      * <ul>
9000      *   <li>The view never automatically triggers autofill requests, but it can trigger a manual
9001      *       request through {@link AutofillManager#requestAutofill(View)}.
9002      *   <li>The contents of the view are not included in the {@link ViewStructure} used in an
9003      *       autofill request, unless the request has the
9004      *       {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag.
9005      * </ul>
9006      *
9007      * @return whether the view is considered important for autofill.
9008      *
9009      * @see #setImportantForAutofill(int)
9010      * @see #IMPORTANT_FOR_AUTOFILL_AUTO
9011      * @see #IMPORTANT_FOR_AUTOFILL_YES
9012      * @see #IMPORTANT_FOR_AUTOFILL_NO
9013      * @see #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
9014      * @see #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
9015      * @see AutofillManager#requestAutofill(View)
9016      */
9017     public final boolean isImportantForAutofill() {
9018         // Check parent mode to ensure we're not hidden.
9019         ViewParent parent = mParent;
9020         while (parent instanceof View) {
9021             final int parentImportance = ((View) parent).getImportantForAutofill();
9022             if (parentImportance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
9023                     || parentImportance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS) {
9024                 if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
9025                     Log.v(AUTOFILL_LOG_TAG, "View (" +  this + ") is not important for autofill "
9026                             + "because parent " + parent + "'s importance is " + parentImportance);
9027                 }
9028                 return false;
9029             }
9030             parent = parent.getParent();
9031         }
9032 
9033         final int importance = getImportantForAutofill();
9034 
9035         // First, check the explicit states.
9036         if (importance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
9037                 || importance == IMPORTANT_FOR_AUTOFILL_YES) {
9038             return true;
9039         }
9040         if (importance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
9041                 || importance == IMPORTANT_FOR_AUTOFILL_NO) {
9042             if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
9043                 Log.v(AUTOFILL_LOG_TAG, "View (" +  this + ") is not important for autofill "
9044                         + "because its importance is " + importance);
9045             }
9046             return false;
9047         }
9048 
9049         // Then use some heuristics to handle AUTO.
9050         if (importance != IMPORTANT_FOR_AUTOFILL_AUTO) {
9051             Log.w(AUTOFILL_LOG_TAG, "invalid autofill importance (" + importance + " on view "
9052                     + this);
9053             return false;
9054         }
9055 
9056         // Always include views that have an explicit resource id.
9057         final int id = mID;
9058         if (id != NO_ID && !isViewIdGenerated(id)) {
9059             final Resources res = getResources();
9060             String entry = null;
9061             String pkg = null;
9062             try {
9063                 entry = res.getResourceEntryName(id);
9064                 pkg = res.getResourcePackageName(id);
9065             } catch (Resources.NotFoundException e) {
9066                 // ignore
9067             }
9068             if (entry != null && pkg != null && pkg.equals(mContext.getPackageName())) {
9069                 return true;
9070             }
9071         }
9072 
9073         // If the app developer explicitly set hints for it, it's important.
9074         if (getAutofillHints() != null) {
9075             return true;
9076         }
9077 
9078         // Otherwise, assume it's not important...
9079         return false;
9080     }
9081 
9082     /**
9083      * Sets the (optional) {@link ContentCaptureSession} associated with this view.
9084      *
9085      * <p>This method should be called when you need to associate a {@link ContentCaptureContext} to
9086      * the content capture events associated with this view or its view hierarchy (if it's a
9087      * {@link ViewGroup}).
9088      *
9089      * <p>For example, if your activity is associated with a web domain, first you would need to
9090      * set the context for the main DOM:
9091      *
9092      * <pre>
9093      *   ContentCaptureSession mainSession = rootView.getContentCaptureSession();
9094      *   mainSession.setContentCaptureContext(ContentCaptureContext.forLocusId(Uri.parse(myUrl));
9095      * </pre>
9096      *
9097      * <p>Then if the page had an {@code IFRAME}, you would create a new session for it:
9098      *
9099      * <pre>
9100      *   ContentCaptureSession iframeSession = mainSession.createContentCaptureSession(
9101      *       ContentCaptureContext.forLocusId(Uri.parse(iframeUrl)));
9102      *   iframeView.setContentCaptureSession(iframeSession);
9103      * </pre>
9104      *
9105      * @param contentCaptureSession a session created by
9106      * {@link ContentCaptureSession#createContentCaptureSession(
9107      *        android.view.contentcapture.ContentCaptureContext)}.
9108      */
9109     public void setContentCaptureSession(@Nullable ContentCaptureSession contentCaptureSession) {
9110         mContentCaptureSession = contentCaptureSession;
9111     }
9112 
9113     /**
9114      * Gets the session used to notify content capture events.
9115      *
9116      * @return session explicitly set by {@link #setContentCaptureSession(ContentCaptureSession)},
9117      * inherited by ancestors, default session or {@code null} if content capture is disabled for
9118      * this view.
9119      */
9120     @Nullable
9121     public final ContentCaptureSession getContentCaptureSession() {
9122         if (mCachedContentCaptureSession != null) {
9123             return mCachedContentCaptureSession;
9124         }
9125 
9126         mCachedContentCaptureSession = getAndCacheContentCaptureSession();
9127         return mCachedContentCaptureSession;
9128     }
9129 
9130     @Nullable
9131     private ContentCaptureSession getAndCacheContentCaptureSession() {
9132         // First try the session explicitly set by setContentCaptureSession()
9133         if (mContentCaptureSession != null) return mContentCaptureSession;
9134 
9135         // Then the session explicitly set in an ancestor
9136         ContentCaptureSession session = null;
9137         if (mParent instanceof View) {
9138             session = ((View) mParent).getContentCaptureSession();
9139         }
9140 
9141         // Finally, if no session was explicitly set, use the context's default session.
9142         if (session == null) {
9143             final ContentCaptureManager ccm = mContext
9144                     .getSystemService(ContentCaptureManager.class);
9145             return ccm == null ? null : ccm.getMainContentCaptureSession();
9146         }
9147         return session;
9148     }
9149 
9150     @Nullable
9151     private AutofillManager getAutofillManager() {
9152         return mContext.getSystemService(AutofillManager.class);
9153     }
9154 
9155     private boolean isAutofillable() {
9156         if (getAutofillType() == AUTOFILL_TYPE_NONE) return false;
9157 
9158         if (!isImportantForAutofill()) {
9159             // View is not important for "regular" autofill, so we must check if Augmented Autofill
9160             // is enabled for the activity
9161             final AutofillOptions options = mContext.getAutofillOptions();
9162             if (options == null || !options.isAugmentedAutofillEnabled(mContext)) {
9163                 return false;
9164             }
9165             final AutofillManager afm = getAutofillManager();
9166             if (afm == null) return false;
9167             afm.notifyViewEnteredForAugmentedAutofill(this);
9168         }
9169 
9170         return getAutofillViewId() > LAST_APP_AUTOFILL_ID;
9171     }
9172 
9173     /** @hide */
9174     public boolean canNotifyAutofillEnterExitEvent() {
9175         return isAutofillable() && isAttachedToWindow();
9176     }
9177 
9178     private void populateVirtualStructure(ViewStructure structure,
9179             AccessibilityNodeProvider provider, AccessibilityNodeInfo info,
9180             boolean forAutofill) {
9181         structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
9182                 null, null, info.getViewIdResourceName());
9183         Rect rect = structure.getTempRect();
9184         info.getBoundsInParent(rect);
9185         structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
9186         structure.setVisibility(VISIBLE);
9187         structure.setEnabled(info.isEnabled());
9188         if (info.isClickable()) {
9189             structure.setClickable(true);
9190         }
9191         if (info.isFocusable()) {
9192             structure.setFocusable(true);
9193         }
9194         if (info.isFocused()) {
9195             structure.setFocused(true);
9196         }
9197         if (info.isAccessibilityFocused()) {
9198             structure.setAccessibilityFocused(true);
9199         }
9200         if (info.isSelected()) {
9201             structure.setSelected(true);
9202         }
9203         if (info.isLongClickable()) {
9204             structure.setLongClickable(true);
9205         }
9206         if (info.isCheckable()) {
9207             structure.setCheckable(true);
9208             if (info.isChecked()) {
9209                 structure.setChecked(true);
9210             }
9211         }
9212         if (info.isContextClickable()) {
9213             structure.setContextClickable(true);
9214         }
9215         if (forAutofill) {
9216             structure.setAutofillId(new AutofillId(getAutofillId(),
9217                     AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId())));
9218         }
9219         CharSequence cname = info.getClassName();
9220         structure.setClassName(cname != null ? cname.toString() : null);
9221         structure.setContentDescription(info.getContentDescription());
9222         if (forAutofill) {
9223             final int maxTextLength = info.getMaxTextLength();
9224             if (maxTextLength != -1) {
9225                 structure.setMaxTextLength(maxTextLength);
9226             }
9227             structure.setHint(info.getHintText());
9228         }
9229         CharSequence text = info.getText();
9230         boolean hasText = text != null || info.getError() != null;
9231         if (hasText) {
9232             structure.setText(text, info.getTextSelectionStart(), info.getTextSelectionEnd());
9233         }
9234         if (forAutofill) {
9235             if (info.isEditable()) {
9236                 structure.setDataIsSensitive(true);
9237                 if (hasText) {
9238                     structure.setAutofillType(AUTOFILL_TYPE_TEXT);
9239                     structure.setAutofillValue(AutofillValue.forText(text));
9240                 }
9241                 int inputType = info.getInputType();
9242                 if (inputType == 0 && info.isPassword()) {
9243                     inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD;
9244                 }
9245                 structure.setInputType(inputType);
9246             } else {
9247                 structure.setDataIsSensitive(false);
9248             }
9249         }
9250         final int NCHILDREN = info.getChildCount();
9251         if (NCHILDREN > 0) {
9252             structure.setChildCount(NCHILDREN);
9253             for (int i=0; i<NCHILDREN; i++) {
9254                 if (AccessibilityNodeInfo.getVirtualDescendantId(info.getChildNodeIds().get(i))
9255                         == AccessibilityNodeProvider.HOST_VIEW_ID) {
9256                     Log.e(VIEW_LOG_TAG, "Virtual view pointing to its host. Ignoring");
9257                     continue;
9258                 }
9259                 AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
9260                         AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
9261                 ViewStructure child = structure.newChild(i);
9262                 populateVirtualStructure(child, provider, cinfo, forAutofill);
9263                 cinfo.recycle();
9264             }
9265         }
9266     }
9267 
9268     /**
9269      * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
9270      * implementation calls {@link #onProvideStructure} and
9271      * {@link #onProvideVirtualStructure}.
9272      */
9273     public void dispatchProvideStructure(ViewStructure structure) {
9274         dispatchProvideStructure(structure, VIEW_STRUCTURE_FOR_ASSIST, /* flags= */ 0);
9275     }
9276 
9277     /**
9278      * Dispatches creation of a {@link ViewStructure}s for autofill purposes down the hierarchy,
9279      * when an Assist structure is being created as part of an autofill request.
9280      *
9281      * <p>The default implementation does the following:
9282      * <ul>
9283      *   <li>Sets the {@link AutofillId} in the structure.
9284      *   <li>Calls {@link #onProvideAutofillStructure(ViewStructure, int)}.
9285      *   <li>Calls {@link #onProvideAutofillVirtualStructure(ViewStructure, int)}.
9286      * </ul>
9287      *
9288      * <p>Typically, this method should only be overridden by subclasses that provide a view
9289      * hierarchy (such as {@link ViewGroup}) - other classes should override
9290      * {@link #onProvideAutofillStructure(ViewStructure, int)} or
9291      * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} instead.
9292      *
9293      * <p>When overridden, it must:
9294      *
9295      * <ul>
9296      *   <li>Either call
9297      *       {@code super.dispatchProvideAutofillStructure(structure, flags)} or explicitly
9298      *       set the {@link AutofillId} in the structure (for example, by calling
9299      *       {@code structure.setAutofillId(getAutofillId())}).
9300      *   <li>Decide how to handle the {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag - when
9301      *       set, all views in the structure should be considered important for autofill,
9302      *       regardless of what {@link #isImportantForAutofill()} returns. We encourage you to
9303      *       respect this flag to provide a better user experience - this flag is typically used
9304      *       when an user explicitly requested autofill. If the flag is not set,
9305      *       then only views marked as important for autofill should be included in the
9306      *       structure - skipping non-important views optimizes the overall autofill performance.
9307      * </ul>
9308      *
9309      * @param structure fill in with structured view data for autofill purposes.
9310      * @param flags optional flags.
9311      *
9312      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
9313      */
9314     public void dispatchProvideAutofillStructure(@NonNull ViewStructure structure,
9315             @AutofillFlags int flags) {
9316         dispatchProvideStructure(structure, VIEW_STRUCTURE_FOR_AUTOFILL, flags);
9317     }
9318 
9319     private void dispatchProvideStructure(@NonNull ViewStructure structure,
9320             @ViewStructureType int viewFor, @AutofillFlags int flags) {
9321         if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
9322             structure.setAutofillId(getAutofillId());
9323             onProvideAutofillStructure(structure, flags);
9324             onProvideAutofillVirtualStructure(structure, flags);
9325         } else if (!isAssistBlocked()) {
9326             onProvideStructure(structure);
9327             onProvideVirtualStructure(structure);
9328         } else {
9329             structure.setClassName(getAccessibilityClassName().toString());
9330             structure.setAssistBlocked(true);
9331         }
9332     }
9333 
9334     /**
9335      * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
9336      *
9337      * Note: Called from the default {@link AccessibilityDelegate}.
9338      *
9339      * @hide
9340      */
9341     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
9342         if (mAttachInfo == null) {
9343             return;
9344         }
9345 
9346         Rect bounds = mAttachInfo.mTmpInvalRect;
9347 
9348         getDrawingRect(bounds);
9349         info.setBoundsInParent(bounds);
9350 
9351         getBoundsOnScreen(bounds, true);
9352         info.setBoundsInScreen(bounds);
9353 
9354         ViewParent parent = getParentForAccessibility();
9355         if (parent instanceof View) {
9356             info.setParent((View) parent);
9357         }
9358 
9359         if (mID != View.NO_ID) {
9360             View rootView = getRootView();
9361             if (rootView == null) {
9362                 rootView = this;
9363             }
9364 
9365             View label = rootView.findLabelForView(this, mID);
9366             if (label != null) {
9367                 info.setLabeledBy(label);
9368             }
9369 
9370             if ((mAttachInfo.mAccessibilityFetchFlags
9371                     & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
9372                     && Resources.resourceHasPackage(mID)) {
9373                 try {
9374                     String viewId = getResources().getResourceName(mID);
9375                     info.setViewIdResourceName(viewId);
9376                 } catch (Resources.NotFoundException nfe) {
9377                     /* ignore */
9378                 }
9379             }
9380         }
9381 
9382         if (mLabelForId != View.NO_ID) {
9383             View rootView = getRootView();
9384             if (rootView == null) {
9385                 rootView = this;
9386             }
9387             View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
9388             if (labeled != null) {
9389                 info.setLabelFor(labeled);
9390             }
9391         }
9392 
9393         if (mAccessibilityTraversalBeforeId != View.NO_ID) {
9394             View rootView = getRootView();
9395             if (rootView == null) {
9396                 rootView = this;
9397             }
9398             View next = rootView.findViewInsideOutShouldExist(this,
9399                     mAccessibilityTraversalBeforeId);
9400             if (next != null && next.includeForAccessibility()) {
9401                 info.setTraversalBefore(next);
9402             }
9403         }
9404 
9405         if (mAccessibilityTraversalAfterId != View.NO_ID) {
9406             View rootView = getRootView();
9407             if (rootView == null) {
9408                 rootView = this;
9409             }
9410             View next = rootView.findViewInsideOutShouldExist(this,
9411                     mAccessibilityTraversalAfterId);
9412             if (next != null && next.includeForAccessibility()) {
9413                 info.setTraversalAfter(next);
9414             }
9415         }
9416 
9417         info.setVisibleToUser(isVisibleToUser());
9418 
9419         info.setImportantForAccessibility(isImportantForAccessibility());
9420         info.setPackageName(mContext.getPackageName());
9421         info.setClassName(getAccessibilityClassName());
9422         info.setContentDescription(getContentDescription());
9423 
9424         info.setEnabled(isEnabled());
9425         info.setClickable(isClickable());
9426         info.setFocusable(isFocusable());
9427         info.setScreenReaderFocusable(isScreenReaderFocusable());
9428         info.setFocused(isFocused());
9429         info.setAccessibilityFocused(isAccessibilityFocused());
9430         info.setSelected(isSelected());
9431         info.setLongClickable(isLongClickable());
9432         info.setContextClickable(isContextClickable());
9433         info.setLiveRegion(getAccessibilityLiveRegion());
9434         if ((mTooltipInfo != null) && (mTooltipInfo.mTooltipText != null)) {
9435             info.setTooltipText(mTooltipInfo.mTooltipText);
9436             info.addAction((mTooltipInfo.mTooltipPopup == null)
9437                     ? AccessibilityNodeInfo.AccessibilityAction.ACTION_SHOW_TOOLTIP
9438                     : AccessibilityNodeInfo.AccessibilityAction.ACTION_HIDE_TOOLTIP);
9439         }
9440 
9441         // TODO: These make sense only if we are in an AdapterView but all
9442         // views can be selected. Maybe from accessibility perspective
9443         // we should report as selectable view in an AdapterView.
9444         info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
9445         info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
9446 
9447         if (isFocusable()) {
9448             if (isFocused()) {
9449                 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
9450             } else {
9451                 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
9452             }
9453         }
9454 
9455         if (!isAccessibilityFocused()) {
9456             info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
9457         } else {
9458             info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
9459         }
9460 
9461         if (isClickable() && isEnabled()) {
9462             info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
9463         }
9464 
9465         if (isLongClickable() && isEnabled()) {
9466             info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
9467         }
9468 
9469         if (isContextClickable() && isEnabled()) {
9470             info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
9471         }
9472 
9473         CharSequence text = getIterableTextForAccessibility();
9474         if (text != null && text.length() > 0) {
9475             info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
9476 
9477             info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
9478             info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
9479             info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
9480             info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
9481                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
9482                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
9483         }
9484 
9485         info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
9486         populateAccessibilityNodeInfoDrawingOrderInParent(info);
9487         info.setPaneTitle(mAccessibilityPaneTitle);
9488         info.setHeading(isAccessibilityHeading());
9489 
9490         if (mTouchDelegate != null) {
9491             info.setTouchDelegateInfo(mTouchDelegate.getTouchDelegateInfo());
9492         }
9493     }
9494 
9495     /**
9496      * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
9497      * additional data.
9498      * <p>
9499      * This method only needs overloading if the node is marked as having extra data available.
9500      * </p>
9501      *
9502      * @param info The info to which to add the extra data. Never {@code null}.
9503      * @param extraDataKey A key specifying the type of extra data to add to the info. The
9504      *                     extra data should be added to the {@link Bundle} returned by
9505      *                     the info's {@link AccessibilityNodeInfo#getExtras} method. Never
9506      *                     {@code null}.
9507      * @param arguments A {@link Bundle} holding any arguments relevant for this request. May be
9508      *                  {@code null} if the service provided no arguments.
9509      *
9510      * @see AccessibilityNodeInfo#setAvailableExtraData(List)
9511      */
9512     public void addExtraDataToAccessibilityNodeInfo(
9513             @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
9514             @Nullable Bundle arguments) {
9515     }
9516 
9517     /**
9518      * Determine the order in which this view will be drawn relative to its siblings for a11y
9519      *
9520      * @param info The info whose drawing order should be populated
9521      */
9522     private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
9523         /*
9524          * If the view's bounds haven't been set yet, layout has not completed. In that situation,
9525          * drawing order may not be well-defined, and some Views with custom drawing order may
9526          * not be initialized sufficiently to respond properly getChildDrawingOrder.
9527          */
9528         if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
9529             info.setDrawingOrder(0);
9530             return;
9531         }
9532         int drawingOrderInParent = 1;
9533         // Iterate up the hierarchy if parents are not important for a11y
9534         View viewAtDrawingLevel = this;
9535         final ViewParent parent = getParentForAccessibility();
9536         while (viewAtDrawingLevel != parent) {
9537             final ViewParent currentParent = viewAtDrawingLevel.getParent();
9538             if (!(currentParent instanceof ViewGroup)) {
9539                 // Should only happen for the Decor
9540                 drawingOrderInParent = 0;
9541                 break;
9542             } else {
9543                 final ViewGroup parentGroup = (ViewGroup) currentParent;
9544                 final int childCount = parentGroup.getChildCount();
9545                 if (childCount > 1) {
9546                     List<View> preorderedList = parentGroup.buildOrderedChildList();
9547                     if (preorderedList != null) {
9548                         final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
9549                         for (int i = 0; i < childDrawIndex; i++) {
9550                             drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
9551                         }
9552                     } else {
9553                         final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
9554                         final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
9555                         final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
9556                                 .getChildDrawingOrder(childCount, childIndex) : childIndex;
9557                         final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
9558                         if (childDrawIndex != 0) {
9559                             for (int i = 0; i < numChildrenToIterate; i++) {
9560                                 final int otherDrawIndex = (customOrder ?
9561                                         parentGroup.getChildDrawingOrder(childCount, i) : i);
9562                                 if (otherDrawIndex < childDrawIndex) {
9563                                     drawingOrderInParent +=
9564                                             numViewsForAccessibility(parentGroup.getChildAt(i));
9565                                 }
9566                             }
9567                         }
9568                     }
9569                 }
9570             }
9571             viewAtDrawingLevel = (View) currentParent;
9572         }
9573         info.setDrawingOrder(drawingOrderInParent);
9574     }
9575 
9576     private static int numViewsForAccessibility(View view) {
9577         if (view != null) {
9578             if (view.includeForAccessibility()) {
9579                 return 1;
9580             } else if (view instanceof ViewGroup) {
9581                 return ((ViewGroup) view).getNumChildrenForAccessibility();
9582             }
9583         }
9584         return 0;
9585     }
9586 
9587     private View findLabelForView(View view, int labeledId) {
9588         if (mMatchLabelForPredicate == null) {
9589             mMatchLabelForPredicate = new MatchLabelForPredicate();
9590         }
9591         mMatchLabelForPredicate.mLabeledId = labeledId;
9592         return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
9593     }
9594 
9595     /**
9596      * Computes whether this virtual autofill view is visible to the user.
9597      *
9598      * <p><b>Note: </b>By default it returns {@code true}, but views providing a virtual hierarchy
9599      * view must override it.
9600      *
9601      * @return Whether the view is visible on the screen.
9602      */
9603     public boolean isVisibleToUserForAutofill(int virtualId) {
9604         if (mContext.isAutofillCompatibilityEnabled()) {
9605             final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
9606             if (provider != null) {
9607                 final AccessibilityNodeInfo node = provider.createAccessibilityNodeInfo(virtualId);
9608                 if (node != null) {
9609                     return node.isVisibleToUser();
9610                 }
9611                 // if node is null, assume it's not visible anymore
9612             } else {
9613                 Log.w(VIEW_LOG_TAG, "isVisibleToUserForAutofill(" + virtualId + "): no provider");
9614             }
9615             return false;
9616         }
9617         return true;
9618     }
9619 
9620     /**
9621      * Computes whether this view is visible to the user. Such a view is
9622      * attached, visible, all its predecessors are visible, it is not clipped
9623      * entirely by its predecessors, and has an alpha greater than zero.
9624      *
9625      * @return Whether the view is visible on the screen.
9626      *
9627      * @hide
9628      */
9629     @UnsupportedAppUsage
9630     public boolean isVisibleToUser() {
9631         return isVisibleToUser(null);
9632     }
9633 
9634     /**
9635      * Computes whether the given portion of this view is visible to the user.
9636      * Such a view is attached, visible, all its predecessors are visible,
9637      * has an alpha greater than zero, and the specified portion is not
9638      * clipped entirely by its predecessors.
9639      *
9640      * @param boundInView the portion of the view to test; coordinates should be relative; may be
9641      *                    <code>null</code>, and the entire view will be tested in this case.
9642      *                    When <code>true</code> is returned by the function, the actual visible
9643      *                    region will be stored in this parameter; that is, if boundInView is fully
9644      *                    contained within the view, no modification will be made, otherwise regions
9645      *                    outside of the visible area of the view will be clipped.
9646      *
9647      * @return Whether the specified portion of the view is visible on the screen.
9648      *
9649      * @hide
9650      */
9651     @UnsupportedAppUsage
9652     protected boolean isVisibleToUser(Rect boundInView) {
9653         if (mAttachInfo != null) {
9654             // Attached to invisible window means this view is not visible.
9655             if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
9656                 return false;
9657             }
9658             // An invisible predecessor or one with alpha zero means
9659             // that this view is not visible to the user.
9660             Object current = this;
9661             while (current instanceof View) {
9662                 View view = (View) current;
9663                 // We have attach info so this view is attached and there is no
9664                 // need to check whether we reach to ViewRootImpl on the way up.
9665                 if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
9666                         view.getVisibility() != VISIBLE) {
9667                     return false;
9668                 }
9669                 current = view.mParent;
9670             }
9671             // Check if the view is entirely covered by its predecessors.
9672             Rect visibleRect = mAttachInfo.mTmpInvalRect;
9673             Point offset = mAttachInfo.mPoint;
9674             if (!getGlobalVisibleRect(visibleRect, offset)) {
9675                 return false;
9676             }
9677             // Check if the visible portion intersects the rectangle of interest.
9678             if (boundInView != null) {
9679                 visibleRect.offset(-offset.x, -offset.y);
9680                 return boundInView.intersect(visibleRect);
9681             }
9682             return true;
9683         }
9684         return false;
9685     }
9686 
9687     /**
9688      * Returns the delegate for implementing accessibility support via
9689      * composition. For more details see {@link AccessibilityDelegate}.
9690      *
9691      * @return The delegate, or null if none set.
9692      */
9693     public AccessibilityDelegate getAccessibilityDelegate() {
9694         return mAccessibilityDelegate;
9695     }
9696 
9697     /**
9698      * Sets a delegate for implementing accessibility support via composition
9699      * (as opposed to inheritance). For more details, see
9700      * {@link AccessibilityDelegate}.
9701      * <p>
9702      * <strong>Note:</strong> On platform versions prior to
9703      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
9704      * views in the {@code android.widget.*} package are called <i>before</i>
9705      * host methods. This prevents certain properties such as class name from
9706      * being modified by overriding
9707      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
9708      * as any changes will be overwritten by the host class.
9709      * <p>
9710      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
9711      * methods are called <i>after</i> host methods, which all properties to be
9712      * modified without being overwritten by the host class.
9713      *
9714      * @param delegate the object to which accessibility method calls should be
9715      *                 delegated
9716      * @see AccessibilityDelegate
9717      */
9718     public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
9719         mAccessibilityDelegate = delegate;
9720     }
9721 
9722     /**
9723      * Gets the provider for managing a virtual view hierarchy rooted at this View
9724      * and reported to {@link android.accessibilityservice.AccessibilityService}s
9725      * that explore the window content.
9726      * <p>
9727      * If this method returns an instance, this instance is responsible for managing
9728      * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
9729      * View including the one representing the View itself. Similarly the returned
9730      * instance is responsible for performing accessibility actions on any virtual
9731      * view or the root view itself.
9732      * </p>
9733      * <p>
9734      * If an {@link AccessibilityDelegate} has been specified via calling
9735      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
9736      * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
9737      * is responsible for handling this call.
9738      * </p>
9739      *
9740      * @return The provider.
9741      *
9742      * @see AccessibilityNodeProvider
9743      */
9744     public AccessibilityNodeProvider getAccessibilityNodeProvider() {
9745         if (mAccessibilityDelegate != null) {
9746             return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
9747         } else {
9748             return null;
9749         }
9750     }
9751 
9752     /**
9753      * Gets the unique identifier of this view on the screen for accessibility purposes.
9754      *
9755      * @return The view accessibility id.
9756      *
9757      * @hide
9758      */
9759     @UnsupportedAppUsage
9760     public int getAccessibilityViewId() {
9761         if (mAccessibilityViewId == NO_ID) {
9762             mAccessibilityViewId = sNextAccessibilityViewId++;
9763         }
9764         return mAccessibilityViewId;
9765     }
9766 
9767     /**
9768      * Gets the unique identifier of this view on the screen for autofill purposes.
9769      *
9770      * @return The view autofill id.
9771      *
9772      * @hide
9773      */
9774     public int getAutofillViewId() {
9775         if (mAutofillViewId == NO_ID) {
9776             mAutofillViewId = mContext.getNextAutofillId();
9777         }
9778         return mAutofillViewId;
9779     }
9780 
9781     /**
9782      * Gets the unique identifier of the window in which this View reseides.
9783      *
9784      * @return The window accessibility id.
9785      *
9786      * @hide
9787      */
9788     public int getAccessibilityWindowId() {
9789         return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
9790                 : AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
9791     }
9792 
9793     /**
9794      * Returns the {@link View}'s content description.
9795      * <p>
9796      * <strong>Note:</strong> Do not override this method, as it will have no
9797      * effect on the content description presented to accessibility services.
9798      * You must call {@link #setContentDescription(CharSequence)} to modify the
9799      * content description.
9800      *
9801      * @return the content description
9802      * @see #setContentDescription(CharSequence)
9803      * @attr ref android.R.styleable#View_contentDescription
9804      */
9805     @ViewDebug.ExportedProperty(category = "accessibility")
9806     @InspectableProperty
9807     public CharSequence getContentDescription() {
9808         return mContentDescription;
9809     }
9810 
9811     /**
9812      * Sets the {@link View}'s content description.
9813      * <p>
9814      * A content description briefly describes the view and is primarily used
9815      * for accessibility support to determine how a view should be presented to
9816      * the user. In the case of a view with no textual representation, such as
9817      * {@link android.widget.ImageButton}, a useful content description
9818      * explains what the view does. For example, an image button with a phone
9819      * icon that is used to place a call may use "Call" as its content
9820      * description. An image of a floppy disk that is used to save a file may
9821      * use "Save".
9822      *
9823      * @param contentDescription The content description.
9824      * @see #getContentDescription()
9825      * @attr ref android.R.styleable#View_contentDescription
9826      */
9827     @RemotableViewMethod
9828     public void setContentDescription(CharSequence contentDescription) {
9829         if (mContentDescription == null) {
9830             if (contentDescription == null) {
9831                 return;
9832             }
9833         } else if (mContentDescription.equals(contentDescription)) {
9834             return;
9835         }
9836         mContentDescription = contentDescription;
9837         final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
9838         if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
9839             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
9840             notifySubtreeAccessibilityStateChangedIfNeeded();
9841         } else {
9842             notifyViewAccessibilityStateChangedIfNeeded(
9843                     AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
9844         }
9845     }
9846 
9847     /**
9848      * Sets the id of a view before which this one is visited in accessibility traversal.
9849      * A screen-reader must visit the content of this view before the content of the one
9850      * it precedes. For example, if view B is set to be before view A, then a screen-reader
9851      * will traverse the entire content of B before traversing the entire content of A,
9852      * regardles of what traversal strategy it is using.
9853      * <p>
9854      * Views that do not have specified before/after relationships are traversed in order
9855      * determined by the screen-reader.
9856      * </p>
9857      * <p>
9858      * Setting that this view is before a view that is not important for accessibility
9859      * or if this view is not important for accessibility will have no effect as the
9860      * screen-reader is not aware of unimportant views.
9861      * </p>
9862      *
9863      * @param beforeId The id of a view this one precedes in accessibility traversal.
9864      *
9865      * @attr ref android.R.styleable#View_accessibilityTraversalBefore
9866      *
9867      * @see #setImportantForAccessibility(int)
9868      */
9869     @RemotableViewMethod
9870     public void setAccessibilityTraversalBefore(@IdRes int beforeId) {
9871         if (mAccessibilityTraversalBeforeId == beforeId) {
9872             return;
9873         }
9874         mAccessibilityTraversalBeforeId = beforeId;
9875         notifyViewAccessibilityStateChangedIfNeeded(
9876                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9877     }
9878 
9879     /**
9880      * Gets the id of a view before which this one is visited in accessibility traversal.
9881      *
9882      * @return The id of a view this one precedes in accessibility traversal if
9883      *         specified, otherwise {@link #NO_ID}.
9884      *
9885      * @see #setAccessibilityTraversalBefore(int)
9886      */
9887     @IdRes
9888     @InspectableProperty
9889     public int getAccessibilityTraversalBefore() {
9890         return mAccessibilityTraversalBeforeId;
9891     }
9892 
9893     /**
9894      * Sets the id of a view after which this one is visited in accessibility traversal.
9895      * A screen-reader must visit the content of the other view before the content of this
9896      * one. For example, if view B is set to be after view A, then a screen-reader
9897      * will traverse the entire content of A before traversing the entire content of B,
9898      * regardles of what traversal strategy it is using.
9899      * <p>
9900      * Views that do not have specified before/after relationships are traversed in order
9901      * determined by the screen-reader.
9902      * </p>
9903      * <p>
9904      * Setting that this view is after a view that is not important for accessibility
9905      * or if this view is not important for accessibility will have no effect as the
9906      * screen-reader is not aware of unimportant views.
9907      * </p>
9908      *
9909      * @param afterId The id of a view this one succedees in accessibility traversal.
9910      *
9911      * @attr ref android.R.styleable#View_accessibilityTraversalAfter
9912      *
9913      * @see #setImportantForAccessibility(int)
9914      */
9915     @RemotableViewMethod
9916     public void setAccessibilityTraversalAfter(@IdRes int afterId) {
9917         if (mAccessibilityTraversalAfterId == afterId) {
9918             return;
9919         }
9920         mAccessibilityTraversalAfterId = afterId;
9921         notifyViewAccessibilityStateChangedIfNeeded(
9922                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9923     }
9924 
9925     /**
9926      * Gets the id of a view after which this one is visited in accessibility traversal.
9927      *
9928      * @return The id of a view this one succeedes in accessibility traversal if
9929      *         specified, otherwise {@link #NO_ID}.
9930      *
9931      * @see #setAccessibilityTraversalAfter(int)
9932      */
9933     @IdRes
9934     @InspectableProperty
9935     public int getAccessibilityTraversalAfter() {
9936         return mAccessibilityTraversalAfterId;
9937     }
9938 
9939     /**
9940      * Gets the id of a view for which this view serves as a label for
9941      * accessibility purposes.
9942      *
9943      * @return The labeled view id.
9944      */
9945     @IdRes
9946     @ViewDebug.ExportedProperty(category = "accessibility")
9947     @InspectableProperty
9948     public int getLabelFor() {
9949         return mLabelForId;
9950     }
9951 
9952     /**
9953      * Sets the id of a view for which this view serves as a label for
9954      * accessibility purposes.
9955      *
9956      * @param id The labeled view id.
9957      */
9958     @RemotableViewMethod
9959     public void setLabelFor(@IdRes int id) {
9960         if (mLabelForId == id) {
9961             return;
9962         }
9963         mLabelForId = id;
9964         if (mLabelForId != View.NO_ID
9965                 && mID == View.NO_ID) {
9966             mID = generateViewId();
9967         }
9968         notifyViewAccessibilityStateChangedIfNeeded(
9969                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9970     }
9971 
9972     /**
9973      * Invoked whenever this view loses focus, either by losing window focus or by losing
9974      * focus within its window. This method can be used to clear any state tied to the
9975      * focus. For instance, if a button is held pressed with the trackball and the window
9976      * loses focus, this method can be used to cancel the press.
9977      *
9978      * Subclasses of View overriding this method should always call super.onFocusLost().
9979      *
9980      * @see #onFocusChanged(boolean, int, android.graphics.Rect)
9981      * @see #onWindowFocusChanged(boolean)
9982      *
9983      * @hide pending API council approval
9984      */
9985     @CallSuper
9986     @UnsupportedAppUsage
9987     protected void onFocusLost() {
9988         resetPressedState();
9989     }
9990 
9991     private void resetPressedState() {
9992         if ((mViewFlags & ENABLED_MASK) == DISABLED) {
9993             return;
9994         }
9995 
9996         if (isPressed()) {
9997             setPressed(false);
9998 
9999             if (!mHasPerformedLongPress) {
10000                 removeLongPressCallback();
10001             }
10002         }
10003     }
10004 
10005     /**
10006      * Returns true if this view has focus
10007      *
10008      * @return True if this view has focus, false otherwise.
10009      */
10010     @ViewDebug.ExportedProperty(category = "focus")
10011     @InspectableProperty(hasAttributeId = false)
10012     public boolean isFocused() {
10013         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
10014     }
10015 
10016     /**
10017      * Find the view in the hierarchy rooted at this view that currently has
10018      * focus.
10019      *
10020      * @return The view that currently has focus, or null if no focused view can
10021      *         be found.
10022      */
10023     public View findFocus() {
10024         return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
10025     }
10026 
10027     /**
10028      * Indicates whether this view is one of the set of scrollable containers in
10029      * its window.
10030      *
10031      * @return whether this view is one of the set of scrollable containers in
10032      * its window
10033      *
10034      * @attr ref android.R.styleable#View_isScrollContainer
10035      */
10036     @InspectableProperty(name = "isScrollContainer")
10037     public boolean isScrollContainer() {
10038         return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
10039     }
10040 
10041     /**
10042      * Change whether this view is one of the set of scrollable containers in
10043      * its window.  This will be used to determine whether the window can
10044      * resize or must pan when a soft input area is open -- scrollable
10045      * containers allow the window to use resize mode since the container
10046      * will appropriately shrink.
10047      *
10048      * @attr ref android.R.styleable#View_isScrollContainer
10049      */
10050     public void setScrollContainer(boolean isScrollContainer) {
10051         if (isScrollContainer) {
10052             if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
10053                 mAttachInfo.mScrollContainers.add(this);
10054                 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
10055             }
10056             mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
10057         } else {
10058             if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
10059                 mAttachInfo.mScrollContainers.remove(this);
10060             }
10061             mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
10062         }
10063     }
10064 
10065     /**
10066      * Returns the quality of the drawing cache.
10067      *
10068      * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
10069      *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
10070      *
10071      * @see #setDrawingCacheQuality(int)
10072      * @see #setDrawingCacheEnabled(boolean)
10073      * @see #isDrawingCacheEnabled()
10074      *
10075      * @attr ref android.R.styleable#View_drawingCacheQuality
10076      *
10077      * @deprecated The view drawing cache was largely made obsolete with the introduction of
10078      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
10079      * layers are largely unnecessary and can easily result in a net loss in performance due to the
10080      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
10081      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
10082      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
10083      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
10084      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
10085      * software-rendered usages are discouraged and have compatibility issues with hardware-only
10086      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
10087      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
10088      * reports or unit testing the {@link PixelCopy} API is recommended.
10089      */
10090     @Deprecated
10091     @DrawingCacheQuality
10092     @InspectableProperty(enumMapping = {
10093             @EnumEntry(value = DRAWING_CACHE_QUALITY_LOW, name = "low"),
10094             @EnumEntry(value = DRAWING_CACHE_QUALITY_HIGH, name = "high"),
10095             @EnumEntry(value = DRAWING_CACHE_QUALITY_AUTO, name = "auto")
10096     })
10097     public int getDrawingCacheQuality() {
10098         return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
10099     }
10100 
10101     /**
10102      * Set the drawing cache quality of this view. This value is used only when the
10103      * drawing cache is enabled
10104      *
10105      * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
10106      *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
10107      *
10108      * @see #getDrawingCacheQuality()
10109      * @see #setDrawingCacheEnabled(boolean)
10110      * @see #isDrawingCacheEnabled()
10111      *
10112      * @attr ref android.R.styleable#View_drawingCacheQuality
10113      *
10114      * @deprecated The view drawing cache was largely made obsolete with the introduction of
10115      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
10116      * layers are largely unnecessary and can easily result in a net loss in performance due to the
10117      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
10118      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
10119      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
10120      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
10121      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
10122      * software-rendered usages are discouraged and have compatibility issues with hardware-only
10123      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
10124      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
10125      * reports or unit testing the {@link PixelCopy} API is recommended.
10126      */
10127     @Deprecated
10128     public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
10129         setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
10130     }
10131 
10132     /**
10133      * Returns whether the screen should remain on, corresponding to the current
10134      * value of {@link #KEEP_SCREEN_ON}.
10135      *
10136      * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
10137      *
10138      * @see #setKeepScreenOn(boolean)
10139      *
10140      * @attr ref android.R.styleable#View_keepScreenOn
10141      */
10142     @InspectableProperty
10143     public boolean getKeepScreenOn() {
10144         return (mViewFlags & KEEP_SCREEN_ON) != 0;
10145     }
10146 
10147     /**
10148      * Controls whether the screen should remain on, modifying the
10149      * value of {@link #KEEP_SCREEN_ON}.
10150      *
10151      * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
10152      *
10153      * @see #getKeepScreenOn()
10154      *
10155      * @attr ref android.R.styleable#View_keepScreenOn
10156      */
10157     public void setKeepScreenOn(boolean keepScreenOn) {
10158         setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
10159     }
10160 
10161     /**
10162      * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
10163      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
10164      *
10165      * @attr ref android.R.styleable#View_nextFocusLeft
10166      */
10167     @IdRes
10168     @InspectableProperty(name = "nextFocusLeft")
10169     public int getNextFocusLeftId() {
10170         return mNextFocusLeftId;
10171     }
10172 
10173     /**
10174      * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
10175      * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
10176      * decide automatically.
10177      *
10178      * @attr ref android.R.styleable#View_nextFocusLeft
10179      */
10180     public void setNextFocusLeftId(@IdRes int nextFocusLeftId) {
10181         mNextFocusLeftId = nextFocusLeftId;
10182     }
10183 
10184     /**
10185      * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
10186      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
10187      *
10188      * @attr ref android.R.styleable#View_nextFocusRight
10189      */
10190     @IdRes
10191     @InspectableProperty(name = "nextFocusRight")
10192     public int getNextFocusRightId() {
10193         return mNextFocusRightId;
10194     }
10195 
10196     /**
10197      * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
10198      * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
10199      * decide automatically.
10200      *
10201      * @attr ref android.R.styleable#View_nextFocusRight
10202      */
10203     public void setNextFocusRightId(@IdRes int nextFocusRightId) {
10204         mNextFocusRightId = nextFocusRightId;
10205     }
10206 
10207     /**
10208      * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
10209      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
10210      *
10211      * @attr ref android.R.styleable#View_nextFocusUp
10212      */
10213     @IdRes
10214     @InspectableProperty(name = "nextFocusUp")
10215     public int getNextFocusUpId() {
10216         return mNextFocusUpId;
10217     }
10218 
10219     /**
10220      * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
10221      * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
10222      * decide automatically.
10223      *
10224      * @attr ref android.R.styleable#View_nextFocusUp
10225      */
10226     public void setNextFocusUpId(@IdRes int nextFocusUpId) {
10227         mNextFocusUpId = nextFocusUpId;
10228     }
10229 
10230     /**
10231      * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
10232      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
10233      *
10234      * @attr ref android.R.styleable#View_nextFocusDown
10235      */
10236     @IdRes
10237     @InspectableProperty(name = "nextFocusDown")
10238     public int getNextFocusDownId() {
10239         return mNextFocusDownId;
10240     }
10241 
10242     /**
10243      * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
10244      * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
10245      * decide automatically.
10246      *
10247      * @attr ref android.R.styleable#View_nextFocusDown
10248      */
10249     public void setNextFocusDownId(@IdRes int nextFocusDownId) {
10250         mNextFocusDownId = nextFocusDownId;
10251     }
10252 
10253     /**
10254      * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
10255      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
10256      *
10257      * @attr ref android.R.styleable#View_nextFocusForward
10258      */
10259     @IdRes
10260     @InspectableProperty(name = "nextFocusForward")
10261     public int getNextFocusForwardId() {
10262         return mNextFocusForwardId;
10263     }
10264 
10265     /**
10266      * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
10267      * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
10268      * decide automatically.
10269      *
10270      * @attr ref android.R.styleable#View_nextFocusForward
10271      */
10272     public void setNextFocusForwardId(@IdRes int nextFocusForwardId) {
10273         mNextFocusForwardId = nextFocusForwardId;
10274     }
10275 
10276     /**
10277      * Gets the id of the root of the next keyboard navigation cluster.
10278      * @return The next keyboard navigation cluster ID, or {@link #NO_ID} if the framework should
10279      * decide automatically.
10280      *
10281      * @attr ref android.R.styleable#View_nextClusterForward
10282      */
10283     @IdRes
10284     @InspectableProperty(name = "nextClusterForward")
10285     public int getNextClusterForwardId() {
10286         return mNextClusterForwardId;
10287     }
10288 
10289     /**
10290      * Sets the id of the view to use as the root of the next keyboard navigation cluster.
10291      * @param nextClusterForwardId The next cluster ID, or {@link #NO_ID} if the framework should
10292      * decide automatically.
10293      *
10294      * @attr ref android.R.styleable#View_nextClusterForward
10295      */
10296     public void setNextClusterForwardId(@IdRes int nextClusterForwardId) {
10297         mNextClusterForwardId = nextClusterForwardId;
10298     }
10299 
10300     /**
10301      * Returns the visibility of this view and all of its ancestors
10302      *
10303      * @return True if this view and all of its ancestors are {@link #VISIBLE}
10304      */
10305     public boolean isShown() {
10306         View current = this;
10307         //noinspection ConstantConditions
10308         do {
10309             if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
10310                 return false;
10311             }
10312             ViewParent parent = current.mParent;
10313             if (parent == null) {
10314                 return false; // We are not attached to the view root
10315             }
10316             if (!(parent instanceof View)) {
10317                 return true;
10318             }
10319             current = (View) parent;
10320         } while (current != null);
10321 
10322         return false;
10323     }
10324 
10325     /**
10326      * Called by the view hierarchy when the content insets for a window have
10327      * changed, to allow it to adjust its content to fit within those windows.
10328      * The content insets tell you the space that the status bar, input method,
10329      * and other system windows infringe on the application's window.
10330      *
10331      * <p>You do not normally need to deal with this function, since the default
10332      * window decoration given to applications takes care of applying it to the
10333      * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
10334      * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
10335      * and your content can be placed under those system elements.  You can then
10336      * use this method within your view hierarchy if you have parts of your UI
10337      * which you would like to ensure are not being covered.
10338      *
10339      * <p>The default implementation of this method simply applies the content
10340      * insets to the view's padding, consuming that content (modifying the
10341      * insets to be 0), and returning true.  This behavior is off by default, but can
10342      * be enabled through {@link #setFitsSystemWindows(boolean)}.
10343      *
10344      * <p>This function's traversal down the hierarchy is depth-first.  The same content
10345      * insets object is propagated down the hierarchy, so any changes made to it will
10346      * be seen by all following views (including potentially ones above in
10347      * the hierarchy since this is a depth-first traversal).  The first view
10348      * that returns true will abort the entire traversal.
10349      *
10350      * <p>The default implementation works well for a situation where it is
10351      * used with a container that covers the entire window, allowing it to
10352      * apply the appropriate insets to its content on all edges.  If you need
10353      * a more complicated layout (such as two different views fitting system
10354      * windows, one on the top of the window, and one on the bottom),
10355      * you can override the method and handle the insets however you would like.
10356      * Note that the insets provided by the framework are always relative to the
10357      * far edges of the window, not accounting for the location of the called view
10358      * within that window.  (In fact when this method is called you do not yet know
10359      * where the layout will place the view, as it is done before layout happens.)
10360      *
10361      * <p>Note: unlike many View methods, there is no dispatch phase to this
10362      * call.  If you are overriding it in a ViewGroup and want to allow the
10363      * call to continue to your children, you must be sure to call the super
10364      * implementation.
10365      *
10366      * <p>Here is a sample layout that makes use of fitting system windows
10367      * to have controls for a video view placed inside of the window decorations
10368      * that it hides and shows.  This can be used with code like the second
10369      * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
10370      *
10371      * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
10372      *
10373      * @param insets Current content insets of the window.  Prior to
10374      * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
10375      * the insets or else you and Android will be unhappy.
10376      *
10377      * @return {@code true} if this view applied the insets and it should not
10378      * continue propagating further down the hierarchy, {@code false} otherwise.
10379      * @see #getFitsSystemWindows()
10380      * @see #setFitsSystemWindows(boolean)
10381      * @see #setSystemUiVisibility(int)
10382      *
10383      * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
10384      * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
10385      * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
10386      * to implement handling their own insets.
10387      */
10388     @Deprecated
10389     protected boolean fitSystemWindows(Rect insets) {
10390         if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
10391             if (insets == null) {
10392                 // Null insets by definition have already been consumed.
10393                 // This call cannot apply insets since there are none to apply,
10394                 // so return false.
10395                 return false;
10396             }
10397             // If we're not in the process of dispatching the newer apply insets call,
10398             // that means we're not in the compatibility path. Dispatch into the newer
10399             // apply insets path and take things from there.
10400             try {
10401                 mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
10402                 return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
10403             } finally {
10404                 mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
10405             }
10406         } else {
10407             // We're being called from the newer apply insets path.
10408             // Perform the standard fallback behavior.
10409             return fitSystemWindowsInt(insets);
10410         }
10411     }
10412 
10413     private boolean fitSystemWindowsInt(Rect insets) {
10414         if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
10415             mUserPaddingStart = UNDEFINED_PADDING;
10416             mUserPaddingEnd = UNDEFINED_PADDING;
10417             Rect localInsets = sThreadLocal.get();
10418             if (localInsets == null) {
10419                 localInsets = new Rect();
10420                 sThreadLocal.set(localInsets);
10421             }
10422             boolean res = computeFitSystemWindows(insets, localInsets);
10423             mUserPaddingLeftInitial = localInsets.left;
10424             mUserPaddingRightInitial = localInsets.right;
10425             internalSetPadding(localInsets.left, localInsets.top,
10426                     localInsets.right, localInsets.bottom);
10427             return res;
10428         }
10429         return false;
10430     }
10431 
10432     /**
10433      * Called when the view should apply {@link WindowInsets} according to its internal policy.
10434      *
10435      * <p>This method should be overridden by views that wish to apply a policy different from or
10436      * in addition to the default behavior. Clients that wish to force a view subtree
10437      * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
10438      *
10439      * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
10440      * it will be called during dispatch instead of this method. The listener may optionally
10441      * call this method from its own implementation if it wishes to apply the view's default
10442      * insets policy in addition to its own.</p>
10443      *
10444      * <p>Implementations of this method should either return the insets parameter unchanged
10445      * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
10446      * that this view applied itself. This allows new inset types added in future platform
10447      * versions to pass through existing implementations unchanged without being erroneously
10448      * consumed.</p>
10449      *
10450      * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
10451      * property is set then the view will consume the system window insets and apply them
10452      * as padding for the view.</p>
10453      *
10454      * @param insets Insets to apply
10455      * @return The supplied insets with any applied insets consumed
10456      */
10457     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
10458         if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
10459             // We weren't called from within a direct call to fitSystemWindows,
10460             // call into it as a fallback in case we're in a class that overrides it
10461             // and has logic to perform.
10462             if (fitSystemWindows(insets.getSystemWindowInsetsAsRect())) {
10463                 return insets.consumeSystemWindowInsets();
10464             }
10465         } else {
10466             // We were called from within a direct call to fitSystemWindows.
10467             if (fitSystemWindowsInt(insets.getSystemWindowInsetsAsRect())) {
10468                 return insets.consumeSystemWindowInsets();
10469             }
10470         }
10471         return insets;
10472     }
10473 
10474     /**
10475      * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
10476      * window insets to this view. The listener's
10477      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
10478      * method will be called instead of the view's
10479      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
10480      *
10481      * @param listener Listener to set
10482      *
10483      * @see #onApplyWindowInsets(WindowInsets)
10484      */
10485     public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
10486         getListenerInfo().mOnApplyWindowInsetsListener = listener;
10487     }
10488 
10489     /**
10490      * Request to apply the given window insets to this view or another view in its subtree.
10491      *
10492      * <p>This method should be called by clients wishing to apply insets corresponding to areas
10493      * obscured by window decorations or overlays. This can include the status and navigation bars,
10494      * action bars, input methods and more. New inset categories may be added in the future.
10495      * The method returns the insets provided minus any that were applied by this view or its
10496      * children.</p>
10497      *
10498      * <p>Clients wishing to provide custom behavior should override the
10499      * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
10500      * {@link OnApplyWindowInsetsListener} via the
10501      * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
10502      * method.</p>
10503      *
10504      * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
10505      * </p>
10506      *
10507      * @param insets Insets to apply
10508      * @return The provided insets minus the insets that were consumed
10509      */
10510     public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
10511         try {
10512             mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
10513             if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
10514                 return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
10515             } else {
10516                 return onApplyWindowInsets(insets);
10517             }
10518         } finally {
10519             mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
10520         }
10521     }
10522 
10523     /**
10524      * Sets a {@link WindowInsetsAnimationListener} to be notified about animations of windows that
10525      * cause insets.
10526      *
10527      * @param listener The listener to set.
10528      * @hide pending unhide
10529      */
10530     public void setWindowInsetsAnimationListener(WindowInsetsAnimationListener listener) {
10531         getListenerInfo().mWindowInsetsAnimationListener = listener;
10532     }
10533 
10534     void dispatchWindowInsetsAnimationStarted(InsetsAnimation animation) {
10535         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationListener != null) {
10536             mListenerInfo.mWindowInsetsAnimationListener.onStarted(animation);
10537         }
10538     }
10539 
10540     WindowInsets dispatchWindowInsetsAnimationProgress(WindowInsets insets) {
10541         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationListener != null) {
10542             return mListenerInfo.mWindowInsetsAnimationListener.onProgress(insets);
10543         } else {
10544             return insets;
10545         }
10546     }
10547 
10548     void dispatchWindowInsetsAnimationFinished(InsetsAnimation animation) {
10549         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationListener != null) {
10550             mListenerInfo.mWindowInsetsAnimationListener.onFinished(animation);
10551         }
10552     }
10553 
10554     /**
10555      * Sets a list of areas within this view's post-layout coordinate space where the system
10556      * should not intercept touch or other pointing device gestures. <em>This method should
10557      * be called by {@link #onLayout(boolean, int, int, int, int)} or {@link #onDraw(Canvas)}.</em>
10558      *
10559      * <p>Use this to tell the system which specific sub-areas of a view need to receive gesture
10560      * input in order to function correctly in the presence of global system gestures that may
10561      * conflict. For example, if the system wishes to capture swipe-in-from-screen-edge gestures
10562      * to provide system-level navigation functionality, a view such as a navigation drawer
10563      * container can mark the left (or starting) edge of itself as requiring gesture capture
10564      * priority using this API. The system may then choose to relax its own gesture recognition
10565      * to allow the app to consume the user's gesture. It is not necessary for an app to register
10566      * exclusion rects for broadly spanning regions such as the entirety of a
10567      * <code>ScrollView</code> or for simple press and release click targets such as
10568      * <code>Button</code>. Mark an exclusion rect when interacting with a view requires
10569      * a precision touch gesture in a small area in either the X or Y dimension, such as
10570      * an edge swipe or dragging a <code>SeekBar</code> thumb.</p>
10571      *
10572      * <p>Do not modify the provided list after this method is called.</p>
10573      *
10574      * @param rects A list of precision gesture regions that this view needs to function correctly
10575      */
10576     public void setSystemGestureExclusionRects(@NonNull List<Rect> rects) {
10577         if (rects.isEmpty() && mListenerInfo == null) return;
10578 
10579         final ListenerInfo info = getListenerInfo();
10580         if (rects.isEmpty()) {
10581             info.mSystemGestureExclusionRects = null;
10582             if (info.mPositionUpdateListener != null) {
10583                 mRenderNode.removePositionUpdateListener(info.mPositionUpdateListener);
10584             }
10585         } else {
10586             info.mSystemGestureExclusionRects = rects;
10587             if (info.mPositionUpdateListener == null) {
10588                 info.mPositionUpdateListener = new RenderNode.PositionUpdateListener() {
10589                     @Override
10590                     public void positionChanged(long n, int l, int t, int r, int b) {
10591                         postUpdateSystemGestureExclusionRects();
10592                     }
10593 
10594                     @Override
10595                     public void positionLost(long frameNumber) {
10596                         postUpdateSystemGestureExclusionRects();
10597                     }
10598                 };
10599                 mRenderNode.addPositionUpdateListener(info.mPositionUpdateListener);
10600             }
10601         }
10602         postUpdateSystemGestureExclusionRects();
10603     }
10604 
10605     /**
10606      * WARNING: this can be called by a hwui worker thread, not just the UI thread!
10607      */
10608     void postUpdateSystemGestureExclusionRects() {
10609         // Potentially racey from a background thread. It's ok if it's not perfect.
10610         final Handler h = getHandler();
10611         if (h != null) {
10612             h.postAtFrontOfQueue(this::updateSystemGestureExclusionRects);
10613         }
10614     }
10615 
10616     void updateSystemGestureExclusionRects() {
10617         final AttachInfo ai = mAttachInfo;
10618         if (ai != null) {
10619             ai.mViewRootImpl.updateSystemGestureExclusionRectsForView(this);
10620         }
10621     }
10622 
10623     /**
10624      * Retrieve the list of areas within this view's post-layout coordinate space where the system
10625      * should not intercept touch or other pointing device gestures.
10626      *
10627      * <p>Do not modify the returned list.</p>
10628      *
10629      * @return the list set by {@link #setSystemGestureExclusionRects(List)}
10630      */
10631     @NonNull
10632     public List<Rect> getSystemGestureExclusionRects() {
10633         final ListenerInfo info = mListenerInfo;
10634         if (info != null) {
10635             final List<Rect> list = info.mSystemGestureExclusionRects;
10636             if (list != null) {
10637                 return list;
10638             }
10639         }
10640         return Collections.emptyList();
10641     }
10642 
10643     /**
10644      * Compute the view's coordinate within the surface.
10645      *
10646      * <p>Computes the coordinates of this view in its surface. The argument
10647      * must be an array of two integers. After the method returns, the array
10648      * contains the x and y location in that order.</p>
10649      *
10650      * @param location an array of two integers in which to hold the coordinates
10651      */
10652     public void getLocationInSurface(@NonNull @Size(2) int[] location) {
10653         getLocationInWindow(location);
10654         if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
10655             location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
10656             location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
10657         }
10658     }
10659 
10660     /**
10661      * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
10662      * only available if the view is attached.
10663      *
10664      * @return WindowInsets from the top of the view hierarchy or null if View is detached
10665      */
10666     public WindowInsets getRootWindowInsets() {
10667         if (mAttachInfo != null) {
10668             return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
10669         }
10670         return null;
10671     }
10672 
10673     /**
10674      * Retrieves the single {@link WindowInsetsController} of the window this view is attached to.
10675      *
10676      * @return The {@link WindowInsetsController} or {@code null} if the view isn't attached to a
10677      *         a window.
10678      * @see Window#getInsetsController()
10679      * @hide pending unhide
10680      */
10681     public @Nullable WindowInsetsController getWindowInsetsController() {
10682         if (mAttachInfo != null) {
10683             return mAttachInfo.mViewRootImpl.getInsetsController();
10684         }
10685         return null;
10686     }
10687 
10688     /**
10689      * @hide Compute the insets that should be consumed by this view and the ones
10690      * that should propagate to those under it.
10691      *
10692      * Note: This is used by appcompat's ActionBarOverlayLayout through reflection.
10693      *
10694      * @param inoutInsets the insets given to this view
10695      * @param outLocalInsets the insets that should be applied to this view
10696      * @deprecated use {@link #computeSystemWindowInsets}
10697      * @return
10698      */
10699     @Deprecated
10700     @UnsupportedAppUsage
10701     protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
10702         WindowInsets innerInsets = computeSystemWindowInsets(new WindowInsets(inoutInsets),
10703                 outLocalInsets);
10704         inoutInsets.set(innerInsets.getSystemWindowInsetsAsRect());
10705         return innerInsets.isSystemWindowInsetsConsumed();
10706     }
10707 
10708     /**
10709      * Compute insets that should be consumed by this view and the ones that should propagate
10710      * to those under it.
10711      *
10712      * @param in Insets currently being processed by this View, likely received as a parameter
10713      *           to {@link #onApplyWindowInsets(WindowInsets)}.
10714      * @param outLocalInsets A Rect that will receive the insets that should be consumed
10715      *                       by this view
10716      * @return Insets that should be passed along to views under this one
10717      */
10718     public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
10719         if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
10720                 || mAttachInfo == null
10721                 || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
10722                 && !mAttachInfo.mOverscanRequested)) {
10723             outLocalInsets.set(in.getSystemWindowInsetsAsRect());
10724             return in.consumeSystemWindowInsets().inset(outLocalInsets);
10725         } else {
10726             // The application wants to take care of fitting system window for
10727             // the content...  however we still need to take care of any overscan here.
10728             final Rect overscan = mAttachInfo.mOverscanInsets;
10729             outLocalInsets.set(overscan);
10730             return in.inset(outLocalInsets);
10731         }
10732     }
10733 
10734     /**
10735      * Sets whether or not this view should account for system screen decorations
10736      * such as the status bar and inset its content; that is, controlling whether
10737      * the default implementation of {@link #fitSystemWindows(Rect)} will be
10738      * executed.  See that method for more details.
10739      *
10740      * <p>Note that if you are providing your own implementation of
10741      * {@link #fitSystemWindows(Rect)}, then there is no need to set this
10742      * flag to true -- your implementation will be overriding the default
10743      * implementation that checks this flag.
10744      *
10745      * @param fitSystemWindows If true, then the default implementation of
10746      * {@link #fitSystemWindows(Rect)} will be executed.
10747      *
10748      * @attr ref android.R.styleable#View_fitsSystemWindows
10749      * @see #getFitsSystemWindows()
10750      * @see #fitSystemWindows(Rect)
10751      * @see #setSystemUiVisibility(int)
10752      */
10753     public void setFitsSystemWindows(boolean fitSystemWindows) {
10754         setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
10755     }
10756 
10757     /**
10758      * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
10759      * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
10760      * will be executed.
10761      *
10762      * @return {@code true} if the default implementation of
10763      * {@link #fitSystemWindows(Rect)} will be executed.
10764      *
10765      * @attr ref android.R.styleable#View_fitsSystemWindows
10766      * @see #setFitsSystemWindows(boolean)
10767      * @see #fitSystemWindows(Rect)
10768      * @see #setSystemUiVisibility(int)
10769      */
10770     @ViewDebug.ExportedProperty
10771     @InspectableProperty
10772     public boolean getFitsSystemWindows() {
10773         return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
10774     }
10775 
10776     /** @hide */
10777     @UnsupportedAppUsage
10778     public boolean fitsSystemWindows() {
10779         return getFitsSystemWindows();
10780     }
10781 
10782     /**
10783      * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
10784      * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
10785      */
10786     @Deprecated
10787     public void requestFitSystemWindows() {
10788         if (mParent != null) {
10789             mParent.requestFitSystemWindows();
10790         }
10791     }
10792 
10793     /**
10794      * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
10795      */
10796     public void requestApplyInsets() {
10797         requestFitSystemWindows();
10798     }
10799 
10800     /**
10801      * For use by PhoneWindow to make its own system window fitting optional.
10802      * @hide
10803      */
10804     @UnsupportedAppUsage
10805     public void makeOptionalFitsSystemWindows() {
10806         setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
10807     }
10808 
10809     /**
10810      * Returns the outsets, which areas of the device that aren't a surface, but we would like to
10811      * treat them as such.
10812      * @hide
10813      */
10814     public void getOutsets(Rect outOutsetRect) {
10815         if (mAttachInfo != null) {
10816             outOutsetRect.set(mAttachInfo.mOutsets);
10817         } else {
10818             outOutsetRect.setEmpty();
10819         }
10820     }
10821 
10822     /**
10823      * Returns the visibility status for this view.
10824      *
10825      * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
10826      * @attr ref android.R.styleable#View_visibility
10827      */
10828     @ViewDebug.ExportedProperty(mapping = {
10829         @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
10830         @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
10831         @ViewDebug.IntToString(from = GONE,      to = "GONE")
10832     })
10833     @InspectableProperty(enumMapping = {
10834             @EnumEntry(value = VISIBLE, name = "visible"),
10835             @EnumEntry(value = INVISIBLE, name = "invisible"),
10836             @EnumEntry(value = GONE, name = "gone")
10837     })
10838     @Visibility
10839     public int getVisibility() {
10840         return mViewFlags & VISIBILITY_MASK;
10841     }
10842 
10843     /**
10844      * Set the visibility state of this view.
10845      *
10846      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
10847      * @attr ref android.R.styleable#View_visibility
10848      */
10849     @RemotableViewMethod
10850     public void setVisibility(@Visibility int visibility) {
10851         setFlags(visibility, VISIBILITY_MASK);
10852     }
10853 
10854     /**
10855      * Returns the enabled status for this view. The interpretation of the
10856      * enabled state varies by subclass.
10857      *
10858      * @return True if this view is enabled, false otherwise.
10859      */
10860     @ViewDebug.ExportedProperty
10861     @InspectableProperty
10862     public boolean isEnabled() {
10863         return (mViewFlags & ENABLED_MASK) == ENABLED;
10864     }
10865 
10866     /**
10867      * Set the enabled state of this view. The interpretation of the enabled
10868      * state varies by subclass.
10869      *
10870      * @param enabled True if this view is enabled, false otherwise.
10871      */
10872     @RemotableViewMethod
10873     public void setEnabled(boolean enabled) {
10874         if (enabled == isEnabled()) return;
10875 
10876         setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
10877 
10878         /*
10879          * The View most likely has to change its appearance, so refresh
10880          * the drawable state.
10881          */
10882         refreshDrawableState();
10883 
10884         // Invalidate too, since the default behavior for views is to be
10885         // be drawn at 50% alpha rather than to change the drawable.
10886         invalidate(true);
10887 
10888         if (!enabled) {
10889             cancelPendingInputEvents();
10890         }
10891     }
10892 
10893     /**
10894      * Set whether this view can receive the focus.
10895      * <p>
10896      * Setting this to false will also ensure that this view is not focusable
10897      * in touch mode.
10898      *
10899      * @param focusable If true, this view can receive the focus.
10900      *
10901      * @see #setFocusableInTouchMode(boolean)
10902      * @see #setFocusable(int)
10903      * @attr ref android.R.styleable#View_focusable
10904      */
10905     public void setFocusable(boolean focusable) {
10906         setFocusable(focusable ? FOCUSABLE : NOT_FOCUSABLE);
10907     }
10908 
10909     /**
10910      * Sets whether this view can receive focus.
10911      * <p>
10912      * Setting this to {@link #FOCUSABLE_AUTO} tells the framework to determine focusability
10913      * automatically based on the view's interactivity. This is the default.
10914      * <p>
10915      * Setting this to NOT_FOCUSABLE will ensure that this view is also not focusable
10916      * in touch mode.
10917      *
10918      * @param focusable One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE},
10919      *                  or {@link #FOCUSABLE_AUTO}.
10920      * @see #setFocusableInTouchMode(boolean)
10921      * @attr ref android.R.styleable#View_focusable
10922      */
10923     public void setFocusable(@Focusable int focusable) {
10924         if ((focusable & (FOCUSABLE_AUTO | FOCUSABLE)) == 0) {
10925             setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
10926         }
10927         setFlags(focusable, FOCUSABLE_MASK);
10928     }
10929 
10930     /**
10931      * Set whether this view can receive focus while in touch mode.
10932      *
10933      * Setting this to true will also ensure that this view is focusable.
10934      *
10935      * @param focusableInTouchMode If true, this view can receive the focus while
10936      *   in touch mode.
10937      *
10938      * @see #setFocusable(boolean)
10939      * @attr ref android.R.styleable#View_focusableInTouchMode
10940      */
10941     public void setFocusableInTouchMode(boolean focusableInTouchMode) {
10942         // Focusable in touch mode should always be set before the focusable flag
10943         // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
10944         // which, in touch mode, will not successfully request focus on this view
10945         // because the focusable in touch mode flag is not set
10946         setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
10947 
10948         // Clear FOCUSABLE_AUTO if set.
10949         if (focusableInTouchMode) {
10950             // Clears FOCUSABLE_AUTO if set.
10951             setFlags(FOCUSABLE, FOCUSABLE_MASK);
10952         }
10953     }
10954 
10955     /**
10956      * Sets the hints that help an {@link android.service.autofill.AutofillService} determine how
10957      * to autofill the view with the user's data.
10958      *
10959      * <p>Typically, there is only one way to autofill a view, but there could be more than one.
10960      * For example, if the application accepts either an username or email address to identify
10961      * an user.
10962      *
10963      * <p>These hints are not validated by the Android System, but passed "as is" to the service.
10964      * Hence, they can have any value, but it's recommended to use the {@code AUTOFILL_HINT_}
10965      * constants such as:
10966      * {@link #AUTOFILL_HINT_USERNAME}, {@link #AUTOFILL_HINT_PASSWORD},
10967      * {@link #AUTOFILL_HINT_EMAIL_ADDRESS},
10968      * {@link #AUTOFILL_HINT_NAME},
10969      * {@link #AUTOFILL_HINT_PHONE},
10970      * {@link #AUTOFILL_HINT_POSTAL_ADDRESS}, {@link #AUTOFILL_HINT_POSTAL_CODE},
10971      * {@link #AUTOFILL_HINT_CREDIT_CARD_NUMBER}, {@link #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE},
10972      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE},
10973      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
10974      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH} or
10975      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}.
10976      *
10977      * @param autofillHints The autofill hints to set. If the array is emtpy, {@code null} is set.
10978      * @attr ref android.R.styleable#View_autofillHints
10979      */
10980     public void setAutofillHints(@Nullable String... autofillHints) {
10981         if (autofillHints == null || autofillHints.length == 0) {
10982             mAutofillHints = null;
10983         } else {
10984             mAutofillHints = autofillHints;
10985         }
10986     }
10987 
10988     /**
10989      * @hide
10990      */
10991     @TestApi
10992     public void setAutofilled(boolean isAutofilled) {
10993         boolean wasChanged = isAutofilled != isAutofilled();
10994 
10995         if (wasChanged) {
10996             if (isAutofilled) {
10997                 mPrivateFlags3 |= PFLAG3_IS_AUTOFILLED;
10998             } else {
10999                 mPrivateFlags3 &= ~PFLAG3_IS_AUTOFILLED;
11000             }
11001 
11002             invalidate();
11003         }
11004     }
11005 
11006     /**
11007      * Set whether this view should have sound effects enabled for events such as
11008      * clicking and touching.
11009      *
11010      * <p>You may wish to disable sound effects for a view if you already play sounds,
11011      * for instance, a dial key that plays dtmf tones.
11012      *
11013      * @param soundEffectsEnabled whether sound effects are enabled for this view.
11014      * @see #isSoundEffectsEnabled()
11015      * @see #playSoundEffect(int)
11016      * @attr ref android.R.styleable#View_soundEffectsEnabled
11017      */
11018     public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
11019         setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
11020     }
11021 
11022     /**
11023      * @return whether this view should have sound effects enabled for events such as
11024      *     clicking and touching.
11025      *
11026      * @see #setSoundEffectsEnabled(boolean)
11027      * @see #playSoundEffect(int)
11028      * @attr ref android.R.styleable#View_soundEffectsEnabled
11029      */
11030     @ViewDebug.ExportedProperty
11031     @InspectableProperty
11032     public boolean isSoundEffectsEnabled() {
11033         return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
11034     }
11035 
11036     /**
11037      * Set whether this view should have haptic feedback for events such as
11038      * long presses.
11039      *
11040      * <p>You may wish to disable haptic feedback if your view already controls
11041      * its own haptic feedback.
11042      *
11043      * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
11044      * @see #isHapticFeedbackEnabled()
11045      * @see #performHapticFeedback(int)
11046      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
11047      */
11048     public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
11049         setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
11050     }
11051 
11052     /**
11053      * @return whether this view should have haptic feedback enabled for events
11054      * long presses.
11055      *
11056      * @see #setHapticFeedbackEnabled(boolean)
11057      * @see #performHapticFeedback(int)
11058      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
11059      */
11060     @ViewDebug.ExportedProperty
11061     @InspectableProperty
11062     public boolean isHapticFeedbackEnabled() {
11063         return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
11064     }
11065 
11066     /**
11067      * Returns the layout direction for this view.
11068      *
11069      * @return One of {@link #LAYOUT_DIRECTION_LTR},
11070      *   {@link #LAYOUT_DIRECTION_RTL},
11071      *   {@link #LAYOUT_DIRECTION_INHERIT} or
11072      *   {@link #LAYOUT_DIRECTION_LOCALE}.
11073      *
11074      * @attr ref android.R.styleable#View_layoutDirection
11075      *
11076      * @hide
11077      */
11078     @ViewDebug.ExportedProperty(category = "layout", mapping = {
11079         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
11080         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
11081         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
11082         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
11083     })
11084     @InspectableProperty(hasAttributeId = false, enumMapping = {
11085             @EnumEntry(value = LAYOUT_DIRECTION_LTR, name = "ltr"),
11086             @EnumEntry(value = LAYOUT_DIRECTION_RTL, name = "rtl"),
11087             @EnumEntry(value = LAYOUT_DIRECTION_INHERIT, name = "inherit"),
11088             @EnumEntry(value = LAYOUT_DIRECTION_LOCALE, name = "locale")
11089     })
11090     @LayoutDir
11091     public int getRawLayoutDirection() {
11092         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
11093     }
11094 
11095     /**
11096      * Set the layout direction for this view. This will propagate a reset of layout direction
11097      * resolution to the view's children and resolve layout direction for this view.
11098      *
11099      * @param layoutDirection the layout direction to set. Should be one of:
11100      *
11101      * {@link #LAYOUT_DIRECTION_LTR},
11102      * {@link #LAYOUT_DIRECTION_RTL},
11103      * {@link #LAYOUT_DIRECTION_INHERIT},
11104      * {@link #LAYOUT_DIRECTION_LOCALE}.
11105      *
11106      * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
11107      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
11108      * will return the default {@link #LAYOUT_DIRECTION_LTR}.
11109      *
11110      * @attr ref android.R.styleable#View_layoutDirection
11111      */
11112     @RemotableViewMethod
11113     public void setLayoutDirection(@LayoutDir int layoutDirection) {
11114         if (getRawLayoutDirection() != layoutDirection) {
11115             // Reset the current layout direction and the resolved one
11116             mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
11117             resetRtlProperties();
11118             // Set the new layout direction (filtered)
11119             mPrivateFlags2 |=
11120                     ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
11121             // We need to resolve all RTL properties as they all depend on layout direction
11122             resolveRtlPropertiesIfNeeded();
11123             requestLayout();
11124             invalidate(true);
11125         }
11126     }
11127 
11128     /**
11129      * Returns the resolved layout direction for this view.
11130      *
11131      * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
11132      * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
11133      *
11134      * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
11135      * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
11136      *
11137      * @attr ref android.R.styleable#View_layoutDirection
11138      */
11139     @ViewDebug.ExportedProperty(category = "layout", mapping = {
11140         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
11141         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
11142     })
11143     @InspectableProperty(enumMapping = {
11144             @EnumEntry(value = LAYOUT_DIRECTION_LTR, name = "ltr"),
11145             @EnumEntry(value = LAYOUT_DIRECTION_RTL, name = "rtl")
11146     })
11147     @ResolvedLayoutDir
11148     public int getLayoutDirection() {
11149         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
11150         if (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
11151             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
11152             return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
11153         }
11154         return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
11155                 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
11156     }
11157 
11158     /**
11159      * Indicates whether or not this view's layout is right-to-left. This is resolved from
11160      * layout attribute and/or the inherited value from the parent
11161      *
11162      * @return true if the layout is right-to-left.
11163      *
11164      * @hide
11165      */
11166     @ViewDebug.ExportedProperty(category = "layout")
11167     @UnsupportedAppUsage
11168     public boolean isLayoutRtl() {
11169         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
11170     }
11171 
11172     /**
11173      * Indicates whether the view is currently tracking transient state that the
11174      * app should not need to concern itself with saving and restoring, but that
11175      * the framework should take special note to preserve when possible.
11176      *
11177      * <p>A view with transient state cannot be trivially rebound from an external
11178      * data source, such as an adapter binding item views in a list. This may be
11179      * because the view is performing an animation, tracking user selection
11180      * of content, or similar.</p>
11181      *
11182      * @return true if the view has transient state
11183      */
11184     @ViewDebug.ExportedProperty(category = "layout")
11185     public boolean hasTransientState() {
11186         return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
11187     }
11188 
11189     /**
11190      * Set whether this view is currently tracking transient state that the
11191      * framework should attempt to preserve when possible. This flag is reference counted,
11192      * so every call to setHasTransientState(true) should be paired with a later call
11193      * to setHasTransientState(false).
11194      *
11195      * <p>A view with transient state cannot be trivially rebound from an external
11196      * data source, such as an adapter binding item views in a list. This may be
11197      * because the view is performing an animation, tracking user selection
11198      * of content, or similar.</p>
11199      *
11200      * @param hasTransientState true if this view has transient state
11201      */
11202     public void setHasTransientState(boolean hasTransientState) {
11203         final boolean oldHasTransientState = hasTransientState();
11204         mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
11205                 mTransientStateCount - 1;
11206         if (mTransientStateCount < 0) {
11207             mTransientStateCount = 0;
11208             Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
11209                     "unmatched pair of setHasTransientState calls");
11210         } else if ((hasTransientState && mTransientStateCount == 1) ||
11211                 (!hasTransientState && mTransientStateCount == 0)) {
11212             // update flag if we've just incremented up from 0 or decremented down to 0
11213             mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
11214                     (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
11215             final boolean newHasTransientState = hasTransientState();
11216             if (mParent != null && newHasTransientState != oldHasTransientState) {
11217                 try {
11218                     mParent.childHasTransientStateChanged(this, newHasTransientState);
11219                 } catch (AbstractMethodError e) {
11220                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
11221                             " does not fully implement ViewParent", e);
11222                 }
11223             }
11224         }
11225     }
11226 
11227     /**
11228      * Returns true if this view is currently attached to a window.
11229      */
11230     public boolean isAttachedToWindow() {
11231         return mAttachInfo != null;
11232     }
11233 
11234     /**
11235      * Returns true if this view has been through at least one layout since it
11236      * was last attached to or detached from a window.
11237      */
11238     public boolean isLaidOut() {
11239         return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
11240     }
11241 
11242     /**
11243      * @return {@code true} if laid-out and not about to do another layout.
11244      */
11245     boolean isLayoutValid() {
11246         return isLaidOut() && ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == 0);
11247     }
11248 
11249     /**
11250      * If this view doesn't do any drawing on its own, set this flag to
11251      * allow further optimizations. By default, this flag is not set on
11252      * View, but could be set on some View subclasses such as ViewGroup.
11253      *
11254      * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
11255      * you should clear this flag.
11256      *
11257      * @param willNotDraw whether or not this View draw on its own
11258      */
11259     public void setWillNotDraw(boolean willNotDraw) {
11260         setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
11261     }
11262 
11263     /**
11264      * Returns whether or not this View draws on its own.
11265      *
11266      * @return true if this view has nothing to draw, false otherwise
11267      */
11268     @ViewDebug.ExportedProperty(category = "drawing")
11269     public boolean willNotDraw() {
11270         return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
11271     }
11272 
11273     /**
11274      * When a View's drawing cache is enabled, drawing is redirected to an
11275      * offscreen bitmap. Some views, like an ImageView, must be able to
11276      * bypass this mechanism if they already draw a single bitmap, to avoid
11277      * unnecessary usage of the memory.
11278      *
11279      * @param willNotCacheDrawing true if this view does not cache its
11280      *        drawing, false otherwise
11281      *
11282      * @deprecated The view drawing cache was largely made obsolete with the introduction of
11283      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
11284      * layers are largely unnecessary and can easily result in a net loss in performance due to the
11285      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
11286      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
11287      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
11288      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
11289      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
11290      * software-rendered usages are discouraged and have compatibility issues with hardware-only
11291      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
11292      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
11293      * reports or unit testing the {@link PixelCopy} API is recommended.
11294      */
11295     @Deprecated
11296     public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
11297         setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
11298     }
11299 
11300     /**
11301      * Returns whether or not this View can cache its drawing or not.
11302      *
11303      * @return true if this view does not cache its drawing, false otherwise
11304      *
11305      * @deprecated The view drawing cache was largely made obsolete with the introduction of
11306      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
11307      * layers are largely unnecessary and can easily result in a net loss in performance due to the
11308      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
11309      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
11310      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
11311      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
11312      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
11313      * software-rendered usages are discouraged and have compatibility issues with hardware-only
11314      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
11315      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
11316      * reports or unit testing the {@link PixelCopy} API is recommended.
11317      */
11318     @ViewDebug.ExportedProperty(category = "drawing")
11319     @Deprecated
11320     public boolean willNotCacheDrawing() {
11321         return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
11322     }
11323 
11324     /**
11325      * Indicates whether this view reacts to click events or not.
11326      *
11327      * @return true if the view is clickable, false otherwise
11328      *
11329      * @see #setClickable(boolean)
11330      * @attr ref android.R.styleable#View_clickable
11331      */
11332     @ViewDebug.ExportedProperty
11333     @InspectableProperty
11334     public boolean isClickable() {
11335         return (mViewFlags & CLICKABLE) == CLICKABLE;
11336     }
11337 
11338     /**
11339      * Enables or disables click events for this view. When a view
11340      * is clickable it will change its state to "pressed" on every click.
11341      * Subclasses should set the view clickable to visually react to
11342      * user's clicks.
11343      *
11344      * @param clickable true to make the view clickable, false otherwise
11345      *
11346      * @see #isClickable()
11347      * @attr ref android.R.styleable#View_clickable
11348      */
11349     public void setClickable(boolean clickable) {
11350         setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
11351     }
11352 
11353     /**
11354      * Indicates whether this view reacts to long click events or not.
11355      *
11356      * @return true if the view is long clickable, false otherwise
11357      *
11358      * @see #setLongClickable(boolean)
11359      * @attr ref android.R.styleable#View_longClickable
11360      */
11361     @InspectableProperty
11362     public boolean isLongClickable() {
11363         return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
11364     }
11365 
11366     /**
11367      * Enables or disables long click events for this view. When a view is long
11368      * clickable it reacts to the user holding down the button for a longer
11369      * duration than a tap. This event can either launch the listener or a
11370      * context menu.
11371      *
11372      * @param longClickable true to make the view long clickable, false otherwise
11373      * @see #isLongClickable()
11374      * @attr ref android.R.styleable#View_longClickable
11375      */
11376     public void setLongClickable(boolean longClickable) {
11377         setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
11378     }
11379 
11380     /**
11381      * Indicates whether this view reacts to context clicks or not.
11382      *
11383      * @return true if the view is context clickable, false otherwise
11384      * @see #setContextClickable(boolean)
11385      * @attr ref android.R.styleable#View_contextClickable
11386      */
11387     @InspectableProperty
11388     public boolean isContextClickable() {
11389         return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
11390     }
11391 
11392     /**
11393      * Enables or disables context clicking for this view. This event can launch the listener.
11394      *
11395      * @param contextClickable true to make the view react to a context click, false otherwise
11396      * @see #isContextClickable()
11397      * @attr ref android.R.styleable#View_contextClickable
11398      */
11399     public void setContextClickable(boolean contextClickable) {
11400         setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
11401     }
11402 
11403     /**
11404      * Sets the pressed state for this view and provides a touch coordinate for
11405      * animation hinting.
11406      *
11407      * @param pressed Pass true to set the View's internal state to "pressed",
11408      *            or false to reverts the View's internal state from a
11409      *            previously set "pressed" state.
11410      * @param x The x coordinate of the touch that caused the press
11411      * @param y The y coordinate of the touch that caused the press
11412      */
11413     private void setPressed(boolean pressed, float x, float y) {
11414         if (pressed) {
11415             drawableHotspotChanged(x, y);
11416         }
11417 
11418         setPressed(pressed);
11419     }
11420 
11421     /**
11422      * Sets the pressed state for this view.
11423      *
11424      * @see #isClickable()
11425      * @see #setClickable(boolean)
11426      *
11427      * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
11428      *        the View's internal state from a previously set "pressed" state.
11429      */
11430     public void setPressed(boolean pressed) {
11431         final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
11432 
11433         if (pressed) {
11434             mPrivateFlags |= PFLAG_PRESSED;
11435         } else {
11436             mPrivateFlags &= ~PFLAG_PRESSED;
11437         }
11438 
11439         if (needsRefresh) {
11440             refreshDrawableState();
11441         }
11442         dispatchSetPressed(pressed);
11443     }
11444 
11445     /**
11446      * Dispatch setPressed to all of this View's children.
11447      *
11448      * @see #setPressed(boolean)
11449      *
11450      * @param pressed The new pressed state
11451      */
11452     protected void dispatchSetPressed(boolean pressed) {
11453     }
11454 
11455     /**
11456      * Indicates whether the view is currently in pressed state. Unless
11457      * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
11458      * the pressed state.
11459      *
11460      * @see #setPressed(boolean)
11461      * @see #isClickable()
11462      * @see #setClickable(boolean)
11463      *
11464      * @return true if the view is currently pressed, false otherwise
11465      */
11466     @ViewDebug.ExportedProperty
11467     @InspectableProperty(hasAttributeId = false)
11468     public boolean isPressed() {
11469         return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
11470     }
11471 
11472     /**
11473      * @hide
11474      * Indicates whether this view will participate in data collection through
11475      * {@link ViewStructure}.  If true, it will not provide any data
11476      * for itself or its children.  If false, the normal data collection will be allowed.
11477      *
11478      * @return Returns false if assist data collection is not blocked, else true.
11479      *
11480      * @see #setAssistBlocked(boolean)
11481      * @attr ref android.R.styleable#View_assistBlocked
11482      */
11483     public boolean isAssistBlocked() {
11484         return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
11485     }
11486 
11487     /**
11488      * @hide
11489      * Controls whether assist data collection from this view and its children is enabled
11490      * (that is, whether {@link #onProvideStructure} and
11491      * {@link #onProvideVirtualStructure} will be called).  The default value is false,
11492      * allowing normal assist collection.  Setting this to false will disable assist collection.
11493      *
11494      * @param enabled Set to true to <em>disable</em> assist data collection, or false
11495      * (the default) to allow it.
11496      *
11497      * @see #isAssistBlocked()
11498      * @see #onProvideStructure
11499      * @see #onProvideVirtualStructure
11500      * @attr ref android.R.styleable#View_assistBlocked
11501      */
11502     @UnsupportedAppUsage
11503     public void setAssistBlocked(boolean enabled) {
11504         if (enabled) {
11505             mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
11506         } else {
11507             mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
11508         }
11509     }
11510 
11511     /**
11512      * Indicates whether this view will save its state (that is,
11513      * whether its {@link #onSaveInstanceState} method will be called).
11514      *
11515      * @return Returns true if the view state saving is enabled, else false.
11516      *
11517      * @see #setSaveEnabled(boolean)
11518      * @attr ref android.R.styleable#View_saveEnabled
11519      */
11520     @InspectableProperty
11521     public boolean isSaveEnabled() {
11522         return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
11523     }
11524 
11525     /**
11526      * Controls whether the saving of this view's state is
11527      * enabled (that is, whether its {@link #onSaveInstanceState} method
11528      * will be called).  Note that even if freezing is enabled, the
11529      * view still must have an id assigned to it (via {@link #setId(int)})
11530      * for its state to be saved.  This flag can only disable the
11531      * saving of this view; any child views may still have their state saved.
11532      *
11533      * @param enabled Set to false to <em>disable</em> state saving, or true
11534      * (the default) to allow it.
11535      *
11536      * @see #isSaveEnabled()
11537      * @see #setId(int)
11538      * @see #onSaveInstanceState()
11539      * @attr ref android.R.styleable#View_saveEnabled
11540      */
11541     public void setSaveEnabled(boolean enabled) {
11542         setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
11543     }
11544 
11545     /**
11546      * Gets whether the framework should discard touches when the view's
11547      * window is obscured by another visible window.
11548      * Refer to the {@link View} security documentation for more details.
11549      *
11550      * @return True if touch filtering is enabled.
11551      *
11552      * @see #setFilterTouchesWhenObscured(boolean)
11553      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
11554      */
11555     @ViewDebug.ExportedProperty
11556     @InspectableProperty
11557     public boolean getFilterTouchesWhenObscured() {
11558         return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
11559     }
11560 
11561     /**
11562      * Sets whether the framework should discard touches when the view's
11563      * window is obscured by another visible window.
11564      * Refer to the {@link View} security documentation for more details.
11565      *
11566      * @param enabled True if touch filtering should be enabled.
11567      *
11568      * @see #getFilterTouchesWhenObscured
11569      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
11570      */
11571     public void setFilterTouchesWhenObscured(boolean enabled) {
11572         setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
11573                 FILTER_TOUCHES_WHEN_OBSCURED);
11574     }
11575 
11576     /**
11577      * Indicates whether the entire hierarchy under this view will save its
11578      * state when a state saving traversal occurs from its parent.  The default
11579      * is true; if false, these views will not be saved unless
11580      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
11581      *
11582      * @return Returns true if the view state saving from parent is enabled, else false.
11583      *
11584      * @see #setSaveFromParentEnabled(boolean)
11585      */
11586     public boolean isSaveFromParentEnabled() {
11587         return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
11588     }
11589 
11590     /**
11591      * Controls whether the entire hierarchy under this view will save its
11592      * state when a state saving traversal occurs from its parent.  The default
11593      * is true; if false, these views will not be saved unless
11594      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
11595      *
11596      * @param enabled Set to false to <em>disable</em> state saving, or true
11597      * (the default) to allow it.
11598      *
11599      * @see #isSaveFromParentEnabled()
11600      * @see #setId(int)
11601      * @see #onSaveInstanceState()
11602      */
11603     public void setSaveFromParentEnabled(boolean enabled) {
11604         setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
11605     }
11606 
11607 
11608     /**
11609      * Returns whether this View is currently able to take focus.
11610      *
11611      * @return True if this view can take focus, or false otherwise.
11612      */
11613     @ViewDebug.ExportedProperty(category = "focus")
11614     public final boolean isFocusable() {
11615         return FOCUSABLE == (mViewFlags & FOCUSABLE);
11616     }
11617 
11618     /**
11619      * Returns the focusable setting for this view.
11620      *
11621      * @return One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE}, or {@link #FOCUSABLE_AUTO}.
11622      * @attr ref android.R.styleable#View_focusable
11623      */
11624     @ViewDebug.ExportedProperty(mapping = {
11625             @ViewDebug.IntToString(from = NOT_FOCUSABLE, to = "NOT_FOCUSABLE"),
11626             @ViewDebug.IntToString(from = FOCUSABLE, to = "FOCUSABLE"),
11627             @ViewDebug.IntToString(from = FOCUSABLE_AUTO, to = "FOCUSABLE_AUTO")
11628             }, category = "focus")
11629     @InspectableProperty(enumMapping = {
11630             @EnumEntry(value = NOT_FOCUSABLE, name = "false"),
11631             @EnumEntry(value = FOCUSABLE, name = "true"),
11632             @EnumEntry(value = FOCUSABLE_AUTO, name = "auto")
11633     })
11634     @Focusable
11635     public int getFocusable() {
11636         return (mViewFlags & FOCUSABLE_AUTO) > 0 ? FOCUSABLE_AUTO : mViewFlags & FOCUSABLE;
11637     }
11638 
11639     /**
11640      * When a view is focusable, it may not want to take focus when in touch mode.
11641      * For example, a button would like focus when the user is navigating via a D-pad
11642      * so that the user can click on it, but once the user starts touching the screen,
11643      * the button shouldn't take focus
11644      * @return Whether the view is focusable in touch mode.
11645      * @attr ref android.R.styleable#View_focusableInTouchMode
11646      */
11647     @ViewDebug.ExportedProperty(category = "focus")
11648     @InspectableProperty
11649     public final boolean isFocusableInTouchMode() {
11650         return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
11651     }
11652 
11653     /**
11654      * Returns whether the view should be treated as a focusable unit by screen reader
11655      * accessibility tools.
11656      * @see #setScreenReaderFocusable(boolean)
11657      *
11658      * @return Whether the view should be treated as a focusable unit by screen reader.
11659      *
11660      * @attr ref android.R.styleable#View_screenReaderFocusable
11661      */
11662     @InspectableProperty
11663     public boolean isScreenReaderFocusable() {
11664         return (mPrivateFlags3 & PFLAG3_SCREEN_READER_FOCUSABLE) != 0;
11665     }
11666 
11667     /**
11668      * Sets whether this View should be a focusable element for screen readers
11669      * and include non-focusable Views from its subtree when providing feedback.
11670      * <p>
11671      * Note: this is similar to using <a href="#attr_android:focusable">{@code android:focusable},
11672      * but does not impact input focus behavior.
11673      *
11674      * @param screenReaderFocusable Whether the view should be treated as a unit by screen reader
11675      *                              accessibility tools.
11676      *
11677      * @attr ref android.R.styleable#View_screenReaderFocusable
11678      */
11679     public void setScreenReaderFocusable(boolean screenReaderFocusable) {
11680         updatePflags3AndNotifyA11yIfChanged(PFLAG3_SCREEN_READER_FOCUSABLE, screenReaderFocusable);
11681     }
11682 
11683     /**
11684      * Gets whether this view is a heading for accessibility purposes.
11685      *
11686      * @return {@code true} if the view is a heading, {@code false} otherwise.
11687      *
11688      * @attr ref android.R.styleable#View_accessibilityHeading
11689      */
11690     @InspectableProperty
11691     public boolean isAccessibilityHeading() {
11692         return (mPrivateFlags3 & PFLAG3_ACCESSIBILITY_HEADING) != 0;
11693     }
11694 
11695     /**
11696      * Set if view is a heading for a section of content for accessibility purposes.
11697      *
11698      * @param isHeading {@code true} if the view is a heading, {@code false} otherwise.
11699      *
11700      * @attr ref android.R.styleable#View_accessibilityHeading
11701      */
11702     public void setAccessibilityHeading(boolean isHeading) {
11703         updatePflags3AndNotifyA11yIfChanged(PFLAG3_ACCESSIBILITY_HEADING, isHeading);
11704     }
11705 
11706     private void updatePflags3AndNotifyA11yIfChanged(int mask, boolean newValue) {
11707         int pflags3 = mPrivateFlags3;
11708         if (newValue) {
11709             pflags3 |= mask;
11710         } else {
11711             pflags3 &= ~mask;
11712         }
11713 
11714         if (pflags3 != mPrivateFlags3) {
11715             mPrivateFlags3 = pflags3;
11716             notifyViewAccessibilityStateChangedIfNeeded(
11717                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11718         }
11719     }
11720 
11721     /**
11722      * Find the nearest view in the specified direction that can take focus.
11723      * This does not actually give focus to that view.
11724      *
11725      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
11726      *
11727      * @return The nearest focusable in the specified direction, or null if none
11728      *         can be found.
11729      */
11730     public View focusSearch(@FocusRealDirection int direction) {
11731         if (mParent != null) {
11732             return mParent.focusSearch(this, direction);
11733         } else {
11734             return null;
11735         }
11736     }
11737 
11738     /**
11739      * Returns whether this View is a root of a keyboard navigation cluster.
11740      *
11741      * @return True if this view is a root of a cluster, or false otherwise.
11742      * @attr ref android.R.styleable#View_keyboardNavigationCluster
11743      */
11744     @ViewDebug.ExportedProperty(category = "focus")
11745     @InspectableProperty
11746     public final boolean isKeyboardNavigationCluster() {
11747         return (mPrivateFlags3 & PFLAG3_CLUSTER) != 0;
11748     }
11749 
11750     /**
11751      * Searches up the view hierarchy to find the top-most cluster. All deeper/nested clusters
11752      * will be ignored.
11753      *
11754      * @return the keyboard navigation cluster that this view is in (can be this view)
11755      *         or {@code null} if not in one
11756      */
11757     View findKeyboardNavigationCluster() {
11758         if (mParent instanceof View) {
11759             View cluster = ((View) mParent).findKeyboardNavigationCluster();
11760             if (cluster != null) {
11761                 return cluster;
11762             } else if (isKeyboardNavigationCluster()) {
11763                 return this;
11764             }
11765         }
11766         return null;
11767     }
11768 
11769     /**
11770      * Set whether this view is a root of a keyboard navigation cluster.
11771      *
11772      * @param isCluster If true, this view is a root of a cluster.
11773      *
11774      * @attr ref android.R.styleable#View_keyboardNavigationCluster
11775      */
11776     public void setKeyboardNavigationCluster(boolean isCluster) {
11777         if (isCluster) {
11778             mPrivateFlags3 |= PFLAG3_CLUSTER;
11779         } else {
11780             mPrivateFlags3 &= ~PFLAG3_CLUSTER;
11781         }
11782     }
11783 
11784     /**
11785      * Sets this View as the one which receives focus the next time cluster navigation jumps
11786      * to the cluster containing this View. This does NOT change focus even if the cluster
11787      * containing this view is current.
11788      *
11789      * @hide
11790      */
11791     @TestApi
11792     public final void setFocusedInCluster() {
11793         setFocusedInCluster(findKeyboardNavigationCluster());
11794     }
11795 
11796     private void setFocusedInCluster(View cluster) {
11797         if (this instanceof ViewGroup) {
11798             ((ViewGroup) this).mFocusedInCluster = null;
11799         }
11800         if (cluster == this) {
11801             return;
11802         }
11803         ViewParent parent = mParent;
11804         View child = this;
11805         while (parent instanceof ViewGroup) {
11806             ((ViewGroup) parent).mFocusedInCluster = child;
11807             if (parent == cluster) {
11808                 break;
11809             }
11810             child = (View) parent;
11811             parent = parent.getParent();
11812         }
11813     }
11814 
11815     private void updateFocusedInCluster(View oldFocus, @FocusDirection int direction) {
11816         if (oldFocus != null) {
11817             View oldCluster = oldFocus.findKeyboardNavigationCluster();
11818             View cluster = findKeyboardNavigationCluster();
11819             if (oldCluster != cluster) {
11820                 // Going from one cluster to another, so save last-focused.
11821                 // This covers cluster jumps because they are always FOCUS_DOWN
11822                 oldFocus.setFocusedInCluster(oldCluster);
11823                 if (!(oldFocus.mParent instanceof ViewGroup)) {
11824                     return;
11825                 }
11826                 if (direction == FOCUS_FORWARD || direction == FOCUS_BACKWARD) {
11827                     // This is a result of ordered navigation so consider navigation through
11828                     // the previous cluster "complete" and clear its last-focused memory.
11829                     ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
11830                 } else if (oldFocus instanceof ViewGroup
11831                         && ((ViewGroup) oldFocus).getDescendantFocusability()
11832                                 == ViewGroup.FOCUS_AFTER_DESCENDANTS
11833                         && ViewRootImpl.isViewDescendantOf(this, oldFocus)) {
11834                     // This means oldFocus is not focusable since it obviously has a focusable
11835                     // child (this). Don't restore focus to it in the future.
11836                     ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
11837                 }
11838             }
11839         }
11840     }
11841 
11842     /**
11843      * Returns whether this View should receive focus when the focus is restored for the view
11844      * hierarchy containing this view.
11845      * <p>
11846      * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
11847      * window or serves as a target of cluster navigation.
11848      *
11849      * @see #restoreDefaultFocus()
11850      *
11851      * @return {@code true} if this view is the default-focus view, {@code false} otherwise
11852      * @attr ref android.R.styleable#View_focusedByDefault
11853      */
11854     @ViewDebug.ExportedProperty(category = "focus")
11855     @InspectableProperty
11856     public final boolean isFocusedByDefault() {
11857         return (mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0;
11858     }
11859 
11860     /**
11861      * Sets whether this View should receive focus when the focus is restored for the view
11862      * hierarchy containing this view.
11863      * <p>
11864      * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
11865      * window or serves as a target of cluster navigation.
11866      *
11867      * @param isFocusedByDefault {@code true} to set this view as the default-focus view,
11868      *                           {@code false} otherwise.
11869      *
11870      * @see #restoreDefaultFocus()
11871      *
11872      * @attr ref android.R.styleable#View_focusedByDefault
11873      */
11874     public void setFocusedByDefault(boolean isFocusedByDefault) {
11875         if (isFocusedByDefault == ((mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0)) {
11876             return;
11877         }
11878 
11879         if (isFocusedByDefault) {
11880             mPrivateFlags3 |= PFLAG3_FOCUSED_BY_DEFAULT;
11881         } else {
11882             mPrivateFlags3 &= ~PFLAG3_FOCUSED_BY_DEFAULT;
11883         }
11884 
11885         if (mParent instanceof ViewGroup) {
11886             if (isFocusedByDefault) {
11887                 ((ViewGroup) mParent).setDefaultFocus(this);
11888             } else {
11889                 ((ViewGroup) mParent).clearDefaultFocus(this);
11890             }
11891         }
11892     }
11893 
11894     /**
11895      * Returns whether the view hierarchy with this view as a root contain a default-focus view.
11896      *
11897      * @return {@code true} if this view has default focus, {@code false} otherwise
11898      */
11899     boolean hasDefaultFocus() {
11900         return isFocusedByDefault();
11901     }
11902 
11903     /**
11904      * Find the nearest keyboard navigation cluster in the specified direction.
11905      * This does not actually give focus to that cluster.
11906      *
11907      * @param currentCluster The starting point of the search. Null means the current cluster is not
11908      *                       found yet
11909      * @param direction Direction to look
11910      *
11911      * @return The nearest keyboard navigation cluster in the specified direction, or null if none
11912      *         can be found
11913      */
11914     public View keyboardNavigationClusterSearch(View currentCluster,
11915             @FocusDirection int direction) {
11916         if (isKeyboardNavigationCluster()) {
11917             currentCluster = this;
11918         }
11919         if (isRootNamespace()) {
11920             // Root namespace means we should consider ourselves the top of the
11921             // tree for group searching; otherwise we could be group searching
11922             // into other tabs.  see LocalActivityManager and TabHost for more info.
11923             return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
11924                     this, currentCluster, direction);
11925         } else if (mParent != null) {
11926             return mParent.keyboardNavigationClusterSearch(currentCluster, direction);
11927         }
11928         return null;
11929     }
11930 
11931     /**
11932      * This method is the last chance for the focused view and its ancestors to
11933      * respond to an arrow key. This is called when the focused view did not
11934      * consume the key internally, nor could the view system find a new view in
11935      * the requested direction to give focus to.
11936      *
11937      * @param focused The currently focused view.
11938      * @param direction The direction focus wants to move. One of FOCUS_UP,
11939      *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
11940      * @return True if the this view consumed this unhandled move.
11941      */
11942     public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
11943         return false;
11944     }
11945 
11946     /**
11947      * Sets whether this View should use a default focus highlight when it gets focused but doesn't
11948      * have {@link android.R.attr#state_focused} defined in its background.
11949      *
11950      * @param defaultFocusHighlightEnabled {@code true} to set this view to use a default focus
11951      *                                      highlight, {@code false} otherwise.
11952      *
11953      * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
11954      */
11955     public void setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled) {
11956         mDefaultFocusHighlightEnabled = defaultFocusHighlightEnabled;
11957     }
11958 
11959     /**
11960 
11961     /**
11962      * Returns whether this View should use a default focus highlight when it gets focused but
11963      * doesn't have {@link android.R.attr#state_focused} defined in its background.
11964      *
11965      * @return True if this View should use a default focus highlight.
11966      * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
11967      */
11968     @ViewDebug.ExportedProperty(category = "focus")
11969     @InspectableProperty
11970     public final boolean getDefaultFocusHighlightEnabled() {
11971         return mDefaultFocusHighlightEnabled;
11972     }
11973 
11974     /**
11975      * If a user manually specified the next view id for a particular direction,
11976      * use the root to look up the view.
11977      * @param root The root view of the hierarchy containing this view.
11978      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
11979      * or FOCUS_BACKWARD.
11980      * @return The user specified next view, or null if there is none.
11981      */
11982     View findUserSetNextFocus(View root, @FocusDirection int direction) {
11983         switch (direction) {
11984             case FOCUS_LEFT:
11985                 if (mNextFocusLeftId == View.NO_ID) return null;
11986                 return findViewInsideOutShouldExist(root, mNextFocusLeftId);
11987             case FOCUS_RIGHT:
11988                 if (mNextFocusRightId == View.NO_ID) return null;
11989                 return findViewInsideOutShouldExist(root, mNextFocusRightId);
11990             case FOCUS_UP:
11991                 if (mNextFocusUpId == View.NO_ID) return null;
11992                 return findViewInsideOutShouldExist(root, mNextFocusUpId);
11993             case FOCUS_DOWN:
11994                 if (mNextFocusDownId == View.NO_ID) return null;
11995                 return findViewInsideOutShouldExist(root, mNextFocusDownId);
11996             case FOCUS_FORWARD:
11997                 if (mNextFocusForwardId == View.NO_ID) return null;
11998                 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
11999             case FOCUS_BACKWARD: {
12000                 if (mID == View.NO_ID) return null;
12001                 final int id = mID;
12002                 return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
12003                     @Override
12004                     public boolean test(View t) {
12005                         return t.mNextFocusForwardId == id;
12006                     }
12007                 });
12008             }
12009         }
12010         return null;
12011     }
12012 
12013     /**
12014      * If a user manually specified the next keyboard-navigation cluster for a particular direction,
12015      * use the root to look up the view.
12016      *
12017      * @param root the root view of the hierarchy containing this view
12018      * @param direction {@link #FOCUS_FORWARD} or {@link #FOCUS_BACKWARD}
12019      * @return the user-specified next cluster, or {@code null} if there is none
12020      */
12021     View findUserSetNextKeyboardNavigationCluster(View root, @FocusDirection int direction) {
12022         switch (direction) {
12023             case FOCUS_FORWARD:
12024                 if (mNextClusterForwardId == View.NO_ID) return null;
12025                 return findViewInsideOutShouldExist(root, mNextClusterForwardId);
12026             case FOCUS_BACKWARD: {
12027                 if (mID == View.NO_ID) return null;
12028                 final int id = mID;
12029                 return root.findViewByPredicateInsideOut(this,
12030                         (Predicate<View>) t -> t.mNextClusterForwardId == id);
12031             }
12032         }
12033         return null;
12034     }
12035 
12036     private View findViewInsideOutShouldExist(View root, int id) {
12037         if (mMatchIdPredicate == null) {
12038             mMatchIdPredicate = new MatchIdPredicate();
12039         }
12040         mMatchIdPredicate.mId = id;
12041         View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
12042         if (result == null) {
12043             Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
12044         }
12045         return result;
12046     }
12047 
12048     /**
12049      * Find and return all focusable views that are descendants of this view,
12050      * possibly including this view if it is focusable itself.
12051      *
12052      * @param direction The direction of the focus
12053      * @return A list of focusable views
12054      */
12055     public ArrayList<View> getFocusables(@FocusDirection int direction) {
12056         ArrayList<View> result = new ArrayList<View>(24);
12057         addFocusables(result, direction);
12058         return result;
12059     }
12060 
12061     /**
12062      * Add any focusable views that are descendants of this view (possibly
12063      * including this view if it is focusable itself) to views.  If we are in touch mode,
12064      * only add views that are also focusable in touch mode.
12065      *
12066      * @param views Focusable views found so far
12067      * @param direction The direction of the focus
12068      */
12069     public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
12070         addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
12071     }
12072 
12073     /**
12074      * Adds any focusable views that are descendants of this view (possibly
12075      * including this view if it is focusable itself) to views. This method
12076      * adds all focusable views regardless if we are in touch mode or
12077      * only views focusable in touch mode if we are in touch mode or
12078      * only views that can take accessibility focus if accessibility is enabled
12079      * depending on the focusable mode parameter.
12080      *
12081      * @param views Focusable views found so far or null if all we are interested is
12082      *        the number of focusables.
12083      * @param direction The direction of the focus.
12084      * @param focusableMode The type of focusables to be added.
12085      *
12086      * @see #FOCUSABLES_ALL
12087      * @see #FOCUSABLES_TOUCH_MODE
12088      */
12089     public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
12090             @FocusableMode int focusableMode) {
12091         if (views == null) {
12092             return;
12093         }
12094         if (!canTakeFocus()) {
12095             return;
12096         }
12097         if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
12098                 && !isFocusableInTouchMode()) {
12099             return;
12100         }
12101         views.add(this);
12102     }
12103 
12104     /**
12105      * Adds any keyboard navigation cluster roots that are descendants of this view (possibly
12106      * including this view if it is a cluster root itself) to views.
12107      *
12108      * @param views Keyboard navigation cluster roots found so far
12109      * @param direction Direction to look
12110      */
12111     public void addKeyboardNavigationClusters(
12112             @NonNull Collection<View> views,
12113             int direction) {
12114         if (!isKeyboardNavigationCluster()) {
12115             return;
12116         }
12117         if (!hasFocusable()) {
12118             return;
12119         }
12120         views.add(this);
12121     }
12122 
12123     /**
12124      * Finds the Views that contain given text. The containment is case insensitive.
12125      * The search is performed by either the text that the View renders or the content
12126      * description that describes the view for accessibility purposes and the view does
12127      * not render or both. Clients can specify how the search is to be performed via
12128      * passing the {@link #FIND_VIEWS_WITH_TEXT} and
12129      * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
12130      *
12131      * @param outViews The output list of matching Views.
12132      * @param searched The text to match against.
12133      *
12134      * @see #FIND_VIEWS_WITH_TEXT
12135      * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
12136      * @see #setContentDescription(CharSequence)
12137      */
12138     public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
12139             @FindViewFlags int flags) {
12140         if (getAccessibilityNodeProvider() != null) {
12141             if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
12142                 outViews.add(this);
12143             }
12144         } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
12145                 && (searched != null && searched.length() > 0)
12146                 && (mContentDescription != null && mContentDescription.length() > 0)) {
12147             String searchedLowerCase = searched.toString().toLowerCase();
12148             String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
12149             if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
12150                 outViews.add(this);
12151             }
12152         }
12153     }
12154 
12155     /**
12156      * Find and return all touchable views that are descendants of this view,
12157      * possibly including this view if it is touchable itself.
12158      *
12159      * @return A list of touchable views
12160      */
12161     public ArrayList<View> getTouchables() {
12162         ArrayList<View> result = new ArrayList<View>();
12163         addTouchables(result);
12164         return result;
12165     }
12166 
12167     /**
12168      * Add any touchable views that are descendants of this view (possibly
12169      * including this view if it is touchable itself) to views.
12170      *
12171      * @param views Touchable views found so far
12172      */
12173     public void addTouchables(ArrayList<View> views) {
12174         final int viewFlags = mViewFlags;
12175 
12176         if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
12177                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
12178                 && (viewFlags & ENABLED_MASK) == ENABLED) {
12179             views.add(this);
12180         }
12181     }
12182 
12183     /**
12184      * Returns whether this View is accessibility focused.
12185      *
12186      * @return True if this View is accessibility focused.
12187      */
12188     @InspectableProperty(hasAttributeId = false)
12189     public boolean isAccessibilityFocused() {
12190         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
12191     }
12192 
12193     /**
12194      * Call this to try to give accessibility focus to this view.
12195      *
12196      * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
12197      * returns false or the view is no visible or the view already has accessibility
12198      * focus.
12199      *
12200      * See also {@link #focusSearch(int)}, which is what you call to say that you
12201      * have focus, and you want your parent to look for the next one.
12202      *
12203      * @return Whether this view actually took accessibility focus.
12204      *
12205      * @hide
12206      */
12207     @UnsupportedAppUsage
12208     public boolean requestAccessibilityFocus() {
12209         AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
12210         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
12211             return false;
12212         }
12213         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
12214             return false;
12215         }
12216         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
12217             mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
12218             ViewRootImpl viewRootImpl = getViewRootImpl();
12219             if (viewRootImpl != null) {
12220                 viewRootImpl.setAccessibilityFocus(this, null);
12221             }
12222             invalidate();
12223             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
12224             return true;
12225         }
12226         return false;
12227     }
12228 
12229     /**
12230      * Call this to try to clear accessibility focus of this view.
12231      *
12232      * See also {@link #focusSearch(int)}, which is what you call to say that you
12233      * have focus, and you want your parent to look for the next one.
12234      *
12235      * @hide
12236      */
12237     @UnsupportedAppUsage
12238     public void clearAccessibilityFocus() {
12239         clearAccessibilityFocusNoCallbacks(0);
12240 
12241         // Clear the global reference of accessibility focus if this view or
12242         // any of its descendants had accessibility focus. This will NOT send
12243         // an event or update internal state if focus is cleared from a
12244         // descendant view, which may leave views in inconsistent states.
12245         final ViewRootImpl viewRootImpl = getViewRootImpl();
12246         if (viewRootImpl != null) {
12247             final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
12248             if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
12249                 viewRootImpl.setAccessibilityFocus(null, null);
12250             }
12251         }
12252     }
12253 
12254     private void sendAccessibilityHoverEvent(int eventType) {
12255         // Since we are not delivering to a client accessibility events from not
12256         // important views (unless the clinet request that) we need to fire the
12257         // event from the deepest view exposed to the client. As a consequence if
12258         // the user crosses a not exposed view the client will see enter and exit
12259         // of the exposed predecessor followed by and enter and exit of that same
12260         // predecessor when entering and exiting the not exposed descendant. This
12261         // is fine since the client has a clear idea which view is hovered at the
12262         // price of a couple more events being sent. This is a simple and
12263         // working solution.
12264         View source = this;
12265         while (true) {
12266             if (source.includeForAccessibility()) {
12267                 source.sendAccessibilityEvent(eventType);
12268                 return;
12269             }
12270             ViewParent parent = source.getParent();
12271             if (parent instanceof View) {
12272                 source = (View) parent;
12273             } else {
12274                 return;
12275             }
12276         }
12277     }
12278 
12279     /**
12280      * Clears accessibility focus without calling any callback methods
12281      * normally invoked in {@link #clearAccessibilityFocus()}. This method
12282      * is used separately from that one for clearing accessibility focus when
12283      * giving this focus to another view.
12284      *
12285      * @param action The action, if any, that led to focus being cleared. Set to
12286      * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
12287      * the window.
12288      */
12289     void clearAccessibilityFocusNoCallbacks(int action) {
12290         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
12291             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
12292             invalidate();
12293             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
12294                 AccessibilityEvent event = AccessibilityEvent.obtain(
12295                         AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
12296                 event.setAction(action);
12297                 if (mAccessibilityDelegate != null) {
12298                     mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
12299                 } else {
12300                     sendAccessibilityEventUnchecked(event);
12301                 }
12302             }
12303         }
12304     }
12305 
12306     /**
12307      * Call this to try to give focus to a specific view or to one of its
12308      * descendants.
12309      *
12310      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
12311      * false), or if it can't be focused due to other conditions (not focusable in touch mode
12312      * ({@link #isFocusableInTouchMode}) while the device is in touch mode, not visible, not
12313      * enabled, or has no size).
12314      *
12315      * See also {@link #focusSearch(int)}, which is what you call to say that you
12316      * have focus, and you want your parent to look for the next one.
12317      *
12318      * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
12319      * {@link #FOCUS_DOWN} and <code>null</code>.
12320      *
12321      * @return Whether this view or one of its descendants actually took focus.
12322      */
12323     public final boolean requestFocus() {
12324         return requestFocus(View.FOCUS_DOWN);
12325     }
12326 
12327     /**
12328      * This will request focus for whichever View was last focused within this
12329      * cluster before a focus-jump out of it.
12330      *
12331      * @hide
12332      */
12333     @TestApi
12334     public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
12335         // Prioritize focusableByDefault over algorithmic focus selection.
12336         if (restoreDefaultFocus()) {
12337             return true;
12338         }
12339         return requestFocus(direction);
12340     }
12341 
12342     /**
12343      * This will request focus for whichever View not in a cluster was last focused before a
12344      * focus-jump to a cluster. If no non-cluster View has previously had focus, this will focus
12345      * the "first" focusable view it finds.
12346      *
12347      * @hide
12348      */
12349     @TestApi
12350     public boolean restoreFocusNotInCluster() {
12351         return requestFocus(View.FOCUS_DOWN);
12352     }
12353 
12354     /**
12355      * Gives focus to the default-focus view in the view hierarchy that has this view as a root.
12356      * If the default-focus view cannot be found, falls back to calling {@link #requestFocus(int)}.
12357      *
12358      * @return Whether this view or one of its descendants actually took focus
12359      */
12360     public boolean restoreDefaultFocus() {
12361         return requestFocus(View.FOCUS_DOWN);
12362     }
12363 
12364     /**
12365      * Call this to try to give focus to a specific view or to one of its
12366      * descendants and give it a hint about what direction focus is heading.
12367      *
12368      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
12369      * false), or if it is focusable and it is not focusable in touch mode
12370      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
12371      *
12372      * See also {@link #focusSearch(int)}, which is what you call to say that you
12373      * have focus, and you want your parent to look for the next one.
12374      *
12375      * This is equivalent to calling {@link #requestFocus(int, Rect)} with
12376      * <code>null</code> set for the previously focused rectangle.
12377      *
12378      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
12379      * @return Whether this view or one of its descendants actually took focus.
12380      */
12381     public final boolean requestFocus(int direction) {
12382         return requestFocus(direction, null);
12383     }
12384 
12385     /**
12386      * Call this to try to give focus to a specific view or to one of its descendants
12387      * and give it hints about the direction and a specific rectangle that the focus
12388      * is coming from.  The rectangle can help give larger views a finer grained hint
12389      * about where focus is coming from, and therefore, where to show selection, or
12390      * forward focus change internally.
12391      *
12392      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
12393      * false), or if it is focusable and it is not focusable in touch mode
12394      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
12395      *
12396      * A View will not take focus if it is not visible.
12397      *
12398      * A View will not take focus if one of its parents has
12399      * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
12400      * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
12401      *
12402      * See also {@link #focusSearch(int)}, which is what you call to say that you
12403      * have focus, and you want your parent to look for the next one.
12404      *
12405      * You may wish to override this method if your custom {@link View} has an internal
12406      * {@link View} that it wishes to forward the request to.
12407      *
12408      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
12409      * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
12410      *        to give a finer grained hint about where focus is coming from.  May be null
12411      *        if there is no hint.
12412      * @return Whether this view or one of its descendants actually took focus.
12413      */
12414     public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
12415         return requestFocusNoSearch(direction, previouslyFocusedRect);
12416     }
12417 
12418     private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
12419         // need to be focusable
12420         if (!canTakeFocus()) {
12421             return false;
12422         }
12423 
12424         // need to be focusable in touch mode if in touch mode
12425         if (isInTouchMode() &&
12426             (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
12427                return false;
12428         }
12429 
12430         // need to not have any parents blocking us
12431         if (hasAncestorThatBlocksDescendantFocus()) {
12432             return false;
12433         }
12434 
12435         if (!isLayoutValid()) {
12436             mPrivateFlags |= PFLAG_WANTS_FOCUS;
12437         } else {
12438             clearParentsWantFocus();
12439         }
12440 
12441         handleFocusGainInternal(direction, previouslyFocusedRect);
12442         return true;
12443     }
12444 
12445     void clearParentsWantFocus() {
12446         if (mParent instanceof View) {
12447             ((View) mParent).mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
12448             ((View) mParent).clearParentsWantFocus();
12449         }
12450     }
12451 
12452     /**
12453      * Call this to try to give focus to a specific view or to one of its descendants. This is a
12454      * special variant of {@link #requestFocus() } that will allow views that are not focusable in
12455      * touch mode to request focus when they are touched.
12456      *
12457      * @return Whether this view or one of its descendants actually took focus.
12458      *
12459      * @see #isInTouchMode()
12460      *
12461      */
12462     public final boolean requestFocusFromTouch() {
12463         // Leave touch mode if we need to
12464         if (isInTouchMode()) {
12465             ViewRootImpl viewRoot = getViewRootImpl();
12466             if (viewRoot != null) {
12467                 viewRoot.ensureTouchMode(false);
12468             }
12469         }
12470         return requestFocus(View.FOCUS_DOWN);
12471     }
12472 
12473     /**
12474      * @return Whether any ancestor of this view blocks descendant focus.
12475      */
12476     private boolean hasAncestorThatBlocksDescendantFocus() {
12477         final boolean focusableInTouchMode = isFocusableInTouchMode();
12478         ViewParent ancestor = mParent;
12479         while (ancestor instanceof ViewGroup) {
12480             final ViewGroup vgAncestor = (ViewGroup) ancestor;
12481             if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
12482                     || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
12483                 return true;
12484             } else {
12485                 ancestor = vgAncestor.getParent();
12486             }
12487         }
12488         return false;
12489     }
12490 
12491     /**
12492      * Gets the mode for determining whether this View is important for accessibility.
12493      * A view is important for accessibility if it fires accessibility events and if it
12494      * is reported to accessibility services that query the screen.
12495      *
12496      * @return The mode for determining whether a view is important for accessibility, one
12497      * of {@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, {@link #IMPORTANT_FOR_ACCESSIBILITY_YES},
12498      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO}, or
12499      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}.
12500      *
12501      * @attr ref android.R.styleable#View_importantForAccessibility
12502      *
12503      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
12504      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
12505      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
12506      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
12507      */
12508     @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
12509             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
12510             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
12511             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
12512             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
12513                     to = "noHideDescendants")
12514         })
12515     @InspectableProperty(enumMapping = {
12516             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_AUTO, name = "auto"),
12517             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_YES, name = "yes"),
12518             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_NO, name = "no"),
12519             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
12520                     name = "noHideDescendants"),
12521     })
12522     public int getImportantForAccessibility() {
12523         return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
12524                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
12525     }
12526 
12527     /**
12528      * Sets the live region mode for this view. This indicates to accessibility
12529      * services whether they should automatically notify the user about changes
12530      * to the view's content description or text, or to the content descriptions
12531      * or text of the view's children (where applicable).
12532      * <p>
12533      * For example, in a login screen with a TextView that displays an "incorrect
12534      * password" notification, that view should be marked as a live region with
12535      * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
12536      * <p>
12537      * To disable change notifications for this view, use
12538      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
12539      * mode for most views.
12540      * <p>
12541      * To indicate that the user should be notified of changes, use
12542      * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
12543      * <p>
12544      * If the view's changes should interrupt ongoing speech and notify the user
12545      * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
12546      *
12547      * @param mode The live region mode for this view, one of:
12548      *        <ul>
12549      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
12550      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
12551      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
12552      *        </ul>
12553      * @attr ref android.R.styleable#View_accessibilityLiveRegion
12554      */
12555     public void setAccessibilityLiveRegion(int mode) {
12556         if (mode != getAccessibilityLiveRegion()) {
12557             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
12558             mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
12559                     & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
12560             notifyViewAccessibilityStateChangedIfNeeded(
12561                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
12562         }
12563     }
12564 
12565     /**
12566      * Gets the live region mode for this View.
12567      *
12568      * @return The live region mode for the view.
12569      *
12570      * @attr ref android.R.styleable#View_accessibilityLiveRegion
12571      *
12572      * @see #setAccessibilityLiveRegion(int)
12573      */
12574     @InspectableProperty(enumMapping = {
12575             @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_NONE, name = "none"),
12576             @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_POLITE, name = "polite"),
12577             @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_ASSERTIVE, name = "assertive")
12578     })
12579     public int getAccessibilityLiveRegion() {
12580         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
12581                 >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
12582     }
12583 
12584     /**
12585      * Sets how to determine whether this view is important for accessibility
12586      * which is if it fires accessibility events and if it is reported to
12587      * accessibility services that query the screen.
12588      *
12589      * @param mode How to determine whether this view is important for accessibility.
12590      *
12591      * @attr ref android.R.styleable#View_importantForAccessibility
12592      *
12593      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
12594      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
12595      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
12596      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
12597      */
12598     public void setImportantForAccessibility(int mode) {
12599         final int oldMode = getImportantForAccessibility();
12600         if (mode != oldMode) {
12601             final boolean hideDescendants =
12602                     mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
12603 
12604             // If this node or its descendants are no longer important, try to
12605             // clear accessibility focus.
12606             if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
12607                 final View focusHost = findAccessibilityFocusHost(hideDescendants);
12608                 if (focusHost != null) {
12609                     focusHost.clearAccessibilityFocus();
12610                 }
12611             }
12612 
12613             // If we're moving between AUTO and another state, we might not need
12614             // to send a subtree changed notification. We'll store the computed
12615             // importance, since we'll need to check it later to make sure.
12616             final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
12617                     || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
12618             final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
12619             mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
12620             mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
12621                     & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
12622             if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
12623                 notifySubtreeAccessibilityStateChangedIfNeeded();
12624             } else {
12625                 notifyViewAccessibilityStateChangedIfNeeded(
12626                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
12627             }
12628         }
12629     }
12630 
12631     /**
12632      * Returns the view within this view's hierarchy that is hosting
12633      * accessibility focus.
12634      *
12635      * @param searchDescendants whether to search for focus in descendant views
12636      * @return the view hosting accessibility focus, or {@code null}
12637      */
12638     private View findAccessibilityFocusHost(boolean searchDescendants) {
12639         if (isAccessibilityFocusedViewOrHost()) {
12640             return this;
12641         }
12642 
12643         if (searchDescendants) {
12644             final ViewRootImpl viewRoot = getViewRootImpl();
12645             if (viewRoot != null) {
12646                 final View focusHost = viewRoot.getAccessibilityFocusedHost();
12647                 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
12648                     return focusHost;
12649                 }
12650             }
12651         }
12652 
12653         return null;
12654     }
12655 
12656     /**
12657      * Computes whether this view should be exposed for accessibility. In
12658      * general, views that are interactive or provide information are exposed
12659      * while views that serve only as containers are hidden.
12660      * <p>
12661      * If an ancestor of this view has importance
12662      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
12663      * returns <code>false</code>.
12664      * <p>
12665      * Otherwise, the value is computed according to the view's
12666      * {@link #getImportantForAccessibility()} value:
12667      * <ol>
12668      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
12669      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
12670      * </code>
12671      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
12672      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
12673      * view satisfies any of the following:
12674      * <ul>
12675      * <li>Is actionable, e.g. {@link #isClickable()},
12676      * {@link #isLongClickable()}, or {@link #isFocusable()}
12677      * <li>Has an {@link AccessibilityDelegate}
12678      * <li>Has an interaction listener, e.g. {@link OnTouchListener},
12679      * {@link OnKeyListener}, etc.
12680      * <li>Is an accessibility live region, e.g.
12681      * {@link #getAccessibilityLiveRegion()} is not
12682      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
12683      * </ul>
12684      * <li>Has an accessibility pane title, see {@link #setAccessibilityPaneTitle}</li>
12685      * </ol>
12686      *
12687      * @return Whether the view is exposed for accessibility.
12688      * @see #setImportantForAccessibility(int)
12689      * @see #getImportantForAccessibility()
12690      */
12691     public boolean isImportantForAccessibility() {
12692         final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
12693                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
12694         if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
12695                 || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
12696             return false;
12697         }
12698 
12699         // Check parent mode to ensure we're not hidden.
12700         ViewParent parent = mParent;
12701         while (parent instanceof View) {
12702             if (((View) parent).getImportantForAccessibility()
12703                     == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
12704                 return false;
12705             }
12706             parent = parent.getParent();
12707         }
12708 
12709         return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
12710                 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
12711                 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE
12712                 || isAccessibilityPane();
12713     }
12714 
12715     /**
12716      * Gets the parent for accessibility purposes. Note that the parent for
12717      * accessibility is not necessary the immediate parent. It is the first
12718      * predecessor that is important for accessibility.
12719      *
12720      * @return The parent for accessibility purposes.
12721      */
12722     public ViewParent getParentForAccessibility() {
12723         if (mParent instanceof View) {
12724             View parentView = (View) mParent;
12725             if (parentView.includeForAccessibility()) {
12726                 return mParent;
12727             } else {
12728                 return mParent.getParentForAccessibility();
12729             }
12730         }
12731         return null;
12732     }
12733 
12734     /** @hide */
12735     View getSelfOrParentImportantForA11y() {
12736         if (isImportantForAccessibility()) return this;
12737         ViewParent parent = getParentForAccessibility();
12738         if (parent instanceof View) return (View) parent;
12739         return null;
12740     }
12741 
12742     /**
12743      * Adds the children of this View relevant for accessibility to the given list
12744      * as output. Since some Views are not important for accessibility the added
12745      * child views are not necessarily direct children of this view, rather they are
12746      * the first level of descendants important for accessibility.
12747      *
12748      * @param outChildren The output list that will receive children for accessibility.
12749      */
12750     public void addChildrenForAccessibility(ArrayList<View> outChildren) {
12751 
12752     }
12753 
12754     /**
12755      * Whether to regard this view for accessibility. A view is regarded for
12756      * accessibility if it is important for accessibility or the querying
12757      * accessibility service has explicitly requested that view not
12758      * important for accessibility are regarded.
12759      *
12760      * @return Whether to regard the view for accessibility.
12761      *
12762      * @hide
12763      */
12764     @UnsupportedAppUsage
12765     public boolean includeForAccessibility() {
12766         if (mAttachInfo != null) {
12767             return (mAttachInfo.mAccessibilityFetchFlags
12768                     & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
12769                     || isImportantForAccessibility();
12770         }
12771         return false;
12772     }
12773 
12774     /**
12775      * Returns whether the View is considered actionable from
12776      * accessibility perspective. Such view are important for
12777      * accessibility.
12778      *
12779      * @return True if the view is actionable for accessibility.
12780      *
12781      * @hide
12782      */
12783     public boolean isActionableForAccessibility() {
12784         return (isClickable() || isLongClickable() || isFocusable());
12785     }
12786 
12787     /**
12788      * Returns whether the View has registered callbacks which makes it
12789      * important for accessibility.
12790      *
12791      * @return True if the view is actionable for accessibility.
12792      */
12793     private boolean hasListenersForAccessibility() {
12794         ListenerInfo info = getListenerInfo();
12795         return mTouchDelegate != null || info.mOnKeyListener != null
12796                 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
12797                 || info.mOnHoverListener != null || info.mOnDragListener != null;
12798     }
12799 
12800     /**
12801      * Notifies that the accessibility state of this view changed. The change
12802      * is local to this view and does not represent structural changes such
12803      * as children and parent. For example, the view became focusable. The
12804      * notification is at at most once every
12805      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
12806      * to avoid unnecessary load to the system. Also once a view has a pending
12807      * notification this method is a NOP until the notification has been sent.
12808      *
12809      * @hide
12810      */
12811     @UnsupportedAppUsage
12812     public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
12813         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
12814             return;
12815         }
12816 
12817         // Changes to views with a pane title count as window state changes, as the pane title
12818         // marks them as significant parts of the UI.
12819         if ((changeType != AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE)
12820                 && isAccessibilityPane()) {
12821             // If the pane isn't visible, content changed events are sufficient unless we're
12822             // reporting that the view just disappeared
12823             if ((getVisibility() == VISIBLE)
12824                     || (changeType == AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED)) {
12825                 final AccessibilityEvent event = AccessibilityEvent.obtain();
12826                 onInitializeAccessibilityEvent(event);
12827                 event.setEventType(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
12828                 event.setContentChangeTypes(changeType);
12829                 event.setSource(this);
12830                 onPopulateAccessibilityEvent(event);
12831                 if (mParent != null) {
12832                     try {
12833                         mParent.requestSendAccessibilityEvent(this, event);
12834                     } catch (AbstractMethodError e) {
12835                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName()
12836                                 + " does not fully implement ViewParent", e);
12837                     }
12838                 }
12839                 return;
12840             }
12841         }
12842 
12843         // If this is a live region, we should send a subtree change event
12844         // from this view immediately. Otherwise, we can let it propagate up.
12845         if (getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE) {
12846             final AccessibilityEvent event = AccessibilityEvent.obtain();
12847             event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
12848             event.setContentChangeTypes(changeType);
12849             sendAccessibilityEventUnchecked(event);
12850         } else if (mParent != null) {
12851             try {
12852                 mParent.notifySubtreeAccessibilityStateChanged(this, this, changeType);
12853             } catch (AbstractMethodError e) {
12854                 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
12855                         " does not fully implement ViewParent", e);
12856             }
12857         }
12858     }
12859 
12860     /**
12861      * Notifies that the accessibility state of this view changed. The change
12862      * is *not* local to this view and does represent structural changes such
12863      * as children and parent. For example, the view size changed. The
12864      * notification is at at most once every
12865      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
12866      * to avoid unnecessary load to the system. Also once a view has a pending
12867      * notification this method is a NOP until the notification has been sent.
12868      *
12869      * @hide
12870      */
12871     @UnsupportedAppUsage
12872     public void notifySubtreeAccessibilityStateChangedIfNeeded() {
12873         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
12874             return;
12875         }
12876 
12877         if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
12878             mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
12879             if (mParent != null) {
12880                 try {
12881                     mParent.notifySubtreeAccessibilityStateChanged(
12882                             this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
12883                 } catch (AbstractMethodError e) {
12884                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
12885                             " does not fully implement ViewParent", e);
12886                 }
12887             }
12888         }
12889     }
12890 
12891     /**
12892      * Changes the visibility of this View without triggering any other changes. This should only
12893      * be used by animation frameworks, such as {@link android.transition.Transition}, where
12894      * visibility changes should not adjust focus or trigger a new layout. Application developers
12895      * should use {@link #setVisibility} instead to ensure that the hierarchy is correctly updated.
12896      *
12897      * <p>Only call this method when a temporary visibility must be applied during an
12898      * animation and the original visibility value is guaranteed to be reset after the
12899      * animation completes. Use {@link #setVisibility} in all other cases.</p>
12900      *
12901      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
12902      * @see #setVisibility(int)
12903      */
12904     public void setTransitionVisibility(@Visibility int visibility) {
12905         mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
12906     }
12907 
12908     /**
12909      * Reset the flag indicating the accessibility state of the subtree rooted
12910      * at this view changed.
12911      */
12912     void resetSubtreeAccessibilityStateChanged() {
12913         mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
12914     }
12915 
12916     /**
12917      * Report an accessibility action to this view's parents for delegated processing.
12918      *
12919      * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
12920      * call this method to delegate an accessibility action to a supporting parent. If the parent
12921      * returns true from its
12922      * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
12923      * method this method will return true to signify that the action was consumed.</p>
12924      *
12925      * <p>This method is useful for implementing nested scrolling child views. If
12926      * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
12927      * a custom view implementation may invoke this method to allow a parent to consume the
12928      * scroll first. If this method returns true the custom view should skip its own scrolling
12929      * behavior.</p>
12930      *
12931      * @param action Accessibility action to delegate
12932      * @param arguments Optional action arguments
12933      * @return true if the action was consumed by a parent
12934      */
12935     public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
12936         for (ViewParent p = getParent(); p != null; p = p.getParent()) {
12937             if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
12938                 return true;
12939             }
12940         }
12941         return false;
12942     }
12943 
12944     /**
12945      * Performs the specified accessibility action on the view. For
12946      * possible accessibility actions look at {@link AccessibilityNodeInfo}.
12947      * <p>
12948      * If an {@link AccessibilityDelegate} has been specified via calling
12949      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
12950      * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
12951      * is responsible for handling this call.
12952      * </p>
12953      *
12954      * <p>The default implementation will delegate
12955      * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
12956      * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
12957      * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
12958      *
12959      * @param action The action to perform.
12960      * @param arguments Optional action arguments.
12961      * @return Whether the action was performed.
12962      */
12963     public boolean performAccessibilityAction(int action, Bundle arguments) {
12964       if (mAccessibilityDelegate != null) {
12965           return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
12966       } else {
12967           return performAccessibilityActionInternal(action, arguments);
12968       }
12969     }
12970 
12971    /**
12972     * @see #performAccessibilityAction(int, Bundle)
12973     *
12974     * Note: Called from the default {@link AccessibilityDelegate}.
12975     *
12976     * @hide
12977     */
12978     @UnsupportedAppUsage
12979     public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
12980         if (isNestedScrollingEnabled()
12981                 && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
12982                 || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
12983                 || action == R.id.accessibilityActionScrollUp
12984                 || action == R.id.accessibilityActionScrollLeft
12985                 || action == R.id.accessibilityActionScrollDown
12986                 || action == R.id.accessibilityActionScrollRight)) {
12987             if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
12988                 return true;
12989             }
12990         }
12991 
12992         switch (action) {
12993             case AccessibilityNodeInfo.ACTION_CLICK: {
12994                 if (isClickable()) {
12995                     performClickInternal();
12996                     return true;
12997                 }
12998             } break;
12999             case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
13000                 if (isLongClickable()) {
13001                     performLongClick();
13002                     return true;
13003                 }
13004             } break;
13005             case AccessibilityNodeInfo.ACTION_FOCUS: {
13006                 if (!hasFocus()) {
13007                     // Get out of touch mode since accessibility
13008                     // wants to move focus around.
13009                     getViewRootImpl().ensureTouchMode(false);
13010                     return requestFocus();
13011                 }
13012             } break;
13013             case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
13014                 if (hasFocus()) {
13015                     clearFocus();
13016                     return !isFocused();
13017                 }
13018             } break;
13019             case AccessibilityNodeInfo.ACTION_SELECT: {
13020                 if (!isSelected()) {
13021                     setSelected(true);
13022                     return isSelected();
13023                 }
13024             } break;
13025             case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
13026                 if (isSelected()) {
13027                     setSelected(false);
13028                     return !isSelected();
13029                 }
13030             } break;
13031             case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
13032                 if (!isAccessibilityFocused()) {
13033                     return requestAccessibilityFocus();
13034                 }
13035             } break;
13036             case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
13037                 if (isAccessibilityFocused()) {
13038                     clearAccessibilityFocus();
13039                     return true;
13040                 }
13041             } break;
13042             case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
13043                 if (arguments != null) {
13044                     final int granularity = arguments.getInt(
13045                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
13046                     final boolean extendSelection = arguments.getBoolean(
13047                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
13048                     return traverseAtGranularity(granularity, true, extendSelection);
13049                 }
13050             } break;
13051             case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
13052                 if (arguments != null) {
13053                     final int granularity = arguments.getInt(
13054                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
13055                     final boolean extendSelection = arguments.getBoolean(
13056                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
13057                     return traverseAtGranularity(granularity, false, extendSelection);
13058                 }
13059             } break;
13060             case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
13061                 CharSequence text = getIterableTextForAccessibility();
13062                 if (text == null) {
13063                     return false;
13064                 }
13065                 final int start = (arguments != null) ? arguments.getInt(
13066                         AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
13067                 final int end = (arguments != null) ? arguments.getInt(
13068                 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
13069                 // Only cursor position can be specified (selection length == 0)
13070                 if ((getAccessibilitySelectionStart() != start
13071                         || getAccessibilitySelectionEnd() != end)
13072                         && (start == end)) {
13073                     setAccessibilitySelection(start, end);
13074                     notifyViewAccessibilityStateChangedIfNeeded(
13075                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
13076                     return true;
13077                 }
13078             } break;
13079             case R.id.accessibilityActionShowOnScreen: {
13080                 if (mAttachInfo != null) {
13081                     final Rect r = mAttachInfo.mTmpInvalRect;
13082                     getDrawingRect(r);
13083                     return requestRectangleOnScreen(r, true);
13084                 }
13085             } break;
13086             case R.id.accessibilityActionContextClick: {
13087                 if (isContextClickable()) {
13088                     performContextClick();
13089                     return true;
13090                 }
13091             } break;
13092             case R.id.accessibilityActionShowTooltip: {
13093                 if ((mTooltipInfo != null) && (mTooltipInfo.mTooltipPopup != null)) {
13094                     // Tooltip already showing
13095                     return false;
13096                 }
13097                 return showLongClickTooltip(0, 0);
13098             }
13099             case R.id.accessibilityActionHideTooltip: {
13100                 if ((mTooltipInfo == null) || (mTooltipInfo.mTooltipPopup == null)) {
13101                     // No tooltip showing
13102                     return false;
13103                 }
13104                 hideTooltip();
13105                 return true;
13106             }
13107         }
13108         return false;
13109     }
13110 
13111     private boolean traverseAtGranularity(int granularity, boolean forward,
13112             boolean extendSelection) {
13113         CharSequence text = getIterableTextForAccessibility();
13114         if (text == null || text.length() == 0) {
13115             return false;
13116         }
13117         TextSegmentIterator iterator = getIteratorForGranularity(granularity);
13118         if (iterator == null) {
13119             return false;
13120         }
13121         int current = getAccessibilitySelectionEnd();
13122         if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
13123             current = forward ? 0 : text.length();
13124         }
13125         final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
13126         if (range == null) {
13127             return false;
13128         }
13129         final int segmentStart = range[0];
13130         final int segmentEnd = range[1];
13131         int selectionStart;
13132         int selectionEnd;
13133         if (extendSelection && isAccessibilitySelectionExtendable()) {
13134             selectionStart = getAccessibilitySelectionStart();
13135             if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
13136                 selectionStart = forward ? segmentStart : segmentEnd;
13137             }
13138             selectionEnd = forward ? segmentEnd : segmentStart;
13139         } else {
13140             selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
13141         }
13142         setAccessibilitySelection(selectionStart, selectionEnd);
13143         final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
13144                 : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
13145         sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
13146         return true;
13147     }
13148 
13149     /**
13150      * Gets the text reported for accessibility purposes.
13151      *
13152      * @return The accessibility text.
13153      *
13154      * @hide
13155      */
13156     @UnsupportedAppUsage
13157     public CharSequence getIterableTextForAccessibility() {
13158         return getContentDescription();
13159     }
13160 
13161     /**
13162      * Gets whether accessibility selection can be extended.
13163      *
13164      * @return If selection is extensible.
13165      *
13166      * @hide
13167      */
13168     public boolean isAccessibilitySelectionExtendable() {
13169         return false;
13170     }
13171 
13172     /**
13173      * @hide
13174      */
13175     public int getAccessibilitySelectionStart() {
13176         return mAccessibilityCursorPosition;
13177     }
13178 
13179     /**
13180      * @hide
13181      */
13182     public int getAccessibilitySelectionEnd() {
13183         return getAccessibilitySelectionStart();
13184     }
13185 
13186     /**
13187      * @hide
13188      */
13189     public void setAccessibilitySelection(int start, int end) {
13190         if (start ==  end && end == mAccessibilityCursorPosition) {
13191             return;
13192         }
13193         if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
13194             mAccessibilityCursorPosition = start;
13195         } else {
13196             mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
13197         }
13198         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
13199     }
13200 
13201     private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
13202             int fromIndex, int toIndex) {
13203         if (mParent == null) {
13204             return;
13205         }
13206         AccessibilityEvent event = AccessibilityEvent.obtain(
13207                 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
13208         onInitializeAccessibilityEvent(event);
13209         onPopulateAccessibilityEvent(event);
13210         event.setFromIndex(fromIndex);
13211         event.setToIndex(toIndex);
13212         event.setAction(action);
13213         event.setMovementGranularity(granularity);
13214         mParent.requestSendAccessibilityEvent(this, event);
13215     }
13216 
13217     /**
13218      * @hide
13219      */
13220     @UnsupportedAppUsage
13221     public TextSegmentIterator getIteratorForGranularity(int granularity) {
13222         switch (granularity) {
13223             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
13224                 CharSequence text = getIterableTextForAccessibility();
13225                 if (text != null && text.length() > 0) {
13226                     CharacterTextSegmentIterator iterator =
13227                         CharacterTextSegmentIterator.getInstance(
13228                                 mContext.getResources().getConfiguration().locale);
13229                     iterator.initialize(text.toString());
13230                     return iterator;
13231                 }
13232             } break;
13233             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
13234                 CharSequence text = getIterableTextForAccessibility();
13235                 if (text != null && text.length() > 0) {
13236                     WordTextSegmentIterator iterator =
13237                         WordTextSegmentIterator.getInstance(
13238                                 mContext.getResources().getConfiguration().locale);
13239                     iterator.initialize(text.toString());
13240                     return iterator;
13241                 }
13242             } break;
13243             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
13244                 CharSequence text = getIterableTextForAccessibility();
13245                 if (text != null && text.length() > 0) {
13246                     ParagraphTextSegmentIterator iterator =
13247                         ParagraphTextSegmentIterator.getInstance();
13248                     iterator.initialize(text.toString());
13249                     return iterator;
13250                 }
13251             } break;
13252         }
13253         return null;
13254     }
13255 
13256     /**
13257      * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
13258      * and {@link #onFinishTemporaryDetach()}.
13259      *
13260      * <p>This method always returns {@code true} when called directly or indirectly from
13261      * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
13262      * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
13263      * <ul>
13264      *     <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
13265      *     <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
13266      * </ul>
13267      * </p>
13268      *
13269      * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
13270      * and {@link #onFinishTemporaryDetach()}.
13271      */
isTemporarilyDetached()13272     public final boolean isTemporarilyDetached() {
13273         return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
13274     }
13275 
13276     /**
13277      * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
13278      * a container View.
13279      */
13280     @CallSuper
dispatchStartTemporaryDetach()13281     public void dispatchStartTemporaryDetach() {
13282         mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
13283         notifyEnterOrExitForAutoFillIfNeeded(false);
13284         onStartTemporaryDetach();
13285     }
13286 
13287     /**
13288      * This is called when a container is going to temporarily detach a child, with
13289      * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
13290      * It will either be followed by {@link #onFinishTemporaryDetach()} or
13291      * {@link #onDetachedFromWindow()} when the container is done.
13292      */
onStartTemporaryDetach()13293     public void onStartTemporaryDetach() {
13294         removeUnsetPressCallback();
13295         mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
13296     }
13297 
13298     /**
13299      * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
13300      * a container View.
13301      */
13302     @CallSuper
dispatchFinishTemporaryDetach()13303     public void dispatchFinishTemporaryDetach() {
13304         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
13305         onFinishTemporaryDetach();
13306         if (hasWindowFocus() && hasFocus()) {
13307             notifyFocusChangeToInputMethodManager(true /* hasFocus */);
13308         }
13309         notifyEnterOrExitForAutoFillIfNeeded(true);
13310     }
13311 
13312     /**
13313      * Called after {@link #onStartTemporaryDetach} when the container is done
13314      * changing the view.
13315      */
onFinishTemporaryDetach()13316     public void onFinishTemporaryDetach() {
13317     }
13318 
13319     /**
13320      * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
13321      * for this view's window.  Returns null if the view is not currently attached
13322      * to the window.  Normally you will not need to use this directly, but
13323      * just use the standard high-level event callbacks like
13324      * {@link #onKeyDown(int, KeyEvent)}.
13325      */
getKeyDispatcherState()13326     public KeyEvent.DispatcherState getKeyDispatcherState() {
13327         return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
13328     }
13329 
13330     /**
13331      * Dispatch a key event before it is processed by any input method
13332      * associated with the view hierarchy.  This can be used to intercept
13333      * key events in special situations before the IME consumes them; a
13334      * typical example would be handling the BACK key to update the application's
13335      * UI instead of allowing the IME to see it and close itself.
13336      *
13337      * @param event The key event to be dispatched.
13338      * @return True if the event was handled, false otherwise.
13339      */
dispatchKeyEventPreIme(KeyEvent event)13340     public boolean dispatchKeyEventPreIme(KeyEvent event) {
13341         return onKeyPreIme(event.getKeyCode(), event);
13342     }
13343 
13344     /**
13345      * Dispatch a key event to the next view on the focus path. This path runs
13346      * from the top of the view tree down to the currently focused view. If this
13347      * view has focus, it will dispatch to itself. Otherwise it will dispatch
13348      * the next node down the focus path. This method also fires any key
13349      * listeners.
13350      *
13351      * @param event The key event to be dispatched.
13352      * @return True if the event was handled, false otherwise.
13353      */
dispatchKeyEvent(KeyEvent event)13354     public boolean dispatchKeyEvent(KeyEvent event) {
13355         if (mInputEventConsistencyVerifier != null) {
13356             mInputEventConsistencyVerifier.onKeyEvent(event, 0);
13357         }
13358 
13359         // Give any attached key listener a first crack at the event.
13360         //noinspection SimplifiableIfStatement
13361         ListenerInfo li = mListenerInfo;
13362         if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
13363                 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
13364             return true;
13365         }
13366 
13367         if (event.dispatch(this, mAttachInfo != null
13368                 ? mAttachInfo.mKeyDispatchState : null, this)) {
13369             return true;
13370         }
13371 
13372         if (mInputEventConsistencyVerifier != null) {
13373             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
13374         }
13375         return false;
13376     }
13377 
13378     /**
13379      * Dispatches a key shortcut event.
13380      *
13381      * @param event The key event to be dispatched.
13382      * @return True if the event was handled by the view, false otherwise.
13383      */
dispatchKeyShortcutEvent(KeyEvent event)13384     public boolean dispatchKeyShortcutEvent(KeyEvent event) {
13385         return onKeyShortcut(event.getKeyCode(), event);
13386     }
13387 
13388     /**
13389      * Pass the touch screen motion event down to the target view, or this
13390      * view if it is the target.
13391      *
13392      * @param event The motion event to be dispatched.
13393      * @return True if the event was handled by the view, false otherwise.
13394      */
dispatchTouchEvent(MotionEvent event)13395     public boolean dispatchTouchEvent(MotionEvent event) {
13396         // If the event should be handled by accessibility focus first.
13397         if (event.isTargetAccessibilityFocus()) {
13398             // We don't have focus or no virtual descendant has it, do not handle the event.
13399             if (!isAccessibilityFocusedViewOrHost()) {
13400                 return false;
13401             }
13402             // We have focus and got the event, then use normal event dispatch.
13403             event.setTargetAccessibilityFocus(false);
13404         }
13405 
13406         boolean result = false;
13407 
13408         if (mInputEventConsistencyVerifier != null) {
13409             mInputEventConsistencyVerifier.onTouchEvent(event, 0);
13410         }
13411 
13412         final int actionMasked = event.getActionMasked();
13413         if (actionMasked == MotionEvent.ACTION_DOWN) {
13414             // Defensive cleanup for new gesture
13415             stopNestedScroll();
13416         }
13417 
13418         if (onFilterTouchEventForSecurity(event)) {
13419             if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
13420                 result = true;
13421             }
13422             //noinspection SimplifiableIfStatement
13423             ListenerInfo li = mListenerInfo;
13424             if (li != null && li.mOnTouchListener != null
13425                     && (mViewFlags & ENABLED_MASK) == ENABLED
13426                     && li.mOnTouchListener.onTouch(this, event)) {
13427                 result = true;
13428             }
13429 
13430             if (!result && onTouchEvent(event)) {
13431                 result = true;
13432             }
13433         }
13434 
13435         if (!result && mInputEventConsistencyVerifier != null) {
13436             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
13437         }
13438 
13439         // Clean up after nested scrolls if this is the end of a gesture;
13440         // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
13441         // of the gesture.
13442         if (actionMasked == MotionEvent.ACTION_UP ||
13443                 actionMasked == MotionEvent.ACTION_CANCEL ||
13444                 (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
13445             stopNestedScroll();
13446         }
13447 
13448         return result;
13449     }
13450 
isAccessibilityFocusedViewOrHost()13451     boolean isAccessibilityFocusedViewOrHost() {
13452         return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
13453                 .getAccessibilityFocusedHost() == this);
13454     }
13455 
13456     /**
13457      * Returns whether this view can receive pointer events.
13458      *
13459      * @return {@code true} if this view can receive pointer events.
13460      * @hide
13461      */
canReceivePointerEvents()13462     protected boolean canReceivePointerEvents() {
13463         return (mViewFlags & VISIBILITY_MASK) == VISIBLE || getAnimation() != null;
13464     }
13465 
13466     /**
13467      * Filter the touch event to apply security policies.
13468      *
13469      * @param event The motion event to be filtered.
13470      * @return True if the event should be dispatched, false if the event should be dropped.
13471      *
13472      * @see #getFilterTouchesWhenObscured
13473      */
onFilterTouchEventForSecurity(MotionEvent event)13474     public boolean onFilterTouchEventForSecurity(MotionEvent event) {
13475         //noinspection RedundantIfStatement
13476         if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
13477                 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
13478             // Window is obscured, drop this touch.
13479             return false;
13480         }
13481         return true;
13482     }
13483 
13484     /**
13485      * Pass a trackball motion event down to the focused view.
13486      *
13487      * @param event The motion event to be dispatched.
13488      * @return True if the event was handled by the view, false otherwise.
13489      */
dispatchTrackballEvent(MotionEvent event)13490     public boolean dispatchTrackballEvent(MotionEvent event) {
13491         if (mInputEventConsistencyVerifier != null) {
13492             mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
13493         }
13494 
13495         return onTrackballEvent(event);
13496     }
13497 
13498     /**
13499      * Pass a captured pointer event down to the focused view.
13500      *
13501      * @param event The motion event to be dispatched.
13502      * @return True if the event was handled by the view, false otherwise.
13503      */
dispatchCapturedPointerEvent(MotionEvent event)13504     public boolean dispatchCapturedPointerEvent(MotionEvent event) {
13505         if (!hasPointerCapture()) {
13506             return false;
13507         }
13508         //noinspection SimplifiableIfStatement
13509         ListenerInfo li = mListenerInfo;
13510         if (li != null && li.mOnCapturedPointerListener != null
13511                 && li.mOnCapturedPointerListener.onCapturedPointer(this, event)) {
13512             return true;
13513         }
13514         return onCapturedPointerEvent(event);
13515     }
13516 
13517     /**
13518      * Dispatch a generic motion event.
13519      * <p>
13520      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
13521      * are delivered to the view under the pointer.  All other generic motion events are
13522      * delivered to the focused view.  Hover events are handled specially and are delivered
13523      * to {@link #onHoverEvent(MotionEvent)}.
13524      * </p>
13525      *
13526      * @param event The motion event to be dispatched.
13527      * @return True if the event was handled by the view, false otherwise.
13528      */
dispatchGenericMotionEvent(MotionEvent event)13529     public boolean dispatchGenericMotionEvent(MotionEvent event) {
13530         if (mInputEventConsistencyVerifier != null) {
13531             mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
13532         }
13533 
13534         final int source = event.getSource();
13535         if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
13536             final int action = event.getAction();
13537             if (action == MotionEvent.ACTION_HOVER_ENTER
13538                     || action == MotionEvent.ACTION_HOVER_MOVE
13539                     || action == MotionEvent.ACTION_HOVER_EXIT) {
13540                 if (dispatchHoverEvent(event)) {
13541                     return true;
13542                 }
13543             } else if (dispatchGenericPointerEvent(event)) {
13544                 return true;
13545             }
13546         } else if (dispatchGenericFocusedEvent(event)) {
13547             return true;
13548         }
13549 
13550         if (dispatchGenericMotionEventInternal(event)) {
13551             return true;
13552         }
13553 
13554         if (mInputEventConsistencyVerifier != null) {
13555             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
13556         }
13557         return false;
13558     }
13559 
dispatchGenericMotionEventInternal(MotionEvent event)13560     private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
13561         //noinspection SimplifiableIfStatement
13562         ListenerInfo li = mListenerInfo;
13563         if (li != null && li.mOnGenericMotionListener != null
13564                 && (mViewFlags & ENABLED_MASK) == ENABLED
13565                 && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
13566             return true;
13567         }
13568 
13569         if (onGenericMotionEvent(event)) {
13570             return true;
13571         }
13572 
13573         final int actionButton = event.getActionButton();
13574         switch (event.getActionMasked()) {
13575             case MotionEvent.ACTION_BUTTON_PRESS:
13576                 if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
13577                         && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
13578                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
13579                     if (performContextClick(event.getX(), event.getY())) {
13580                         mInContextButtonPress = true;
13581                         setPressed(true, event.getX(), event.getY());
13582                         removeTapCallback();
13583                         removeLongPressCallback();
13584                         return true;
13585                     }
13586                 }
13587                 break;
13588 
13589             case MotionEvent.ACTION_BUTTON_RELEASE:
13590                 if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
13591                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
13592                     mInContextButtonPress = false;
13593                     mIgnoreNextUpEvent = true;
13594                 }
13595                 break;
13596         }
13597 
13598         if (mInputEventConsistencyVerifier != null) {
13599             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
13600         }
13601         return false;
13602     }
13603 
13604     /**
13605      * Dispatch a hover event.
13606      * <p>
13607      * Do not call this method directly.
13608      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
13609      * </p>
13610      *
13611      * @param event The motion event to be dispatched.
13612      * @return True if the event was handled by the view, false otherwise.
13613      */
dispatchHoverEvent(MotionEvent event)13614     protected boolean dispatchHoverEvent(MotionEvent event) {
13615         ListenerInfo li = mListenerInfo;
13616         //noinspection SimplifiableIfStatement
13617         if (li != null && li.mOnHoverListener != null
13618                 && (mViewFlags & ENABLED_MASK) == ENABLED
13619                 && li.mOnHoverListener.onHover(this, event)) {
13620             return true;
13621         }
13622 
13623         return onHoverEvent(event);
13624     }
13625 
13626     /**
13627      * Returns true if the view has a child to which it has recently sent
13628      * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
13629      * it does not have a hovered child, then it must be the innermost hovered view.
13630      * @hide
13631      */
hasHoveredChild()13632     protected boolean hasHoveredChild() {
13633         return false;
13634     }
13635 
13636     /**
13637      * Returns true if the given point, in local coordinates, is inside the hovered child.
13638      *
13639      * @hide
13640      */
pointInHoveredChild(MotionEvent event)13641     protected boolean pointInHoveredChild(MotionEvent event) {
13642         return false;
13643     }
13644 
13645     /**
13646      * Dispatch a generic motion event to the view under the first pointer.
13647      * <p>
13648      * Do not call this method directly.
13649      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
13650      * </p>
13651      *
13652      * @param event The motion event to be dispatched.
13653      * @return True if the event was handled by the view, false otherwise.
13654      */
dispatchGenericPointerEvent(MotionEvent event)13655     protected boolean dispatchGenericPointerEvent(MotionEvent event) {
13656         return false;
13657     }
13658 
13659     /**
13660      * Dispatch a generic motion event to the currently focused view.
13661      * <p>
13662      * Do not call this method directly.
13663      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
13664      * </p>
13665      *
13666      * @param event The motion event to be dispatched.
13667      * @return True if the event was handled by the view, false otherwise.
13668      */
dispatchGenericFocusedEvent(MotionEvent event)13669     protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
13670         return false;
13671     }
13672 
13673     /**
13674      * Dispatch a pointer event.
13675      * <p>
13676      * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
13677      * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
13678      * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
13679      * and should not be expected to handle other pointing device features.
13680      * </p>
13681      *
13682      * @param event The motion event to be dispatched.
13683      * @return True if the event was handled by the view, false otherwise.
13684      * @hide
13685      */
13686     @UnsupportedAppUsage
dispatchPointerEvent(MotionEvent event)13687     public final boolean dispatchPointerEvent(MotionEvent event) {
13688         if (event.isTouchEvent()) {
13689             return dispatchTouchEvent(event);
13690         } else {
13691             return dispatchGenericMotionEvent(event);
13692         }
13693     }
13694 
13695     /**
13696      * Called when the window containing this view gains or loses window focus.
13697      * ViewGroups should override to route to their children.
13698      *
13699      * @param hasFocus True if the window containing this view now has focus,
13700      *        false otherwise.
13701      */
dispatchWindowFocusChanged(boolean hasFocus)13702     public void dispatchWindowFocusChanged(boolean hasFocus) {
13703         onWindowFocusChanged(hasFocus);
13704     }
13705 
13706     /**
13707      * Called when the window containing this view gains or loses focus.  Note
13708      * that this is separate from view focus: to receive key events, both
13709      * your view and its window must have focus.  If a window is displayed
13710      * on top of yours that takes input focus, then your own window will lose
13711      * focus but the view focus will remain unchanged.
13712      *
13713      * @param hasWindowFocus True if the window containing this view now has
13714      *        focus, false otherwise.
13715      */
onWindowFocusChanged(boolean hasWindowFocus)13716     public void onWindowFocusChanged(boolean hasWindowFocus) {
13717         if (!hasWindowFocus) {
13718             if (isPressed()) {
13719                 setPressed(false);
13720             }
13721             mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
13722             if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
13723                 notifyFocusChangeToInputMethodManager(false /* hasFocus */);
13724             }
13725             removeLongPressCallback();
13726             removeTapCallback();
13727             onFocusLost();
13728         } else if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
13729             notifyFocusChangeToInputMethodManager(true /* hasFocus */);
13730         }
13731 
13732         refreshDrawableState();
13733     }
13734 
13735     /**
13736      * Returns true if this view is in a window that currently has window focus.
13737      * Note that this is not the same as the view itself having focus.
13738      *
13739      * @return True if this view is in a window that currently has window focus.
13740      */
hasWindowFocus()13741     public boolean hasWindowFocus() {
13742         return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
13743     }
13744 
13745     /**
13746      * Dispatch a view visibility change down the view hierarchy.
13747      * ViewGroups should override to route to their children.
13748      * @param changedView The view whose visibility changed. Could be 'this' or
13749      * an ancestor view.
13750      * @param visibility The new visibility of changedView: {@link #VISIBLE},
13751      * {@link #INVISIBLE} or {@link #GONE}.
13752      */
dispatchVisibilityChanged(@onNull View changedView, @Visibility int visibility)13753     protected void dispatchVisibilityChanged(@NonNull View changedView,
13754             @Visibility int visibility) {
13755         onVisibilityChanged(changedView, visibility);
13756     }
13757 
13758     /**
13759      * Called when the visibility of the view or an ancestor of the view has
13760      * changed.
13761      *
13762      * @param changedView The view whose visibility changed. May be
13763      *                    {@code this} or an ancestor view.
13764      * @param visibility The new visibility, one of {@link #VISIBLE},
13765      *                   {@link #INVISIBLE} or {@link #GONE}.
13766      */
onVisibilityChanged(@onNull View changedView, @Visibility int visibility)13767     protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
13768     }
13769 
13770     /**
13771      * Dispatch a hint about whether this view is displayed. For instance, when
13772      * a View moves out of the screen, it might receives a display hint indicating
13773      * the view is not displayed. Applications should not <em>rely</em> on this hint
13774      * as there is no guarantee that they will receive one.
13775      *
13776      * @param hint A hint about whether or not this view is displayed:
13777      * {@link #VISIBLE} or {@link #INVISIBLE}.
13778      */
dispatchDisplayHint(@isibility int hint)13779     public void dispatchDisplayHint(@Visibility int hint) {
13780         onDisplayHint(hint);
13781     }
13782 
13783     /**
13784      * Gives this view a hint about whether is displayed or not. For instance, when
13785      * a View moves out of the screen, it might receives a display hint indicating
13786      * the view is not displayed. Applications should not <em>rely</em> on this hint
13787      * as there is no guarantee that they will receive one.
13788      *
13789      * @param hint A hint about whether or not this view is displayed:
13790      * {@link #VISIBLE} or {@link #INVISIBLE}.
13791      */
onDisplayHint(@isibility int hint)13792     protected void onDisplayHint(@Visibility int hint) {
13793     }
13794 
13795     /**
13796      * Dispatch a window visibility change down the view hierarchy.
13797      * ViewGroups should override to route to their children.
13798      *
13799      * @param visibility The new visibility of the window.
13800      *
13801      * @see #onWindowVisibilityChanged(int)
13802      */
dispatchWindowVisibilityChanged(@isibility int visibility)13803     public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
13804         onWindowVisibilityChanged(visibility);
13805     }
13806 
13807     /**
13808      * Called when the window containing has change its visibility
13809      * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
13810      * that this tells you whether or not your window is being made visible
13811      * to the window manager; this does <em>not</em> tell you whether or not
13812      * your window is obscured by other windows on the screen, even if it
13813      * is itself visible.
13814      *
13815      * @param visibility The new visibility of the window.
13816      */
onWindowVisibilityChanged(@isibility int visibility)13817     protected void onWindowVisibilityChanged(@Visibility int visibility) {
13818         if (visibility == VISIBLE) {
13819             initialAwakenScrollBars();
13820         }
13821     }
13822 
13823     /**
13824      * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
13825      * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
13826      * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
13827      *
13828      * @param isVisible true if this view's visibility to the user is uninterrupted by its
13829      *                  ancestors or by window visibility
13830      * @return true if this view is visible to the user, not counting clipping or overlapping
13831      */
dispatchVisibilityAggregated(boolean isVisible)13832     boolean dispatchVisibilityAggregated(boolean isVisible) {
13833         final boolean thisVisible = getVisibility() == VISIBLE;
13834         // If we're not visible but something is telling us we are, ignore it.
13835         if (thisVisible || !isVisible) {
13836             onVisibilityAggregated(isVisible);
13837         }
13838         return thisVisible && isVisible;
13839     }
13840 
13841     /**
13842      * Called when the user-visibility of this View is potentially affected by a change
13843      * to this view itself, an ancestor view or the window this view is attached to.
13844      *
13845      * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
13846      *                  and this view's window is also visible
13847      */
13848     @CallSuper
onVisibilityAggregated(boolean isVisible)13849     public void onVisibilityAggregated(boolean isVisible) {
13850         // Update our internal visibility tracking so we can detect changes
13851         boolean oldVisible = (mPrivateFlags3 & PFLAG3_AGGREGATED_VISIBLE) != 0;
13852         mPrivateFlags3 = isVisible ? (mPrivateFlags3 | PFLAG3_AGGREGATED_VISIBLE)
13853                 : (mPrivateFlags3 & ~PFLAG3_AGGREGATED_VISIBLE);
13854         if (isVisible && mAttachInfo != null) {
13855             initialAwakenScrollBars();
13856         }
13857 
13858         final Drawable dr = mBackground;
13859         if (dr != null && isVisible != dr.isVisible()) {
13860             dr.setVisible(isVisible, false);
13861         }
13862         final Drawable hl = mDefaultFocusHighlight;
13863         if (hl != null && isVisible != hl.isVisible()) {
13864             hl.setVisible(isVisible, false);
13865         }
13866         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
13867         if (fg != null && isVisible != fg.isVisible()) {
13868             fg.setVisible(isVisible, false);
13869         }
13870 
13871         if (isAutofillable()) {
13872             AutofillManager afm = getAutofillManager();
13873 
13874             if (afm != null && getAutofillViewId() > LAST_APP_AUTOFILL_ID) {
13875                 if (mVisibilityChangeForAutofillHandler != null) {
13876                     mVisibilityChangeForAutofillHandler.removeMessages(0);
13877                 }
13878 
13879                 // If the view is in the background but still part of the hierarchy this is called
13880                 // with isVisible=false. Hence visibility==false requires further checks
13881                 if (isVisible) {
13882                     afm.notifyViewVisibilityChanged(this, true);
13883                 } else {
13884                     if (mVisibilityChangeForAutofillHandler == null) {
13885                         mVisibilityChangeForAutofillHandler =
13886                                 new VisibilityChangeForAutofillHandler(afm, this);
13887                     }
13888                     // Let current operation (e.g. removal of the view from the hierarchy)
13889                     // finish before checking state
13890                     mVisibilityChangeForAutofillHandler.obtainMessage(0, this).sendToTarget();
13891                 }
13892             }
13893         }
13894         if (isAccessibilityPane()) {
13895             if (isVisible != oldVisible) {
13896                 notifyViewAccessibilityStateChangedIfNeeded(isVisible
13897                         ? AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_APPEARED
13898                         : AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED);
13899             }
13900         }
13901     }
13902 
13903     /**
13904      * Returns the current visibility of the window this view is attached to
13905      * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
13906      *
13907      * @return Returns the current visibility of the view's window.
13908      */
13909     @Visibility
getWindowVisibility()13910     public int getWindowVisibility() {
13911         return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
13912     }
13913 
13914     /**
13915      * Retrieve the overall visible display size in which the window this view is
13916      * attached to has been positioned in.  This takes into account screen
13917      * decorations above the window, for both cases where the window itself
13918      * is being position inside of them or the window is being placed under
13919      * then and covered insets are used for the window to position its content
13920      * inside.  In effect, this tells you the available area where content can
13921      * be placed and remain visible to users.
13922      *
13923      * <p>This function requires an IPC back to the window manager to retrieve
13924      * the requested information, so should not be used in performance critical
13925      * code like drawing.
13926      *
13927      * @param outRect Filled in with the visible display frame.  If the view
13928      * is not attached to a window, this is simply the raw display size.
13929      */
getWindowVisibleDisplayFrame(Rect outRect)13930     public void getWindowVisibleDisplayFrame(Rect outRect) {
13931         if (mAttachInfo != null) {
13932             try {
13933                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
13934             } catch (RemoteException e) {
13935                 return;
13936             }
13937             // XXX This is really broken, and probably all needs to be done
13938             // in the window manager, and we need to know more about whether
13939             // we want the area behind or in front of the IME.
13940             final Rect insets = mAttachInfo.mVisibleInsets;
13941             outRect.left += insets.left;
13942             outRect.top += insets.top;
13943             outRect.right -= insets.right;
13944             outRect.bottom -= insets.bottom;
13945             return;
13946         }
13947         // The view is not attached to a display so we don't have a context.
13948         // Make a best guess about the display size.
13949         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
13950         d.getRectSize(outRect);
13951     }
13952 
13953     /**
13954      * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
13955      * is currently in without any insets.
13956      *
13957      * @hide
13958      */
13959     @UnsupportedAppUsage
getWindowDisplayFrame(Rect outRect)13960     public void getWindowDisplayFrame(Rect outRect) {
13961         if (mAttachInfo != null) {
13962             try {
13963                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
13964             } catch (RemoteException e) {
13965                 return;
13966             }
13967             return;
13968         }
13969         // The view is not attached to a display so we don't have a context.
13970         // Make a best guess about the display size.
13971         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
13972         d.getRectSize(outRect);
13973     }
13974 
13975     /**
13976      * Dispatch a notification about a resource configuration change down
13977      * the view hierarchy.
13978      * ViewGroups should override to route to their children.
13979      *
13980      * @param newConfig The new resource configuration.
13981      *
13982      * @see #onConfigurationChanged(android.content.res.Configuration)
13983      */
dispatchConfigurationChanged(Configuration newConfig)13984     public void dispatchConfigurationChanged(Configuration newConfig) {
13985         onConfigurationChanged(newConfig);
13986     }
13987 
13988     /**
13989      * Called when the current configuration of the resources being used
13990      * by the application have changed.  You can use this to decide when
13991      * to reload resources that can changed based on orientation and other
13992      * configuration characteristics.  You only need to use this if you are
13993      * not relying on the normal {@link android.app.Activity} mechanism of
13994      * recreating the activity instance upon a configuration change.
13995      *
13996      * @param newConfig The new resource configuration.
13997      */
onConfigurationChanged(Configuration newConfig)13998     protected void onConfigurationChanged(Configuration newConfig) {
13999     }
14000 
14001     /**
14002      * Private function to aggregate all per-view attributes in to the view
14003      * root.
14004      */
dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility)14005     void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
14006         performCollectViewAttributes(attachInfo, visibility);
14007     }
14008 
performCollectViewAttributes(AttachInfo attachInfo, int visibility)14009     void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
14010         if ((visibility & VISIBILITY_MASK) == VISIBLE) {
14011             if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
14012                 attachInfo.mKeepScreenOn = true;
14013             }
14014             attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
14015             ListenerInfo li = mListenerInfo;
14016             if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
14017                 attachInfo.mHasSystemUiListeners = true;
14018             }
14019         }
14020     }
14021 
needGlobalAttributesUpdate(boolean force)14022     void needGlobalAttributesUpdate(boolean force) {
14023         final AttachInfo ai = mAttachInfo;
14024         if (ai != null && !ai.mRecomputeGlobalAttributes) {
14025             if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
14026                     || ai.mHasSystemUiListeners) {
14027                 ai.mRecomputeGlobalAttributes = true;
14028             }
14029         }
14030     }
14031 
14032     /**
14033      * Returns whether the device is currently in touch mode.  Touch mode is entered
14034      * once the user begins interacting with the device by touch, and affects various
14035      * things like whether focus is always visible to the user.
14036      *
14037      * @return Whether the device is in touch mode.
14038      */
14039     @ViewDebug.ExportedProperty
isInTouchMode()14040     public boolean isInTouchMode() {
14041         if (mAttachInfo != null) {
14042             return mAttachInfo.mInTouchMode;
14043         } else {
14044             return ViewRootImpl.isInTouchMode();
14045         }
14046     }
14047 
14048     /**
14049      * Returns the context the view is running in, through which it can
14050      * access the current theme, resources, etc.
14051      *
14052      * @return The view's Context.
14053      */
14054     @ViewDebug.CapturedViewProperty
getContext()14055     public final Context getContext() {
14056         return mContext;
14057     }
14058 
14059     /**
14060      * Handle a key event before it is processed by any input method
14061      * associated with the view hierarchy.  This can be used to intercept
14062      * key events in special situations before the IME consumes them; a
14063      * typical example would be handling the BACK key to update the application's
14064      * UI instead of allowing the IME to see it and close itself.
14065      *
14066      * @param keyCode The value in event.getKeyCode().
14067      * @param event Description of the key event.
14068      * @return If you handled the event, return true. If you want to allow the
14069      *         event to be handled by the next receiver, return false.
14070      */
onKeyPreIme(int keyCode, KeyEvent event)14071     public boolean onKeyPreIme(int keyCode, KeyEvent event) {
14072         return false;
14073     }
14074 
14075     /**
14076      * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
14077      * KeyEvent.Callback.onKeyDown()}: perform press of the view
14078      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
14079      * is released, if the view is enabled and clickable.
14080      * <p>
14081      * Key presses in software keyboards will generally NOT trigger this
14082      * listener, although some may elect to do so in some situations. Do not
14083      * rely on this to catch software key presses.
14084      *
14085      * @param keyCode a key code that represents the button pressed, from
14086      *                {@link android.view.KeyEvent}
14087      * @param event the KeyEvent object that defines the button action
14088      */
onKeyDown(int keyCode, KeyEvent event)14089     public boolean onKeyDown(int keyCode, KeyEvent event) {
14090         if (KeyEvent.isConfirmKey(keyCode)) {
14091             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
14092                 return true;
14093             }
14094 
14095             if (event.getRepeatCount() == 0) {
14096                 // Long clickable items don't necessarily have to be clickable.
14097                 final boolean clickable = (mViewFlags & CLICKABLE) == CLICKABLE
14098                         || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
14099                 if (clickable || (mViewFlags & TOOLTIP) == TOOLTIP) {
14100                     // For the purposes of menu anchoring and drawable hotspots,
14101                     // key events are considered to be at the center of the view.
14102                     final float x = getWidth() / 2f;
14103                     final float y = getHeight() / 2f;
14104                     if (clickable) {
14105                         setPressed(true, x, y);
14106                     }
14107                     checkForLongClick(
14108                             ViewConfiguration.getLongPressTimeout(),
14109                             x,
14110                             y,
14111                             // This is not a touch gesture -- do not classify it as one.
14112                             TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION);
14113                     return true;
14114                 }
14115             }
14116         }
14117 
14118         return false;
14119     }
14120 
14121     /**
14122      * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
14123      * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
14124      * the event).
14125      * <p>Key presses in software keyboards will generally NOT trigger this listener,
14126      * although some may elect to do so in some situations. Do not rely on this to
14127      * catch software key presses.
14128      */
onKeyLongPress(int keyCode, KeyEvent event)14129     public boolean onKeyLongPress(int keyCode, KeyEvent event) {
14130         return false;
14131     }
14132 
14133     /**
14134      * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
14135      * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
14136      * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
14137      * or {@link KeyEvent#KEYCODE_SPACE} is released.
14138      * <p>Key presses in software keyboards will generally NOT trigger this listener,
14139      * although some may elect to do so in some situations. Do not rely on this to
14140      * catch software key presses.
14141      *
14142      * @param keyCode A key code that represents the button pressed, from
14143      *                {@link android.view.KeyEvent}.
14144      * @param event   The KeyEvent object that defines the button action.
14145      */
onKeyUp(int keyCode, KeyEvent event)14146     public boolean onKeyUp(int keyCode, KeyEvent event) {
14147         if (KeyEvent.isConfirmKey(keyCode)) {
14148             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
14149                 return true;
14150             }
14151             if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
14152                 setPressed(false);
14153 
14154                 if (!mHasPerformedLongPress) {
14155                     // This is a tap, so remove the longpress check
14156                     removeLongPressCallback();
14157                     if (!event.isCanceled()) {
14158                         return performClickInternal();
14159                     }
14160                 }
14161             }
14162         }
14163         return false;
14164     }
14165 
14166     /**
14167      * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
14168      * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
14169      * the event).
14170      * <p>Key presses in software keyboards will generally NOT trigger this listener,
14171      * although some may elect to do so in some situations. Do not rely on this to
14172      * catch software key presses.
14173      *
14174      * @param keyCode     A key code that represents the button pressed, from
14175      *                    {@link android.view.KeyEvent}.
14176      * @param repeatCount The number of times the action was made.
14177      * @param event       The KeyEvent object that defines the button action.
14178      */
onKeyMultiple(int keyCode, int repeatCount, KeyEvent event)14179     public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
14180         return false;
14181     }
14182 
14183     /**
14184      * Called on the focused view when a key shortcut event is not handled.
14185      * Override this method to implement local key shortcuts for the View.
14186      * Key shortcuts can also be implemented by setting the
14187      * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
14188      *
14189      * @param keyCode The value in event.getKeyCode().
14190      * @param event Description of the key event.
14191      * @return If you handled the event, return true. If you want to allow the
14192      *         event to be handled by the next receiver, return false.
14193      */
onKeyShortcut(int keyCode, KeyEvent event)14194     public boolean onKeyShortcut(int keyCode, KeyEvent event) {
14195         return false;
14196     }
14197 
14198     /**
14199      * Check whether the called view is a text editor, in which case it
14200      * would make sense to automatically display a soft input window for
14201      * it.  Subclasses should override this if they implement
14202      * {@link #onCreateInputConnection(EditorInfo)} to return true if
14203      * a call on that method would return a non-null InputConnection, and
14204      * they are really a first-class editor that the user would normally
14205      * start typing on when the go into a window containing your view.
14206      *
14207      * <p>The default implementation always returns false.  This does
14208      * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
14209      * will not be called or the user can not otherwise perform edits on your
14210      * view; it is just a hint to the system that this is not the primary
14211      * purpose of this view.
14212      *
14213      * @return Returns true if this view is a text editor, else false.
14214      */
onCheckIsTextEditor()14215     public boolean onCheckIsTextEditor() {
14216         return false;
14217     }
14218 
14219     /**
14220      * Create a new InputConnection for an InputMethod to interact
14221      * with the view.  The default implementation returns null, since it doesn't
14222      * support input methods.  You can override this to implement such support.
14223      * This is only needed for views that take focus and text input.
14224      *
14225      * <p>When implementing this, you probably also want to implement
14226      * {@link #onCheckIsTextEditor()} to indicate you will return a
14227      * non-null InputConnection.</p>
14228      *
14229      * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
14230      * object correctly and in its entirety, so that the connected IME can rely
14231      * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
14232      * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
14233      * must be filled in with the correct cursor position for IMEs to work correctly
14234      * with your application.</p>
14235      *
14236      * @param outAttrs Fill in with attribute information about the connection.
14237      */
onCreateInputConnection(EditorInfo outAttrs)14238     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
14239         return null;
14240     }
14241 
14242     /**
14243      * Called by the {@link android.view.inputmethod.InputMethodManager}
14244      * when a view who is not the current
14245      * input connection target is trying to make a call on the manager.  The
14246      * default implementation returns false; you can override this to return
14247      * true for certain views if you are performing InputConnection proxying
14248      * to them.
14249      * @param view The View that is making the InputMethodManager call.
14250      * @return Return true to allow the call, false to reject.
14251      */
checkInputConnectionProxy(View view)14252     public boolean checkInputConnectionProxy(View view) {
14253         return false;
14254     }
14255 
14256     /**
14257      * Show the context menu for this view. It is not safe to hold on to the
14258      * menu after returning from this method.
14259      *
14260      * You should normally not overload this method. Overload
14261      * {@link #onCreateContextMenu(ContextMenu)} or define an
14262      * {@link OnCreateContextMenuListener} to add items to the context menu.
14263      *
14264      * @param menu The context menu to populate
14265      */
createContextMenu(ContextMenu menu)14266     public void createContextMenu(ContextMenu menu) {
14267         ContextMenuInfo menuInfo = getContextMenuInfo();
14268 
14269         // Sets the current menu info so all items added to menu will have
14270         // my extra info set.
14271         ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
14272 
14273         onCreateContextMenu(menu);
14274         ListenerInfo li = mListenerInfo;
14275         if (li != null && li.mOnCreateContextMenuListener != null) {
14276             li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
14277         }
14278 
14279         // Clear the extra information so subsequent items that aren't mine don't
14280         // have my extra info.
14281         ((MenuBuilder)menu).setCurrentMenuInfo(null);
14282 
14283         if (mParent != null) {
14284             mParent.createContextMenu(menu);
14285         }
14286     }
14287 
14288     /**
14289      * Views should implement this if they have extra information to associate
14290      * with the context menu. The return result is supplied as a parameter to
14291      * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
14292      * callback.
14293      *
14294      * @return Extra information about the item for which the context menu
14295      *         should be shown. This information will vary across different
14296      *         subclasses of View.
14297      */
getContextMenuInfo()14298     protected ContextMenuInfo getContextMenuInfo() {
14299         return null;
14300     }
14301 
14302     /**
14303      * Views should implement this if the view itself is going to add items to
14304      * the context menu.
14305      *
14306      * @param menu the context menu to populate
14307      */
onCreateContextMenu(ContextMenu menu)14308     protected void onCreateContextMenu(ContextMenu menu) {
14309     }
14310 
14311     /**
14312      * Implement this method to handle trackball motion events.  The
14313      * <em>relative</em> movement of the trackball since the last event
14314      * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
14315      * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
14316      * that a movement of 1 corresponds to the user pressing one DPAD key (so
14317      * they will often be fractional values, representing the more fine-grained
14318      * movement information available from a trackball).
14319      *
14320      * @param event The motion event.
14321      * @return True if the event was handled, false otherwise.
14322      */
onTrackballEvent(MotionEvent event)14323     public boolean onTrackballEvent(MotionEvent event) {
14324         return false;
14325     }
14326 
14327     /**
14328      * Implement this method to handle generic motion events.
14329      * <p>
14330      * Generic motion events describe joystick movements, mouse hovers, track pad
14331      * touches, scroll wheel movements and other input events.  The
14332      * {@link MotionEvent#getSource() source} of the motion event specifies
14333      * the class of input that was received.  Implementations of this method
14334      * must examine the bits in the source before processing the event.
14335      * The following code example shows how this is done.
14336      * </p><p>
14337      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
14338      * are delivered to the view under the pointer.  All other generic motion events are
14339      * delivered to the focused view.
14340      * </p>
14341      * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
14342      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
14343      *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
14344      *             // process the joystick movement...
14345      *             return true;
14346      *         }
14347      *     }
14348      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
14349      *         switch (event.getAction()) {
14350      *             case MotionEvent.ACTION_HOVER_MOVE:
14351      *                 // process the mouse hover movement...
14352      *                 return true;
14353      *             case MotionEvent.ACTION_SCROLL:
14354      *                 // process the scroll wheel movement...
14355      *                 return true;
14356      *         }
14357      *     }
14358      *     return super.onGenericMotionEvent(event);
14359      * }</pre>
14360      *
14361      * @param event The generic motion event being processed.
14362      * @return True if the event was handled, false otherwise.
14363      */
onGenericMotionEvent(MotionEvent event)14364     public boolean onGenericMotionEvent(MotionEvent event) {
14365         return false;
14366     }
14367 
14368     /**
14369      * Dispatching hover events to {@link TouchDelegate} to improve accessibility.
14370      * <p>
14371      * This method is dispatching hover events to the delegate target to support explore by touch.
14372      * Similar to {@link ViewGroup#dispatchTouchEvent}, this method send proper hover events to
14373      * the delegate target according to the pointer and the touch area of the delegate while touch
14374      * exploration enabled.
14375      * </p>
14376      *
14377      * @param event The motion event dispatch to the delegate target.
14378      * @return True if the event was handled, false otherwise.
14379      *
14380      * @see #onHoverEvent
14381      */
dispatchTouchExplorationHoverEvent(MotionEvent event)14382     private boolean dispatchTouchExplorationHoverEvent(MotionEvent event) {
14383         final AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
14384         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
14385             return false;
14386         }
14387 
14388         final boolean oldHoveringTouchDelegate = mHoveringTouchDelegate;
14389         final int action = event.getActionMasked();
14390         boolean pointInDelegateRegion = false;
14391         boolean handled = false;
14392 
14393         final AccessibilityNodeInfo.TouchDelegateInfo info = mTouchDelegate.getTouchDelegateInfo();
14394         for (int i = 0; i < info.getRegionCount(); i++) {
14395             Region r = info.getRegionAt(i);
14396             if (r.contains((int) event.getX(), (int) event.getY())) {
14397                 pointInDelegateRegion = true;
14398             }
14399         }
14400 
14401         // Explore by touch should dispatch events to children under the pointer first if any
14402         // before dispatching to TouchDelegate. For non-hoverable views that do not consume
14403         // hover events but receive accessibility focus, it should also not delegate to these
14404         // views when hovered.
14405         if (!oldHoveringTouchDelegate) {
14406             if ((action == MotionEvent.ACTION_HOVER_ENTER
14407                     || action == MotionEvent.ACTION_HOVER_MOVE)
14408                     && !pointInHoveredChild(event)
14409                     && pointInDelegateRegion) {
14410                 mHoveringTouchDelegate = true;
14411             }
14412         } else {
14413             if (action == MotionEvent.ACTION_HOVER_EXIT
14414                     || (action == MotionEvent.ACTION_HOVER_MOVE
14415                         && (pointInHoveredChild(event) || !pointInDelegateRegion))) {
14416                 mHoveringTouchDelegate = false;
14417             }
14418         }
14419         switch (action) {
14420             case MotionEvent.ACTION_HOVER_MOVE:
14421                 if (oldHoveringTouchDelegate && mHoveringTouchDelegate) {
14422                     // Inside bounds, dispatch as is.
14423                     handled = mTouchDelegate.onTouchExplorationHoverEvent(event);
14424                 } else if (!oldHoveringTouchDelegate && mHoveringTouchDelegate) {
14425                     // Moving inbound, synthesize hover enter.
14426                     MotionEvent eventNoHistory = (event.getHistorySize() == 0)
14427                             ? event : MotionEvent.obtainNoHistory(event);
14428                     eventNoHistory.setAction(MotionEvent.ACTION_HOVER_ENTER);
14429                     handled = mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
14430                     eventNoHistory.setAction(action);
14431                     handled |= mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
14432                 } else if (oldHoveringTouchDelegate && !mHoveringTouchDelegate) {
14433                     // Moving outbound, synthesize hover exit.
14434                     final boolean hoverExitPending = event.isHoverExitPending();
14435                     event.setHoverExitPending(true);
14436                     mTouchDelegate.onTouchExplorationHoverEvent(event);
14437                     MotionEvent eventNoHistory = (event.getHistorySize() == 0)
14438                             ? event : MotionEvent.obtainNoHistory(event);
14439                     eventNoHistory.setHoverExitPending(hoverExitPending);
14440                     eventNoHistory.setAction(MotionEvent.ACTION_HOVER_EXIT);
14441                     mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
14442                 }  // else: outside bounds, do nothing.
14443                 break;
14444             case MotionEvent.ACTION_HOVER_ENTER:
14445                 if (!oldHoveringTouchDelegate && mHoveringTouchDelegate) {
14446                     handled = mTouchDelegate.onTouchExplorationHoverEvent(event);
14447                 }
14448                 break;
14449             case MotionEvent.ACTION_HOVER_EXIT:
14450                 if (oldHoveringTouchDelegate) {
14451                     mTouchDelegate.onTouchExplorationHoverEvent(event);
14452                 }
14453                 break;
14454         }
14455         return handled;
14456     }
14457 
14458     /**
14459      * Implement this method to handle hover events.
14460      * <p>
14461      * This method is called whenever a pointer is hovering into, over, or out of the
14462      * bounds of a view and the view is not currently being touched.
14463      * Hover events are represented as pointer events with action
14464      * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
14465      * or {@link MotionEvent#ACTION_HOVER_EXIT}.
14466      * </p>
14467      * <ul>
14468      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
14469      * when the pointer enters the bounds of the view.</li>
14470      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
14471      * when the pointer has already entered the bounds of the view and has moved.</li>
14472      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
14473      * when the pointer has exited the bounds of the view or when the pointer is
14474      * about to go down due to a button click, tap, or similar user action that
14475      * causes the view to be touched.</li>
14476      * </ul>
14477      * <p>
14478      * The view should implement this method to return true to indicate that it is
14479      * handling the hover event, such as by changing its drawable state.
14480      * </p><p>
14481      * The default implementation calls {@link #setHovered} to update the hovered state
14482      * of the view when a hover enter or hover exit event is received, if the view
14483      * is enabled and is clickable.  The default implementation also sends hover
14484      * accessibility events.
14485      * </p>
14486      *
14487      * @param event The motion event that describes the hover.
14488      * @return True if the view handled the hover event.
14489      *
14490      * @see #isHovered
14491      * @see #setHovered
14492      * @see #onHoverChanged
14493      */
onHoverEvent(MotionEvent event)14494     public boolean onHoverEvent(MotionEvent event) {
14495         if (mTouchDelegate != null && dispatchTouchExplorationHoverEvent(event)) {
14496             return true;
14497         }
14498 
14499         // The root view may receive hover (or touch) events that are outside the bounds of
14500         // the window.  This code ensures that we only send accessibility events for
14501         // hovers that are actually within the bounds of the root view.
14502         final int action = event.getActionMasked();
14503         if (!mSendingHoverAccessibilityEvents) {
14504             if ((action == MotionEvent.ACTION_HOVER_ENTER
14505                     || action == MotionEvent.ACTION_HOVER_MOVE)
14506                     && !hasHoveredChild()
14507                     && pointInView(event.getX(), event.getY())) {
14508                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
14509                 mSendingHoverAccessibilityEvents = true;
14510             }
14511         } else {
14512             if (action == MotionEvent.ACTION_HOVER_EXIT
14513                     || (action == MotionEvent.ACTION_HOVER_MOVE
14514                             && !pointInView(event.getX(), event.getY()))) {
14515                 mSendingHoverAccessibilityEvents = false;
14516                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
14517             }
14518         }
14519 
14520         if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
14521                 && event.isFromSource(InputDevice.SOURCE_MOUSE)
14522                 && isOnScrollbar(event.getX(), event.getY())) {
14523             awakenScrollBars();
14524         }
14525 
14526         // If we consider ourself hoverable, or if we we're already hovered,
14527         // handle changing state in response to ENTER and EXIT events.
14528         if (isHoverable() || isHovered()) {
14529             switch (action) {
14530                 case MotionEvent.ACTION_HOVER_ENTER:
14531                     setHovered(true);
14532                     break;
14533                 case MotionEvent.ACTION_HOVER_EXIT:
14534                     setHovered(false);
14535                     break;
14536             }
14537 
14538             // Dispatch the event to onGenericMotionEvent before returning true.
14539             // This is to provide compatibility with existing applications that
14540             // handled HOVER_MOVE events in onGenericMotionEvent and that would
14541             // break because of the new default handling for hoverable views
14542             // in onHoverEvent.
14543             // Note that onGenericMotionEvent will be called by default when
14544             // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
14545             dispatchGenericMotionEventInternal(event);
14546             // The event was already handled by calling setHovered(), so always
14547             // return true.
14548             return true;
14549         }
14550 
14551         return false;
14552     }
14553 
14554     /**
14555      * Returns true if the view should handle {@link #onHoverEvent}
14556      * by calling {@link #setHovered} to change its hovered state.
14557      *
14558      * @return True if the view is hoverable.
14559      */
isHoverable()14560     private boolean isHoverable() {
14561         final int viewFlags = mViewFlags;
14562         if ((viewFlags & ENABLED_MASK) == DISABLED) {
14563             return false;
14564         }
14565 
14566         return (viewFlags & CLICKABLE) == CLICKABLE
14567                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
14568                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
14569     }
14570 
14571     /**
14572      * Returns true if the view is currently hovered.
14573      *
14574      * @return True if the view is currently hovered.
14575      *
14576      * @see #setHovered
14577      * @see #onHoverChanged
14578      */
14579     @ViewDebug.ExportedProperty
isHovered()14580     public boolean isHovered() {
14581         return (mPrivateFlags & PFLAG_HOVERED) != 0;
14582     }
14583 
14584     /**
14585      * Sets whether the view is currently hovered.
14586      * <p>
14587      * Calling this method also changes the drawable state of the view.  This
14588      * enables the view to react to hover by using different drawable resources
14589      * to change its appearance.
14590      * </p><p>
14591      * The {@link #onHoverChanged} method is called when the hovered state changes.
14592      * </p>
14593      *
14594      * @param hovered True if the view is hovered.
14595      *
14596      * @see #isHovered
14597      * @see #onHoverChanged
14598      */
setHovered(boolean hovered)14599     public void setHovered(boolean hovered) {
14600         if (hovered) {
14601             if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
14602                 mPrivateFlags |= PFLAG_HOVERED;
14603                 refreshDrawableState();
14604                 onHoverChanged(true);
14605             }
14606         } else {
14607             if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
14608                 mPrivateFlags &= ~PFLAG_HOVERED;
14609                 refreshDrawableState();
14610                 onHoverChanged(false);
14611             }
14612         }
14613     }
14614 
14615     /**
14616      * Implement this method to handle hover state changes.
14617      * <p>
14618      * This method is called whenever the hover state changes as a result of a
14619      * call to {@link #setHovered}.
14620      * </p>
14621      *
14622      * @param hovered The current hover state, as returned by {@link #isHovered}.
14623      *
14624      * @see #isHovered
14625      * @see #setHovered
14626      */
onHoverChanged(boolean hovered)14627     public void onHoverChanged(boolean hovered) {
14628     }
14629 
14630     /**
14631      * Handles scroll bar dragging by mouse input.
14632      *
14633      * @hide
14634      * @param event The motion event.
14635      *
14636      * @return true if the event was handled as a scroll bar dragging, false otherwise.
14637      */
handleScrollBarDragging(MotionEvent event)14638     protected boolean handleScrollBarDragging(MotionEvent event) {
14639         if (mScrollCache == null) {
14640             return false;
14641         }
14642         final float x = event.getX();
14643         final float y = event.getY();
14644         final int action = event.getAction();
14645         if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
14646                 && action != MotionEvent.ACTION_DOWN)
14647                     || !event.isFromSource(InputDevice.SOURCE_MOUSE)
14648                     || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
14649             mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
14650             return false;
14651         }
14652 
14653         switch (action) {
14654             case MotionEvent.ACTION_MOVE:
14655                 if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
14656                     return false;
14657                 }
14658                 if (mScrollCache.mScrollBarDraggingState
14659                         == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
14660                     final Rect bounds = mScrollCache.mScrollBarBounds;
14661                     getVerticalScrollBarBounds(bounds, null);
14662                     final int range = computeVerticalScrollRange();
14663                     final int offset = computeVerticalScrollOffset();
14664                     final int extent = computeVerticalScrollExtent();
14665 
14666                     final int thumbLength = ScrollBarUtils.getThumbLength(
14667                             bounds.height(), bounds.width(), extent, range);
14668                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
14669                             bounds.height(), thumbLength, extent, range, offset);
14670 
14671                     final float diff = y - mScrollCache.mScrollBarDraggingPos;
14672                     final float maxThumbOffset = bounds.height() - thumbLength;
14673                     final float newThumbOffset =
14674                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
14675                     final int height = getHeight();
14676                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
14677                             && height > 0 && extent > 0) {
14678                         final int newY = Math.round((range - extent)
14679                                 / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
14680                         if (newY != getScrollY()) {
14681                             mScrollCache.mScrollBarDraggingPos = y;
14682                             setScrollY(newY);
14683                         }
14684                     }
14685                     return true;
14686                 }
14687                 if (mScrollCache.mScrollBarDraggingState
14688                         == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
14689                     final Rect bounds = mScrollCache.mScrollBarBounds;
14690                     getHorizontalScrollBarBounds(bounds, null);
14691                     final int range = computeHorizontalScrollRange();
14692                     final int offset = computeHorizontalScrollOffset();
14693                     final int extent = computeHorizontalScrollExtent();
14694 
14695                     final int thumbLength = ScrollBarUtils.getThumbLength(
14696                             bounds.width(), bounds.height(), extent, range);
14697                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
14698                             bounds.width(), thumbLength, extent, range, offset);
14699 
14700                     final float diff = x - mScrollCache.mScrollBarDraggingPos;
14701                     final float maxThumbOffset = bounds.width() - thumbLength;
14702                     final float newThumbOffset =
14703                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
14704                     final int width = getWidth();
14705                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
14706                             && width > 0 && extent > 0) {
14707                         final int newX = Math.round((range - extent)
14708                                 / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
14709                         if (newX != getScrollX()) {
14710                             mScrollCache.mScrollBarDraggingPos = x;
14711                             setScrollX(newX);
14712                         }
14713                     }
14714                     return true;
14715                 }
14716             case MotionEvent.ACTION_DOWN:
14717                 if (mScrollCache.state == ScrollabilityCache.OFF) {
14718                     return false;
14719                 }
14720                 if (isOnVerticalScrollbarThumb(x, y)) {
14721                     mScrollCache.mScrollBarDraggingState =
14722                             ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
14723                     mScrollCache.mScrollBarDraggingPos = y;
14724                     return true;
14725                 }
14726                 if (isOnHorizontalScrollbarThumb(x, y)) {
14727                     mScrollCache.mScrollBarDraggingState =
14728                             ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
14729                     mScrollCache.mScrollBarDraggingPos = x;
14730                     return true;
14731                 }
14732         }
14733         mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
14734         return false;
14735     }
14736 
14737     /**
14738      * Implement this method to handle touch screen motion events.
14739      * <p>
14740      * If this method is used to detect click actions, it is recommended that
14741      * the actions be performed by implementing and calling
14742      * {@link #performClick()}. This will ensure consistent system behavior,
14743      * including:
14744      * <ul>
14745      * <li>obeying click sound preferences
14746      * <li>dispatching OnClickListener calls
14747      * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
14748      * accessibility features are enabled
14749      * </ul>
14750      *
14751      * @param event The motion event.
14752      * @return True if the event was handled, false otherwise.
14753      */
onTouchEvent(MotionEvent event)14754     public boolean onTouchEvent(MotionEvent event) {
14755         final float x = event.getX();
14756         final float y = event.getY();
14757         final int viewFlags = mViewFlags;
14758         final int action = event.getAction();
14759 
14760         final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE
14761                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
14762                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
14763 
14764         if ((viewFlags & ENABLED_MASK) == DISABLED) {
14765             if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
14766                 setPressed(false);
14767             }
14768             mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
14769             // A disabled view that is clickable still consumes the touch
14770             // events, it just doesn't respond to them.
14771             return clickable;
14772         }
14773         if (mTouchDelegate != null) {
14774             if (mTouchDelegate.onTouchEvent(event)) {
14775                 return true;
14776             }
14777         }
14778 
14779         if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
14780             switch (action) {
14781                 case MotionEvent.ACTION_UP:
14782                     mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
14783                     if ((viewFlags & TOOLTIP) == TOOLTIP) {
14784                         handleTooltipUp();
14785                     }
14786                     if (!clickable) {
14787                         removeTapCallback();
14788                         removeLongPressCallback();
14789                         mInContextButtonPress = false;
14790                         mHasPerformedLongPress = false;
14791                         mIgnoreNextUpEvent = false;
14792                         break;
14793                     }
14794                     boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
14795                     if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
14796                         // take focus if we don't have it already and we should in
14797                         // touch mode.
14798                         boolean focusTaken = false;
14799                         if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
14800                             focusTaken = requestFocus();
14801                         }
14802 
14803                         if (prepressed) {
14804                             // The button is being released before we actually
14805                             // showed it as pressed.  Make it show the pressed
14806                             // state now (before scheduling the click) to ensure
14807                             // the user sees it.
14808                             setPressed(true, x, y);
14809                         }
14810 
14811                         if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
14812                             // This is a tap, so remove the longpress check
14813                             removeLongPressCallback();
14814 
14815                             // Only perform take click actions if we were in the pressed state
14816                             if (!focusTaken) {
14817                                 // Use a Runnable and post this rather than calling
14818                                 // performClick directly. This lets other visual state
14819                                 // of the view update before click actions start.
14820                                 if (mPerformClick == null) {
14821                                     mPerformClick = new PerformClick();
14822                                 }
14823                                 if (!post(mPerformClick)) {
14824                                     performClickInternal();
14825                                 }
14826                             }
14827                         }
14828 
14829                         if (mUnsetPressedState == null) {
14830                             mUnsetPressedState = new UnsetPressedState();
14831                         }
14832 
14833                         if (prepressed) {
14834                             postDelayed(mUnsetPressedState,
14835                                     ViewConfiguration.getPressedStateDuration());
14836                         } else if (!post(mUnsetPressedState)) {
14837                             // If the post failed, unpress right now
14838                             mUnsetPressedState.run();
14839                         }
14840 
14841                         removeTapCallback();
14842                     }
14843                     mIgnoreNextUpEvent = false;
14844                     break;
14845 
14846                 case MotionEvent.ACTION_DOWN:
14847                     if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
14848                         mPrivateFlags3 |= PFLAG3_FINGER_DOWN;
14849                     }
14850                     mHasPerformedLongPress = false;
14851 
14852                     if (!clickable) {
14853                         checkForLongClick(
14854                                 ViewConfiguration.getLongPressTimeout(),
14855                                 x,
14856                                 y,
14857                                 TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
14858                         break;
14859                     }
14860 
14861                     if (performButtonActionOnTouchDown(event)) {
14862                         break;
14863                     }
14864 
14865                     // Walk up the hierarchy to determine if we're inside a scrolling container.
14866                     boolean isInScrollingContainer = isInScrollingContainer();
14867 
14868                     // For views inside a scrolling container, delay the pressed feedback for
14869                     // a short period in case this is a scroll.
14870                     if (isInScrollingContainer) {
14871                         mPrivateFlags |= PFLAG_PREPRESSED;
14872                         if (mPendingCheckForTap == null) {
14873                             mPendingCheckForTap = new CheckForTap();
14874                         }
14875                         mPendingCheckForTap.x = event.getX();
14876                         mPendingCheckForTap.y = event.getY();
14877                         postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
14878                     } else {
14879                         // Not inside a scrolling container, so show the feedback right away
14880                         setPressed(true, x, y);
14881                         checkForLongClick(
14882                                 ViewConfiguration.getLongPressTimeout(),
14883                                 x,
14884                                 y,
14885                                 TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
14886                     }
14887                     break;
14888 
14889                 case MotionEvent.ACTION_CANCEL:
14890                     if (clickable) {
14891                         setPressed(false);
14892                     }
14893                     removeTapCallback();
14894                     removeLongPressCallback();
14895                     mInContextButtonPress = false;
14896                     mHasPerformedLongPress = false;
14897                     mIgnoreNextUpEvent = false;
14898                     mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
14899                     break;
14900 
14901                 case MotionEvent.ACTION_MOVE:
14902                     if (clickable) {
14903                         drawableHotspotChanged(x, y);
14904                     }
14905 
14906                     final int motionClassification = event.getClassification();
14907                     final boolean ambiguousGesture =
14908                             motionClassification == MotionEvent.CLASSIFICATION_AMBIGUOUS_GESTURE;
14909                     int touchSlop = mTouchSlop;
14910                     if (ambiguousGesture && hasPendingLongPressCallback()) {
14911                         final float ambiguousMultiplier =
14912                                 ViewConfiguration.getAmbiguousGestureMultiplier();
14913                         if (!pointInView(x, y, touchSlop)) {
14914                             // The default action here is to cancel long press. But instead, we
14915                             // just extend the timeout here, in case the classification
14916                             // stays ambiguous.
14917                             removeLongPressCallback();
14918                             long delay = (long) (ViewConfiguration.getLongPressTimeout()
14919                                     * ambiguousMultiplier);
14920                             // Subtract the time already spent
14921                             delay -= event.getEventTime() - event.getDownTime();
14922                             checkForLongClick(
14923                                     delay,
14924                                     x,
14925                                     y,
14926                                     TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
14927                         }
14928                         touchSlop *= ambiguousMultiplier;
14929                     }
14930 
14931                     // Be lenient about moving outside of buttons
14932                     if (!pointInView(x, y, touchSlop)) {
14933                         // Outside button
14934                         // Remove any future long press/tap checks
14935                         removeTapCallback();
14936                         removeLongPressCallback();
14937                         if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
14938                             setPressed(false);
14939                         }
14940                         mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
14941                     }
14942 
14943                     final boolean deepPress =
14944                             motionClassification == MotionEvent.CLASSIFICATION_DEEP_PRESS;
14945                     if (deepPress && hasPendingLongPressCallback()) {
14946                         // process the long click action immediately
14947                         removeLongPressCallback();
14948                         checkForLongClick(
14949                                 0 /* send immediately */,
14950                                 x,
14951                                 y,
14952                                 TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS);
14953                     }
14954 
14955                     break;
14956             }
14957 
14958             return true;
14959         }
14960 
14961         return false;
14962     }
14963 
14964     /**
14965      * @hide
14966      */
14967     @UnsupportedAppUsage
isInScrollingContainer()14968     public boolean isInScrollingContainer() {
14969         ViewParent p = getParent();
14970         while (p != null && p instanceof ViewGroup) {
14971             if (((ViewGroup) p).shouldDelayChildPressedState()) {
14972                 return true;
14973             }
14974             p = p.getParent();
14975         }
14976         return false;
14977     }
14978 
14979     /**
14980      * Remove the longpress detection timer.
14981      */
removeLongPressCallback()14982     private void removeLongPressCallback() {
14983         if (mPendingCheckForLongPress != null) {
14984             removeCallbacks(mPendingCheckForLongPress);
14985         }
14986     }
14987 
14988     /**
14989      * Return true if the long press callback is scheduled to run sometime in the future.
14990      * Return false if there is no scheduled long press callback at the moment.
14991      */
hasPendingLongPressCallback()14992     private boolean hasPendingLongPressCallback() {
14993         if (mPendingCheckForLongPress == null) {
14994             return false;
14995         }
14996         final AttachInfo attachInfo = mAttachInfo;
14997         if (attachInfo == null) {
14998             return false;
14999         }
15000         return attachInfo.mHandler.hasCallbacks(mPendingCheckForLongPress);
15001     }
15002 
15003    /**
15004      * Remove the pending click action
15005      */
15006     @UnsupportedAppUsage
removePerformClickCallback()15007     private void removePerformClickCallback() {
15008         if (mPerformClick != null) {
15009             removeCallbacks(mPerformClick);
15010         }
15011     }
15012 
15013     /**
15014      * Remove the prepress detection timer.
15015      */
removeUnsetPressCallback()15016     private void removeUnsetPressCallback() {
15017         if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
15018             setPressed(false);
15019             removeCallbacks(mUnsetPressedState);
15020         }
15021     }
15022 
15023     /**
15024      * Remove the tap detection timer.
15025      */
removeTapCallback()15026     private void removeTapCallback() {
15027         if (mPendingCheckForTap != null) {
15028             mPrivateFlags &= ~PFLAG_PREPRESSED;
15029             removeCallbacks(mPendingCheckForTap);
15030         }
15031     }
15032 
15033     /**
15034      * Cancels a pending long press.  Your subclass can use this if you
15035      * want the context menu to come up if the user presses and holds
15036      * at the same place, but you don't want it to come up if they press
15037      * and then move around enough to cause scrolling.
15038      */
cancelLongPress()15039     public void cancelLongPress() {
15040         removeLongPressCallback();
15041 
15042         /*
15043          * The prepressed state handled by the tap callback is a display
15044          * construct, but the tap callback will post a long press callback
15045          * less its own timeout. Remove it here.
15046          */
15047         removeTapCallback();
15048     }
15049 
15050     /**
15051      * Sets the TouchDelegate for this View.
15052      */
setTouchDelegate(TouchDelegate delegate)15053     public void setTouchDelegate(TouchDelegate delegate) {
15054         mTouchDelegate = delegate;
15055     }
15056 
15057     /**
15058      * Gets the TouchDelegate for this View.
15059      */
getTouchDelegate()15060     public TouchDelegate getTouchDelegate() {
15061         return mTouchDelegate;
15062     }
15063 
15064     /**
15065      * Request unbuffered dispatch of the given stream of MotionEvents to this View.
15066      *
15067      * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
15068      * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
15069      * available. This method should only be called for touch events.
15070      *
15071      * <p class="note">This api is not intended for most applications. Buffered dispatch
15072      * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
15073      * streams will not improve your input latency. Side effects include: increased latency,
15074      * jittery scrolls and inability to take advantage of system resampling. Talk to your input
15075      * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
15076      * you.</p>
15077      */
requestUnbufferedDispatch(MotionEvent event)15078     public final void requestUnbufferedDispatch(MotionEvent event) {
15079         final int action = event.getAction();
15080         if (mAttachInfo == null
15081                 || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
15082                 || !event.isTouchEvent()) {
15083             return;
15084         }
15085         mAttachInfo.mUnbufferedDispatchRequested = true;
15086     }
15087 
hasSize()15088     private boolean hasSize() {
15089         return (mBottom > mTop) && (mRight > mLeft);
15090     }
15091 
canTakeFocus()15092     private boolean canTakeFocus() {
15093         return ((mViewFlags & VISIBILITY_MASK) == VISIBLE)
15094                 && ((mViewFlags & FOCUSABLE) == FOCUSABLE)
15095                 && ((mViewFlags & ENABLED_MASK) == ENABLED)
15096                 && (sCanFocusZeroSized || !isLayoutValid() || hasSize());
15097     }
15098 
15099     /**
15100      * Set flags controlling behavior of this view.
15101      *
15102      * @param flags Constant indicating the value which should be set
15103      * @param mask Constant indicating the bit range that should be changed
15104      */
15105     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
setFlags(int flags, int mask)15106     void setFlags(int flags, int mask) {
15107         final boolean accessibilityEnabled =
15108                 AccessibilityManager.getInstance(mContext).isEnabled();
15109         final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
15110 
15111         int old = mViewFlags;
15112         mViewFlags = (mViewFlags & ~mask) | (flags & mask);
15113 
15114         int changed = mViewFlags ^ old;
15115         if (changed == 0) {
15116             return;
15117         }
15118         int privateFlags = mPrivateFlags;
15119         boolean shouldNotifyFocusableAvailable = false;
15120 
15121         // If focusable is auto, update the FOCUSABLE bit.
15122         int focusableChangedByAuto = 0;
15123         if (((mViewFlags & FOCUSABLE_AUTO) != 0)
15124                 && (changed & (FOCUSABLE_MASK | CLICKABLE)) != 0) {
15125             // Heuristic only takes into account whether view is clickable.
15126             final int newFocus;
15127             if ((mViewFlags & CLICKABLE) != 0) {
15128                 newFocus = FOCUSABLE;
15129             } else {
15130                 newFocus = NOT_FOCUSABLE;
15131             }
15132             mViewFlags = (mViewFlags & ~FOCUSABLE) | newFocus;
15133             focusableChangedByAuto = (old & FOCUSABLE) ^ (newFocus & FOCUSABLE);
15134             changed = (changed & ~FOCUSABLE) | focusableChangedByAuto;
15135         }
15136 
15137         /* Check if the FOCUSABLE bit has changed */
15138         if (((changed & FOCUSABLE) != 0) && ((privateFlags & PFLAG_HAS_BOUNDS) != 0)) {
15139             if (((old & FOCUSABLE) == FOCUSABLE)
15140                     && ((privateFlags & PFLAG_FOCUSED) != 0)) {
15141                 /* Give up focus if we are no longer focusable */
15142                 clearFocus();
15143                 if (mParent instanceof ViewGroup) {
15144                     ((ViewGroup) mParent).clearFocusedInCluster();
15145                 }
15146             } else if (((old & FOCUSABLE) == NOT_FOCUSABLE)
15147                     && ((privateFlags & PFLAG_FOCUSED) == 0)) {
15148                 /*
15149                  * Tell the view system that we are now available to take focus
15150                  * if no one else already has it.
15151                  */
15152                 if (mParent != null) {
15153                     ViewRootImpl viewRootImpl = getViewRootImpl();
15154                     if (!sAutoFocusableOffUIThreadWontNotifyParents
15155                             || focusableChangedByAuto == 0
15156                             || viewRootImpl == null
15157                             || viewRootImpl.mThread == Thread.currentThread()) {
15158                         shouldNotifyFocusableAvailable = canTakeFocus();
15159                     }
15160                 }
15161             }
15162         }
15163 
15164         final int newVisibility = flags & VISIBILITY_MASK;
15165         if (newVisibility == VISIBLE) {
15166             if ((changed & VISIBILITY_MASK) != 0) {
15167                 /*
15168                  * If this view is becoming visible, invalidate it in case it changed while
15169                  * it was not visible. Marking it drawn ensures that the invalidation will
15170                  * go through.
15171                  */
15172                 mPrivateFlags |= PFLAG_DRAWN;
15173                 invalidate(true);
15174 
15175                 needGlobalAttributesUpdate(true);
15176 
15177                 // a view becoming visible is worth notifying the parent about in case nothing has
15178                 // focus. Even if this specific view isn't focusable, it may contain something that
15179                 // is, so let the root view try to give this focus if nothing else does.
15180                 shouldNotifyFocusableAvailable = hasSize();
15181             }
15182         }
15183 
15184         if ((changed & ENABLED_MASK) != 0) {
15185             if ((mViewFlags & ENABLED_MASK) == ENABLED) {
15186                 // a view becoming enabled should notify the parent as long as the view is also
15187                 // visible and the parent wasn't already notified by becoming visible during this
15188                 // setFlags invocation.
15189                 shouldNotifyFocusableAvailable = canTakeFocus();
15190             } else {
15191                 if (isFocused()) clearFocus();
15192             }
15193         }
15194 
15195         if (shouldNotifyFocusableAvailable && mParent != null) {
15196             mParent.focusableViewAvailable(this);
15197         }
15198 
15199         /* Check if the GONE bit has changed */
15200         if ((changed & GONE) != 0) {
15201             needGlobalAttributesUpdate(false);
15202             requestLayout();
15203 
15204             if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
15205                 if (hasFocus()) {
15206                     clearFocus();
15207                     if (mParent instanceof ViewGroup) {
15208                         ((ViewGroup) mParent).clearFocusedInCluster();
15209                     }
15210                 }
15211                 clearAccessibilityFocus();
15212                 destroyDrawingCache();
15213                 if (mParent instanceof View) {
15214                     // GONE views noop invalidation, so invalidate the parent
15215                     ((View) mParent).invalidate(true);
15216                 }
15217                 // Mark the view drawn to ensure that it gets invalidated properly the next
15218                 // time it is visible and gets invalidated
15219                 mPrivateFlags |= PFLAG_DRAWN;
15220             }
15221             if (mAttachInfo != null) {
15222                 mAttachInfo.mViewVisibilityChanged = true;
15223             }
15224         }
15225 
15226         /* Check if the VISIBLE bit has changed */
15227         if ((changed & INVISIBLE) != 0) {
15228             needGlobalAttributesUpdate(false);
15229             /*
15230              * If this view is becoming invisible, set the DRAWN flag so that
15231              * the next invalidate() will not be skipped.
15232              */
15233             mPrivateFlags |= PFLAG_DRAWN;
15234 
15235             if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
15236                 // root view becoming invisible shouldn't clear focus and accessibility focus
15237                 if (getRootView() != this) {
15238                     if (hasFocus()) {
15239                         clearFocus();
15240                         if (mParent instanceof ViewGroup) {
15241                             ((ViewGroup) mParent).clearFocusedInCluster();
15242                         }
15243                     }
15244                     clearAccessibilityFocus();
15245                 }
15246             }
15247             if (mAttachInfo != null) {
15248                 mAttachInfo.mViewVisibilityChanged = true;
15249             }
15250         }
15251 
15252         if ((changed & VISIBILITY_MASK) != 0) {
15253             // If the view is invisible, cleanup its display list to free up resources
15254             if (newVisibility != VISIBLE && mAttachInfo != null) {
15255                 cleanupDraw();
15256             }
15257 
15258             if (mParent instanceof ViewGroup) {
15259                 ViewGroup parent = (ViewGroup) mParent;
15260                 parent.onChildVisibilityChanged(this, (changed & VISIBILITY_MASK),
15261                         newVisibility);
15262                 parent.invalidate(true);
15263             } else if (mParent != null) {
15264                 mParent.invalidateChild(this, null);
15265             }
15266 
15267             if (mAttachInfo != null) {
15268                 dispatchVisibilityChanged(this, newVisibility);
15269 
15270                 // Aggregated visibility changes are dispatched to attached views
15271                 // in visible windows where the parent is currently shown/drawn
15272                 // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
15273                 // discounting clipping or overlapping. This makes it a good place
15274                 // to change animation states.
15275                 if (mParent != null && getWindowVisibility() == VISIBLE &&
15276                         ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
15277                     dispatchVisibilityAggregated(newVisibility == VISIBLE);
15278                 }
15279                 notifySubtreeAccessibilityStateChangedIfNeeded();
15280             }
15281         }
15282 
15283         if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
15284             destroyDrawingCache();
15285         }
15286 
15287         if ((changed & DRAWING_CACHE_ENABLED) != 0) {
15288             destroyDrawingCache();
15289             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
15290             invalidateParentCaches();
15291         }
15292 
15293         if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
15294             destroyDrawingCache();
15295             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
15296         }
15297 
15298         if ((changed & DRAW_MASK) != 0) {
15299             if ((mViewFlags & WILL_NOT_DRAW) != 0) {
15300                 if (mBackground != null
15301                         || mDefaultFocusHighlight != null
15302                         || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
15303                     mPrivateFlags &= ~PFLAG_SKIP_DRAW;
15304                 } else {
15305                     mPrivateFlags |= PFLAG_SKIP_DRAW;
15306                 }
15307             } else {
15308                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
15309             }
15310             requestLayout();
15311             invalidate(true);
15312         }
15313 
15314         if ((changed & KEEP_SCREEN_ON) != 0) {
15315             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
15316                 mParent.recomputeViewAttributes(this);
15317             }
15318         }
15319 
15320         if (accessibilityEnabled) {
15321             // If we're an accessibility pane and the visibility changed, we already have sent
15322             // a state change, so we really don't need to report other changes.
15323             if (isAccessibilityPane()) {
15324                 changed &= ~VISIBILITY_MASK;
15325             }
15326             if ((changed & FOCUSABLE) != 0 || (changed & VISIBILITY_MASK) != 0
15327                     || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
15328                     || (changed & CONTEXT_CLICKABLE) != 0) {
15329                 if (oldIncludeForAccessibility != includeForAccessibility()) {
15330                     notifySubtreeAccessibilityStateChangedIfNeeded();
15331                 } else {
15332                     notifyViewAccessibilityStateChangedIfNeeded(
15333                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
15334                 }
15335             } else if ((changed & ENABLED_MASK) != 0) {
15336                 notifyViewAccessibilityStateChangedIfNeeded(
15337                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
15338             }
15339         }
15340     }
15341 
15342     /**
15343      * Change the view's z order in the tree, so it's on top of other sibling
15344      * views. This ordering change may affect layout, if the parent container
15345      * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
15346      * to {@link android.os.Build.VERSION_CODES#KITKAT} this
15347      * method should be followed by calls to {@link #requestLayout()} and
15348      * {@link View#invalidate()} on the view's parent to force the parent to redraw
15349      * with the new child ordering.
15350      *
15351      * @see ViewGroup#bringChildToFront(View)
15352      */
bringToFront()15353     public void bringToFront() {
15354         if (mParent != null) {
15355             mParent.bringChildToFront(this);
15356         }
15357     }
15358 
15359     /**
15360      * This is called in response to an internal scroll in this view (i.e., the
15361      * view scrolled its own contents). This is typically as a result of
15362      * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
15363      * called.
15364      *
15365      * @param l Current horizontal scroll origin.
15366      * @param t Current vertical scroll origin.
15367      * @param oldl Previous horizontal scroll origin.
15368      * @param oldt Previous vertical scroll origin.
15369      */
onScrollChanged(int l, int t, int oldl, int oldt)15370     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
15371         notifySubtreeAccessibilityStateChangedIfNeeded();
15372 
15373         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
15374             postSendViewScrolledAccessibilityEventCallback(l - oldl, t - oldt);
15375         }
15376 
15377         mBackgroundSizeChanged = true;
15378         mDefaultFocusHighlightSizeChanged = true;
15379         if (mForegroundInfo != null) {
15380             mForegroundInfo.mBoundsChanged = true;
15381         }
15382 
15383         final AttachInfo ai = mAttachInfo;
15384         if (ai != null) {
15385             ai.mViewScrollChanged = true;
15386         }
15387 
15388         if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
15389             mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
15390         }
15391     }
15392 
15393     /**
15394      * Interface definition for a callback to be invoked when the scroll
15395      * X or Y positions of a view change.
15396      * <p>
15397      * <b>Note:</b> Some views handle scrolling independently from View and may
15398      * have their own separate listeners for scroll-type events. For example,
15399      * {@link android.widget.ListView ListView} allows clients to register an
15400      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
15401      * to listen for changes in list scroll position.
15402      *
15403      * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
15404      */
15405     public interface OnScrollChangeListener {
15406         /**
15407          * Called when the scroll position of a view changes.
15408          *
15409          * @param v The view whose scroll position has changed.
15410          * @param scrollX Current horizontal scroll origin.
15411          * @param scrollY Current vertical scroll origin.
15412          * @param oldScrollX Previous horizontal scroll origin.
15413          * @param oldScrollY Previous vertical scroll origin.
15414          */
onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY)15415         void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
15416     }
15417 
15418     /**
15419      * Interface definition for a callback to be invoked when the layout bounds of a view
15420      * changes due to layout processing.
15421      */
15422     public interface OnLayoutChangeListener {
15423         /**
15424          * Called when the layout bounds of a view changes due to layout processing.
15425          *
15426          * @param v The view whose bounds have changed.
15427          * @param left The new value of the view's left property.
15428          * @param top The new value of the view's top property.
15429          * @param right The new value of the view's right property.
15430          * @param bottom The new value of the view's bottom property.
15431          * @param oldLeft The previous value of the view's left property.
15432          * @param oldTop The previous value of the view's top property.
15433          * @param oldRight The previous value of the view's right property.
15434          * @param oldBottom The previous value of the view's bottom property.
15435          */
onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom)15436         void onLayoutChange(View v, int left, int top, int right, int bottom,
15437             int oldLeft, int oldTop, int oldRight, int oldBottom);
15438     }
15439 
15440     /**
15441      * This is called during layout when the size of this view has changed. If
15442      * you were just added to the view hierarchy, you're called with the old
15443      * values of 0.
15444      *
15445      * @param w Current width of this view.
15446      * @param h Current height of this view.
15447      * @param oldw Old width of this view.
15448      * @param oldh Old height of this view.
15449      */
onSizeChanged(int w, int h, int oldw, int oldh)15450     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
15451     }
15452 
15453     /**
15454      * Called by draw to draw the child views. This may be overridden
15455      * by derived classes to gain control just before its children are drawn
15456      * (but after its own view has been drawn).
15457      * @param canvas the canvas on which to draw the view
15458      */
dispatchDraw(Canvas canvas)15459     protected void dispatchDraw(Canvas canvas) {
15460 
15461     }
15462 
15463     /**
15464      * Gets the parent of this view. Note that the parent is a
15465      * ViewParent and not necessarily a View.
15466      *
15467      * @return Parent of this view.
15468      */
getParent()15469     public final ViewParent getParent() {
15470         return mParent;
15471     }
15472 
15473     /**
15474      * Set the horizontal scrolled position of your view. This will cause a call to
15475      * {@link #onScrollChanged(int, int, int, int)} and the view will be
15476      * invalidated.
15477      * @param value the x position to scroll to
15478      */
setScrollX(int value)15479     public void setScrollX(int value) {
15480         scrollTo(value, mScrollY);
15481     }
15482 
15483     /**
15484      * Set the vertical scrolled position of your view. This will cause a call to
15485      * {@link #onScrollChanged(int, int, int, int)} and the view will be
15486      * invalidated.
15487      * @param value the y position to scroll to
15488      */
setScrollY(int value)15489     public void setScrollY(int value) {
15490         scrollTo(mScrollX, value);
15491     }
15492 
15493     /**
15494      * Return the scrolled left position of this view. This is the left edge of
15495      * the displayed part of your view. You do not need to draw any pixels
15496      * farther left, since those are outside of the frame of your view on
15497      * screen.
15498      *
15499      * @return The left edge of the displayed part of your view, in pixels.
15500      */
15501     @InspectableProperty
getScrollX()15502     public final int getScrollX() {
15503         return mScrollX;
15504     }
15505 
15506     /**
15507      * Return the scrolled top position of this view. This is the top edge of
15508      * the displayed part of your view. You do not need to draw any pixels above
15509      * it, since those are outside of the frame of your view on screen.
15510      *
15511      * @return The top edge of the displayed part of your view, in pixels.
15512      */
15513     @InspectableProperty
getScrollY()15514     public final int getScrollY() {
15515         return mScrollY;
15516     }
15517 
15518     /**
15519      * Return the width of your view.
15520      *
15521      * @return The width of your view, in pixels.
15522      */
15523     @ViewDebug.ExportedProperty(category = "layout")
getWidth()15524     public final int getWidth() {
15525         return mRight - mLeft;
15526     }
15527 
15528     /**
15529      * Return the height of your view.
15530      *
15531      * @return The height of your view, in pixels.
15532      */
15533     @ViewDebug.ExportedProperty(category = "layout")
getHeight()15534     public final int getHeight() {
15535         return mBottom - mTop;
15536     }
15537 
15538     /**
15539      * Return the visible drawing bounds of your view. Fills in the output
15540      * rectangle with the values from getScrollX(), getScrollY(),
15541      * getWidth(), and getHeight(). These bounds do not account for any
15542      * transformation properties currently set on the view, such as
15543      * {@link #setScaleX(float)} or {@link #setRotation(float)}.
15544      *
15545      * @param outRect The (scrolled) drawing bounds of the view.
15546      */
getDrawingRect(Rect outRect)15547     public void getDrawingRect(Rect outRect) {
15548         outRect.left = mScrollX;
15549         outRect.top = mScrollY;
15550         outRect.right = mScrollX + (mRight - mLeft);
15551         outRect.bottom = mScrollY + (mBottom - mTop);
15552     }
15553 
15554     /**
15555      * Like {@link #getMeasuredWidthAndState()}, but only returns the
15556      * raw width component (that is the result is masked by
15557      * {@link #MEASURED_SIZE_MASK}).
15558      *
15559      * @return The raw measured width of this view.
15560      */
getMeasuredWidth()15561     public final int getMeasuredWidth() {
15562         return mMeasuredWidth & MEASURED_SIZE_MASK;
15563     }
15564 
15565     /**
15566      * Return the full width measurement information for this view as computed
15567      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
15568      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
15569      * This should be used during measurement and layout calculations only. Use
15570      * {@link #getWidth()} to see how wide a view is after layout.
15571      *
15572      * @return The measured width of this view as a bit mask.
15573      */
15574     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
15575             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
15576                     name = "MEASURED_STATE_TOO_SMALL"),
15577     })
getMeasuredWidthAndState()15578     public final int getMeasuredWidthAndState() {
15579         return mMeasuredWidth;
15580     }
15581 
15582     /**
15583      * Like {@link #getMeasuredHeightAndState()}, but only returns the
15584      * raw height component (that is the result is masked by
15585      * {@link #MEASURED_SIZE_MASK}).
15586      *
15587      * @return The raw measured height of this view.
15588      */
getMeasuredHeight()15589     public final int getMeasuredHeight() {
15590         return mMeasuredHeight & MEASURED_SIZE_MASK;
15591     }
15592 
15593     /**
15594      * Return the full height measurement information for this view as computed
15595      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
15596      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
15597      * This should be used during measurement and layout calculations only. Use
15598      * {@link #getHeight()} to see how wide a view is after layout.
15599      *
15600      * @return The measured height of this view as a bit mask.
15601      */
15602     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
15603             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
15604                     name = "MEASURED_STATE_TOO_SMALL"),
15605     })
getMeasuredHeightAndState()15606     public final int getMeasuredHeightAndState() {
15607         return mMeasuredHeight;
15608     }
15609 
15610     /**
15611      * Return only the state bits of {@link #getMeasuredWidthAndState()}
15612      * and {@link #getMeasuredHeightAndState()}, combined into one integer.
15613      * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
15614      * and the height component is at the shifted bits
15615      * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
15616      */
getMeasuredState()15617     public final int getMeasuredState() {
15618         return (mMeasuredWidth&MEASURED_STATE_MASK)
15619                 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
15620                         & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
15621     }
15622 
15623     /**
15624      * The transform matrix of this view, which is calculated based on the current
15625      * rotation, scale, and pivot properties.
15626      *
15627      * @see #getRotation()
15628      * @see #getScaleX()
15629      * @see #getScaleY()
15630      * @see #getPivotX()
15631      * @see #getPivotY()
15632      * @return The current transform matrix for the view
15633      */
getMatrix()15634     public Matrix getMatrix() {
15635         ensureTransformationInfo();
15636         final Matrix matrix = mTransformationInfo.mMatrix;
15637         mRenderNode.getMatrix(matrix);
15638         return matrix;
15639     }
15640 
15641     /**
15642      * Returns true if the transform matrix is the identity matrix.
15643      * Recomputes the matrix if necessary.
15644      *
15645      * @return True if the transform matrix is the identity matrix, false otherwise.
15646      * @hide
15647      */
15648     @UnsupportedAppUsage
hasIdentityMatrix()15649     public final boolean hasIdentityMatrix() {
15650         return mRenderNode.hasIdentityMatrix();
15651     }
15652 
15653     @UnsupportedAppUsage
ensureTransformationInfo()15654     void ensureTransformationInfo() {
15655         if (mTransformationInfo == null) {
15656             mTransformationInfo = new TransformationInfo();
15657         }
15658     }
15659 
15660     /**
15661      * Utility method to retrieve the inverse of the current mMatrix property.
15662      * We cache the matrix to avoid recalculating it when transform properties
15663      * have not changed.
15664      *
15665      * @return The inverse of the current matrix of this view.
15666      * @hide
15667      */
15668     @UnsupportedAppUsage
getInverseMatrix()15669     public final Matrix getInverseMatrix() {
15670         ensureTransformationInfo();
15671         if (mTransformationInfo.mInverseMatrix == null) {
15672             mTransformationInfo.mInverseMatrix = new Matrix();
15673         }
15674         final Matrix matrix = mTransformationInfo.mInverseMatrix;
15675         mRenderNode.getInverseMatrix(matrix);
15676         return matrix;
15677     }
15678 
15679     /**
15680      * Gets the distance along the Z axis from the camera to this view.
15681      *
15682      * @see #setCameraDistance(float)
15683      *
15684      * @return The distance along the Z axis.
15685      */
getCameraDistance()15686     public float getCameraDistance() {
15687         final float dpi = mResources.getDisplayMetrics().densityDpi;
15688         return mRenderNode.getCameraDistance() * dpi;
15689     }
15690 
15691     /**
15692      * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
15693      * views are drawn) from the camera to this view. The camera's distance
15694      * affects 3D transformations, for instance rotations around the X and Y
15695      * axis. If the rotationX or rotationY properties are changed and this view is
15696      * large (more than half the size of the screen), it is recommended to always
15697      * use a camera distance that's greater than the height (X axis rotation) or
15698      * the width (Y axis rotation) of this view.</p>
15699      *
15700      * <p>The distance of the camera from the view plane can have an affect on the
15701      * perspective distortion of the view when it is rotated around the x or y axis.
15702      * For example, a large distance will result in a large viewing angle, and there
15703      * will not be much perspective distortion of the view as it rotates. A short
15704      * distance may cause much more perspective distortion upon rotation, and can
15705      * also result in some drawing artifacts if the rotated view ends up partially
15706      * behind the camera (which is why the recommendation is to use a distance at
15707      * least as far as the size of the view, if the view is to be rotated.)</p>
15708      *
15709      * <p>The distance is expressed in "depth pixels." The default distance depends
15710      * on the screen density. For instance, on a medium density display, the
15711      * default distance is 1280. On a high density display, the default distance
15712      * is 1920.</p>
15713      *
15714      * <p>If you want to specify a distance that leads to visually consistent
15715      * results across various densities, use the following formula:</p>
15716      * <pre>
15717      * float scale = context.getResources().getDisplayMetrics().density;
15718      * view.setCameraDistance(distance * scale);
15719      * </pre>
15720      *
15721      * <p>The density scale factor of a high density display is 1.5,
15722      * and 1920 = 1280 * 1.5.</p>
15723      *
15724      * @param distance The distance in "depth pixels", if negative the opposite
15725      *        value is used
15726      *
15727      * @see #setRotationX(float)
15728      * @see #setRotationY(float)
15729      */
setCameraDistance(float distance)15730     public void setCameraDistance(float distance) {
15731         final float dpi = mResources.getDisplayMetrics().densityDpi;
15732 
15733         invalidateViewProperty(true, false);
15734         mRenderNode.setCameraDistance(Math.abs(distance) / dpi);
15735         invalidateViewProperty(false, false);
15736 
15737         invalidateParentIfNeededAndWasQuickRejected();
15738     }
15739 
15740     /**
15741      * The degrees that the view is rotated around the pivot point.
15742      *
15743      * @see #setRotation(float)
15744      * @see #getPivotX()
15745      * @see #getPivotY()
15746      *
15747      * @return The degrees of rotation.
15748      */
15749     @ViewDebug.ExportedProperty(category = "drawing")
15750     @InspectableProperty
getRotation()15751     public float getRotation() {
15752         return mRenderNode.getRotationZ();
15753     }
15754 
15755     /**
15756      * Sets the degrees that the view is rotated around the pivot point. Increasing values
15757      * result in clockwise rotation.
15758      *
15759      * @param rotation The degrees of rotation.
15760      *
15761      * @see #getRotation()
15762      * @see #getPivotX()
15763      * @see #getPivotY()
15764      * @see #setRotationX(float)
15765      * @see #setRotationY(float)
15766      *
15767      * @attr ref android.R.styleable#View_rotation
15768      */
setRotation(float rotation)15769     public void setRotation(float rotation) {
15770         if (rotation != getRotation()) {
15771             // Double-invalidation is necessary to capture view's old and new areas
15772             invalidateViewProperty(true, false);
15773             mRenderNode.setRotationZ(rotation);
15774             invalidateViewProperty(false, true);
15775 
15776             invalidateParentIfNeededAndWasQuickRejected();
15777             notifySubtreeAccessibilityStateChangedIfNeeded();
15778         }
15779     }
15780 
15781     /**
15782      * The degrees that the view is rotated around the vertical axis through the pivot point.
15783      *
15784      * @see #getPivotX()
15785      * @see #getPivotY()
15786      * @see #setRotationY(float)
15787      *
15788      * @return The degrees of Y rotation.
15789      */
15790     @ViewDebug.ExportedProperty(category = "drawing")
15791     @InspectableProperty
getRotationY()15792     public float getRotationY() {
15793         return mRenderNode.getRotationY();
15794     }
15795 
15796     /**
15797      * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
15798      * Increasing values result in counter-clockwise rotation from the viewpoint of looking
15799      * down the y axis.
15800      *
15801      * When rotating large views, it is recommended to adjust the camera distance
15802      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
15803      *
15804      * @param rotationY The degrees of Y rotation.
15805      *
15806      * @see #getRotationY()
15807      * @see #getPivotX()
15808      * @see #getPivotY()
15809      * @see #setRotation(float)
15810      * @see #setRotationX(float)
15811      * @see #setCameraDistance(float)
15812      *
15813      * @attr ref android.R.styleable#View_rotationY
15814      */
setRotationY(float rotationY)15815     public void setRotationY(float rotationY) {
15816         if (rotationY != getRotationY()) {
15817             invalidateViewProperty(true, false);
15818             mRenderNode.setRotationY(rotationY);
15819             invalidateViewProperty(false, true);
15820 
15821             invalidateParentIfNeededAndWasQuickRejected();
15822             notifySubtreeAccessibilityStateChangedIfNeeded();
15823         }
15824     }
15825 
15826     /**
15827      * The degrees that the view is rotated around the horizontal axis through the pivot point.
15828      *
15829      * @see #getPivotX()
15830      * @see #getPivotY()
15831      * @see #setRotationX(float)
15832      *
15833      * @return The degrees of X rotation.
15834      */
15835     @ViewDebug.ExportedProperty(category = "drawing")
15836     @InspectableProperty
getRotationX()15837     public float getRotationX() {
15838         return mRenderNode.getRotationX();
15839     }
15840 
15841     /**
15842      * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
15843      * Increasing values result in clockwise rotation from the viewpoint of looking down the
15844      * x axis.
15845      *
15846      * When rotating large views, it is recommended to adjust the camera distance
15847      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
15848      *
15849      * @param rotationX The degrees of X rotation.
15850      *
15851      * @see #getRotationX()
15852      * @see #getPivotX()
15853      * @see #getPivotY()
15854      * @see #setRotation(float)
15855      * @see #setRotationY(float)
15856      * @see #setCameraDistance(float)
15857      *
15858      * @attr ref android.R.styleable#View_rotationX
15859      */
setRotationX(float rotationX)15860     public void setRotationX(float rotationX) {
15861         if (rotationX != getRotationX()) {
15862             invalidateViewProperty(true, false);
15863             mRenderNode.setRotationX(rotationX);
15864             invalidateViewProperty(false, true);
15865 
15866             invalidateParentIfNeededAndWasQuickRejected();
15867             notifySubtreeAccessibilityStateChangedIfNeeded();
15868         }
15869     }
15870 
15871     /**
15872      * The amount that the view is scaled in x around the pivot point, as a proportion of
15873      * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
15874      *
15875      * <p>By default, this is 1.0f.
15876      *
15877      * @see #getPivotX()
15878      * @see #getPivotY()
15879      * @return The scaling factor.
15880      */
15881     @ViewDebug.ExportedProperty(category = "drawing")
15882     @InspectableProperty
getScaleX()15883     public float getScaleX() {
15884         return mRenderNode.getScaleX();
15885     }
15886 
15887     /**
15888      * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
15889      * the view's unscaled width. A value of 1 means that no scaling is applied.
15890      *
15891      * @param scaleX The scaling factor.
15892      * @see #getPivotX()
15893      * @see #getPivotY()
15894      *
15895      * @attr ref android.R.styleable#View_scaleX
15896      */
setScaleX(float scaleX)15897     public void setScaleX(float scaleX) {
15898         if (scaleX != getScaleX()) {
15899             scaleX = sanitizeFloatPropertyValue(scaleX, "scaleX");
15900             invalidateViewProperty(true, false);
15901             mRenderNode.setScaleX(scaleX);
15902             invalidateViewProperty(false, true);
15903 
15904             invalidateParentIfNeededAndWasQuickRejected();
15905             notifySubtreeAccessibilityStateChangedIfNeeded();
15906         }
15907     }
15908 
15909     /**
15910      * The amount that the view is scaled in y around the pivot point, as a proportion of
15911      * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
15912      *
15913      * <p>By default, this is 1.0f.
15914      *
15915      * @see #getPivotX()
15916      * @see #getPivotY()
15917      * @return The scaling factor.
15918      */
15919     @ViewDebug.ExportedProperty(category = "drawing")
15920     @InspectableProperty
getScaleY()15921     public float getScaleY() {
15922         return mRenderNode.getScaleY();
15923     }
15924 
15925     /**
15926      * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
15927      * the view's unscaled width. A value of 1 means that no scaling is applied.
15928      *
15929      * @param scaleY The scaling factor.
15930      * @see #getPivotX()
15931      * @see #getPivotY()
15932      *
15933      * @attr ref android.R.styleable#View_scaleY
15934      */
setScaleY(float scaleY)15935     public void setScaleY(float scaleY) {
15936         if (scaleY != getScaleY()) {
15937             scaleY = sanitizeFloatPropertyValue(scaleY, "scaleY");
15938             invalidateViewProperty(true, false);
15939             mRenderNode.setScaleY(scaleY);
15940             invalidateViewProperty(false, true);
15941 
15942             invalidateParentIfNeededAndWasQuickRejected();
15943             notifySubtreeAccessibilityStateChangedIfNeeded();
15944         }
15945     }
15946 
15947     /**
15948      * The x location of the point around which the view is {@link #setRotation(float) rotated}
15949      * and {@link #setScaleX(float) scaled}.
15950      *
15951      * @see #getRotation()
15952      * @see #getScaleX()
15953      * @see #getScaleY()
15954      * @see #getPivotY()
15955      * @return The x location of the pivot point.
15956      *
15957      * @attr ref android.R.styleable#View_transformPivotX
15958      */
15959     @ViewDebug.ExportedProperty(category = "drawing")
15960     @InspectableProperty(name = "transformPivotX")
getPivotX()15961     public float getPivotX() {
15962         return mRenderNode.getPivotX();
15963     }
15964 
15965     /**
15966      * Sets the x location of the point around which the view is
15967      * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
15968      * By default, the pivot point is centered on the object.
15969      * Setting this property disables this behavior and causes the view to use only the
15970      * explicitly set pivotX and pivotY values.
15971      *
15972      * @param pivotX The x location of the pivot point.
15973      * @see #getRotation()
15974      * @see #getScaleX()
15975      * @see #getScaleY()
15976      * @see #getPivotY()
15977      *
15978      * @attr ref android.R.styleable#View_transformPivotX
15979      */
setPivotX(float pivotX)15980     public void setPivotX(float pivotX) {
15981         if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
15982             invalidateViewProperty(true, false);
15983             mRenderNode.setPivotX(pivotX);
15984             invalidateViewProperty(false, true);
15985 
15986             invalidateParentIfNeededAndWasQuickRejected();
15987         }
15988     }
15989 
15990     /**
15991      * The y location of the point around which the view is {@link #setRotation(float) rotated}
15992      * and {@link #setScaleY(float) scaled}.
15993      *
15994      * @see #getRotation()
15995      * @see #getScaleX()
15996      * @see #getScaleY()
15997      * @see #getPivotY()
15998      * @return The y location of the pivot point.
15999      *
16000      * @attr ref android.R.styleable#View_transformPivotY
16001      */
16002     @ViewDebug.ExportedProperty(category = "drawing")
16003     @InspectableProperty(name = "transformPivotY")
getPivotY()16004     public float getPivotY() {
16005         return mRenderNode.getPivotY();
16006     }
16007 
16008     /**
16009      * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
16010      * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
16011      * Setting this property disables this behavior and causes the view to use only the
16012      * explicitly set pivotX and pivotY values.
16013      *
16014      * @param pivotY The y location of the pivot point.
16015      * @see #getRotation()
16016      * @see #getScaleX()
16017      * @see #getScaleY()
16018      * @see #getPivotY()
16019      *
16020      * @attr ref android.R.styleable#View_transformPivotY
16021      */
setPivotY(float pivotY)16022     public void setPivotY(float pivotY) {
16023         if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
16024             invalidateViewProperty(true, false);
16025             mRenderNode.setPivotY(pivotY);
16026             invalidateViewProperty(false, true);
16027 
16028             invalidateParentIfNeededAndWasQuickRejected();
16029         }
16030     }
16031 
16032     /**
16033      * Returns whether or not a pivot has been set by a call to {@link #setPivotX(float)} or
16034      * {@link #setPivotY(float)}. If no pivot has been set then the pivot will be the center
16035      * of the view.
16036      *
16037      * @return True if a pivot has been set, false if the default pivot is being used
16038      */
isPivotSet()16039     public boolean isPivotSet() {
16040         return mRenderNode.isPivotExplicitlySet();
16041     }
16042 
16043     /**
16044      * Clears any pivot previously set by a call to  {@link #setPivotX(float)} or
16045      * {@link #setPivotY(float)}. After calling this {@link #isPivotSet()} will be false
16046      * and the pivot used for rotation will return to default of being centered on the view.
16047      */
resetPivot()16048     public void resetPivot() {
16049         if (mRenderNode.resetPivot()) {
16050             invalidateViewProperty(false, false);
16051         }
16052     }
16053 
16054     /**
16055      * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
16056      * completely transparent and 1 means the view is completely opaque.
16057      *
16058      * <p>By default this is 1.0f.
16059      * @return The opacity of the view.
16060      */
16061     @ViewDebug.ExportedProperty(category = "drawing")
16062     @InspectableProperty
getAlpha()16063     public float getAlpha() {
16064         return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
16065     }
16066 
16067     /**
16068      * Sets the behavior for overlapping rendering for this view (see {@link
16069      * #hasOverlappingRendering()} for more details on this behavior). Calling this method
16070      * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
16071      * providing the value which is then used internally. That is, when {@link
16072      * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
16073      * #hasOverlappingRendering()} is ignored and the value passed into this method is used
16074      * instead.
16075      *
16076      * @param hasOverlappingRendering The value for overlapping rendering to be used internally
16077      * instead of that returned by {@link #hasOverlappingRendering()}.
16078      *
16079      * @attr ref android.R.styleable#View_forceHasOverlappingRendering
16080      */
forceHasOverlappingRendering(boolean hasOverlappingRendering)16081     public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
16082         mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
16083         if (hasOverlappingRendering) {
16084             mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
16085         } else {
16086             mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
16087         }
16088     }
16089 
16090     /**
16091      * Returns the value for overlapping rendering that is used internally. This is either
16092      * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
16093      * the return value of {@link #hasOverlappingRendering()}, otherwise.
16094      *
16095      * @return The value for overlapping rendering being used internally.
16096      */
getHasOverlappingRendering()16097     public final boolean getHasOverlappingRendering() {
16098         return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
16099                 (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
16100                 hasOverlappingRendering();
16101     }
16102 
16103     /**
16104      * Returns whether this View has content which overlaps.
16105      *
16106      * <p>This function, intended to be overridden by specific View types, is an optimization when
16107      * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
16108      * an offscreen buffer and then composited into place, which can be expensive. If the view has
16109      * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
16110      * directly. An example of overlapping rendering is a TextView with a background image, such as
16111      * a Button. An example of non-overlapping rendering is a TextView with no background, or an
16112      * ImageView with only the foreground image. The default implementation returns true; subclasses
16113      * should override if they have cases which can be optimized.</p>
16114      *
16115      * <p><strong>Note:</strong> The return value of this method is ignored if {@link
16116      * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
16117      *
16118      * @return true if the content in this view might overlap, false otherwise.
16119      */
16120     @ViewDebug.ExportedProperty(category = "drawing")
hasOverlappingRendering()16121     public boolean hasOverlappingRendering() {
16122         return true;
16123     }
16124 
16125     /**
16126      * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
16127      * completely transparent and 1 means the view is completely opaque.
16128      *
16129      * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
16130      * can have significant performance implications, especially for large views. It is best to use
16131      * the alpha property sparingly and transiently, as in the case of fading animations.</p>
16132      *
16133      * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
16134      * strongly recommended for performance reasons to either override
16135      * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
16136      * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
16137      * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
16138      * the default path for rendering an unlayered View with alpha could add multiple milliseconds
16139      * of rendering cost, even for simple or small views. Starting with
16140      * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
16141      * applied to the view at the rendering level.</p>
16142      *
16143      * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
16144      * responsible for applying the opacity itself.</p>
16145      *
16146      * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
16147      * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
16148      * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
16149      * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
16150      *
16151      * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
16152      * value will clip a View to its bounds, unless the View returns <code>false</code> from
16153      * {@link #hasOverlappingRendering}.</p>
16154      *
16155      * @param alpha The opacity of the view.
16156      *
16157      * @see #hasOverlappingRendering()
16158      * @see #setLayerType(int, android.graphics.Paint)
16159      *
16160      * @attr ref android.R.styleable#View_alpha
16161      */
setAlpha(@loatRangefrom=0.0, to=1.0) float alpha)16162     public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
16163         ensureTransformationInfo();
16164         if (mTransformationInfo.mAlpha != alpha) {
16165             setAlphaInternal(alpha);
16166             if (onSetAlpha((int) (alpha * 255))) {
16167                 mPrivateFlags |= PFLAG_ALPHA_SET;
16168                 // subclass is handling alpha - don't optimize rendering cache invalidation
16169                 invalidateParentCaches();
16170                 invalidate(true);
16171             } else {
16172                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
16173                 invalidateViewProperty(true, false);
16174                 mRenderNode.setAlpha(getFinalAlpha());
16175             }
16176         }
16177     }
16178 
16179     /**
16180      * Faster version of setAlpha() which performs the same steps except there are
16181      * no calls to invalidate(). The caller of this function should perform proper invalidation
16182      * on the parent and this object. The return value indicates whether the subclass handles
16183      * alpha (the return value for onSetAlpha()).
16184      *
16185      * @param alpha The new value for the alpha property
16186      * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
16187      *         the new value for the alpha property is different from the old value
16188      */
16189     @UnsupportedAppUsage(maxTargetSdk  = Build.VERSION_CODES.P, trackingBug = 123768435)
setAlphaNoInvalidation(float alpha)16190     boolean setAlphaNoInvalidation(float alpha) {
16191         ensureTransformationInfo();
16192         if (mTransformationInfo.mAlpha != alpha) {
16193             setAlphaInternal(alpha);
16194             boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
16195             if (subclassHandlesAlpha) {
16196                 mPrivateFlags |= PFLAG_ALPHA_SET;
16197                 return true;
16198             } else {
16199                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
16200                 mRenderNode.setAlpha(getFinalAlpha());
16201             }
16202         }
16203         return false;
16204     }
16205 
setAlphaInternal(float alpha)16206     void setAlphaInternal(float alpha) {
16207         float oldAlpha = mTransformationInfo.mAlpha;
16208         mTransformationInfo.mAlpha = alpha;
16209         // Report visibility changes, which can affect children, to accessibility
16210         if ((alpha == 0) ^ (oldAlpha == 0)) {
16211             notifySubtreeAccessibilityStateChangedIfNeeded();
16212         }
16213     }
16214 
16215     /**
16216      * This property is intended only for use by the Fade transition, which animates it
16217      * to produce a visual translucency that does not side-effect (or get affected by)
16218      * the real alpha property. This value is composited with the other alpha value
16219      * (and the AlphaAnimation value, when that is present) to produce a final visual
16220      * translucency result, which is what is passed into the DisplayList.
16221      */
setTransitionAlpha(float alpha)16222     public void setTransitionAlpha(float alpha) {
16223         ensureTransformationInfo();
16224         if (mTransformationInfo.mTransitionAlpha != alpha) {
16225             mTransformationInfo.mTransitionAlpha = alpha;
16226             mPrivateFlags &= ~PFLAG_ALPHA_SET;
16227             invalidateViewProperty(true, false);
16228             mRenderNode.setAlpha(getFinalAlpha());
16229         }
16230     }
16231 
16232     /**
16233      * Calculates the visual alpha of this view, which is a combination of the actual
16234      * alpha value and the transitionAlpha value (if set).
16235      */
getFinalAlpha()16236     private float getFinalAlpha() {
16237         if (mTransformationInfo != null) {
16238             return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
16239         }
16240         return 1;
16241     }
16242 
16243     /**
16244      * This property is intended only for use by the Fade transition, which animates
16245      * it to produce a visual translucency that does not side-effect (or get affected
16246      * by) the real alpha property. This value is composited with the other alpha
16247      * value (and the AlphaAnimation value, when that is present) to produce a final
16248      * visual translucency result, which is what is passed into the DisplayList.
16249      */
16250     @ViewDebug.ExportedProperty(category = "drawing")
getTransitionAlpha()16251     public float getTransitionAlpha() {
16252         return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
16253     }
16254 
16255     /**
16256      * Sets whether or not to allow force dark to apply to this view.
16257      *
16258      * Setting this to false will disable the auto-dark feature on everything this view
16259      * draws, including any descendants.
16260      *
16261      * Setting this to true will allow this view to be automatically made dark, however
16262      * a value of 'true' will not override any 'false' value in its parent chain nor will
16263      * it prevent any 'false' in any of its children.
16264      *
16265      * The default behavior of force dark is also influenced by the Theme's
16266      * {@link android.R.styleable#Theme_isLightTheme isLightTheme} attribute.
16267      * If a theme is isLightTheme="false", then force dark is globally disabled for that theme.
16268      *
16269      * @param allow Whether or not to allow force dark.
16270      */
setForceDarkAllowed(boolean allow)16271     public void setForceDarkAllowed(boolean allow) {
16272         if (mRenderNode.setForceDarkAllowed(allow)) {
16273             // Currently toggling force-dark requires a new display list push to apply
16274             // TODO: Make it not clobber the display list so this is just a damageSelf() instead
16275             invalidate();
16276         }
16277     }
16278 
16279     /**
16280      * See {@link #setForceDarkAllowed(boolean)}
16281      *
16282      * @return true if force dark is allowed (default), false if it is disabled
16283      */
16284     @ViewDebug.ExportedProperty(category = "drawing")
16285     @InspectableProperty
isForceDarkAllowed()16286     public boolean isForceDarkAllowed() {
16287         return mRenderNode.isForceDarkAllowed();
16288     }
16289 
16290     /**
16291      * Top position of this view relative to its parent.
16292      *
16293      * @return The top of this view, in pixels.
16294      */
16295     @ViewDebug.CapturedViewProperty
getTop()16296     public final int getTop() {
16297         return mTop;
16298     }
16299 
16300     /**
16301      * Sets the top position of this view relative to its parent. This method is meant to be called
16302      * by the layout system and should not generally be called otherwise, because the property
16303      * may be changed at any time by the layout.
16304      *
16305      * @param top The top of this view, in pixels.
16306      */
setTop(int top)16307     public final void setTop(int top) {
16308         if (top != mTop) {
16309             final boolean matrixIsIdentity = hasIdentityMatrix();
16310             if (matrixIsIdentity) {
16311                 if (mAttachInfo != null) {
16312                     int minTop;
16313                     int yLoc;
16314                     if (top < mTop) {
16315                         minTop = top;
16316                         yLoc = top - mTop;
16317                     } else {
16318                         minTop = mTop;
16319                         yLoc = 0;
16320                     }
16321                     invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
16322                 }
16323             } else {
16324                 // Double-invalidation is necessary to capture view's old and new areas
16325                 invalidate(true);
16326             }
16327 
16328             int width = mRight - mLeft;
16329             int oldHeight = mBottom - mTop;
16330 
16331             mTop = top;
16332             mRenderNode.setTop(mTop);
16333 
16334             sizeChange(width, mBottom - mTop, width, oldHeight);
16335 
16336             if (!matrixIsIdentity) {
16337                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
16338                 invalidate(true);
16339             }
16340             mBackgroundSizeChanged = true;
16341             mDefaultFocusHighlightSizeChanged = true;
16342             if (mForegroundInfo != null) {
16343                 mForegroundInfo.mBoundsChanged = true;
16344             }
16345             invalidateParentIfNeeded();
16346             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
16347                 // View was rejected last time it was drawn by its parent; this may have changed
16348                 invalidateParentIfNeeded();
16349             }
16350         }
16351     }
16352 
16353     /**
16354      * Bottom position of this view relative to its parent.
16355      *
16356      * @return The bottom of this view, in pixels.
16357      */
16358     @ViewDebug.CapturedViewProperty
getBottom()16359     public final int getBottom() {
16360         return mBottom;
16361     }
16362 
16363     /**
16364      * True if this view has changed since the last time being drawn.
16365      *
16366      * @return The dirty state of this view.
16367      */
isDirty()16368     public boolean isDirty() {
16369         return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
16370     }
16371 
16372     /**
16373      * Sets the bottom position of this view relative to its parent. This method is meant to be
16374      * called by the layout system and should not generally be called otherwise, because the
16375      * property may be changed at any time by the layout.
16376      *
16377      * @param bottom The bottom of this view, in pixels.
16378      */
setBottom(int bottom)16379     public final void setBottom(int bottom) {
16380         if (bottom != mBottom) {
16381             final boolean matrixIsIdentity = hasIdentityMatrix();
16382             if (matrixIsIdentity) {
16383                 if (mAttachInfo != null) {
16384                     int maxBottom;
16385                     if (bottom < mBottom) {
16386                         maxBottom = mBottom;
16387                     } else {
16388                         maxBottom = bottom;
16389                     }
16390                     invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
16391                 }
16392             } else {
16393                 // Double-invalidation is necessary to capture view's old and new areas
16394                 invalidate(true);
16395             }
16396 
16397             int width = mRight - mLeft;
16398             int oldHeight = mBottom - mTop;
16399 
16400             mBottom = bottom;
16401             mRenderNode.setBottom(mBottom);
16402 
16403             sizeChange(width, mBottom - mTop, width, oldHeight);
16404 
16405             if (!matrixIsIdentity) {
16406                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
16407                 invalidate(true);
16408             }
16409             mBackgroundSizeChanged = true;
16410             mDefaultFocusHighlightSizeChanged = true;
16411             if (mForegroundInfo != null) {
16412                 mForegroundInfo.mBoundsChanged = true;
16413             }
16414             invalidateParentIfNeeded();
16415             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
16416                 // View was rejected last time it was drawn by its parent; this may have changed
16417                 invalidateParentIfNeeded();
16418             }
16419         }
16420     }
16421 
16422     /**
16423      * Left position of this view relative to its parent.
16424      *
16425      * @return The left edge of this view, in pixels.
16426      */
16427     @ViewDebug.CapturedViewProperty
getLeft()16428     public final int getLeft() {
16429         return mLeft;
16430     }
16431 
16432     /**
16433      * Sets the left position of this view relative to its parent. This method is meant to be called
16434      * by the layout system and should not generally be called otherwise, because the property
16435      * may be changed at any time by the layout.
16436      *
16437      * @param left The left of this view, in pixels.
16438      */
setLeft(int left)16439     public final void setLeft(int left) {
16440         if (left != mLeft) {
16441             final boolean matrixIsIdentity = hasIdentityMatrix();
16442             if (matrixIsIdentity) {
16443                 if (mAttachInfo != null) {
16444                     int minLeft;
16445                     int xLoc;
16446                     if (left < mLeft) {
16447                         minLeft = left;
16448                         xLoc = left - mLeft;
16449                     } else {
16450                         minLeft = mLeft;
16451                         xLoc = 0;
16452                     }
16453                     invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
16454                 }
16455             } else {
16456                 // Double-invalidation is necessary to capture view's old and new areas
16457                 invalidate(true);
16458             }
16459 
16460             int oldWidth = mRight - mLeft;
16461             int height = mBottom - mTop;
16462 
16463             mLeft = left;
16464             mRenderNode.setLeft(left);
16465 
16466             sizeChange(mRight - mLeft, height, oldWidth, height);
16467 
16468             if (!matrixIsIdentity) {
16469                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
16470                 invalidate(true);
16471             }
16472             mBackgroundSizeChanged = true;
16473             mDefaultFocusHighlightSizeChanged = true;
16474             if (mForegroundInfo != null) {
16475                 mForegroundInfo.mBoundsChanged = true;
16476             }
16477             invalidateParentIfNeeded();
16478             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
16479                 // View was rejected last time it was drawn by its parent; this may have changed
16480                 invalidateParentIfNeeded();
16481             }
16482         }
16483     }
16484 
16485     /**
16486      * Right position of this view relative to its parent.
16487      *
16488      * @return The right edge of this view, in pixels.
16489      */
16490     @ViewDebug.CapturedViewProperty
getRight()16491     public final int getRight() {
16492         return mRight;
16493     }
16494 
16495     /**
16496      * Sets the right position of this view relative to its parent. This method is meant to be called
16497      * by the layout system and should not generally be called otherwise, because the property
16498      * may be changed at any time by the layout.
16499      *
16500      * @param right The right of this view, in pixels.
16501      */
setRight(int right)16502     public final void setRight(int right) {
16503         if (right != mRight) {
16504             final boolean matrixIsIdentity = hasIdentityMatrix();
16505             if (matrixIsIdentity) {
16506                 if (mAttachInfo != null) {
16507                     int maxRight;
16508                     if (right < mRight) {
16509                         maxRight = mRight;
16510                     } else {
16511                         maxRight = right;
16512                     }
16513                     invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
16514                 }
16515             } else {
16516                 // Double-invalidation is necessary to capture view's old and new areas
16517                 invalidate(true);
16518             }
16519 
16520             int oldWidth = mRight - mLeft;
16521             int height = mBottom - mTop;
16522 
16523             mRight = right;
16524             mRenderNode.setRight(mRight);
16525 
16526             sizeChange(mRight - mLeft, height, oldWidth, height);
16527 
16528             if (!matrixIsIdentity) {
16529                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
16530                 invalidate(true);
16531             }
16532             mBackgroundSizeChanged = true;
16533             mDefaultFocusHighlightSizeChanged = true;
16534             if (mForegroundInfo != null) {
16535                 mForegroundInfo.mBoundsChanged = true;
16536             }
16537             invalidateParentIfNeeded();
16538             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
16539                 // View was rejected last time it was drawn by its parent; this may have changed
16540                 invalidateParentIfNeeded();
16541             }
16542         }
16543     }
16544 
sanitizeFloatPropertyValue(float value, String propertyName)16545     private static float sanitizeFloatPropertyValue(float value, String propertyName) {
16546         return sanitizeFloatPropertyValue(value, propertyName, -Float.MAX_VALUE, Float.MAX_VALUE);
16547     }
16548 
sanitizeFloatPropertyValue(float value, String propertyName, float min, float max)16549     private static float sanitizeFloatPropertyValue(float value, String propertyName,
16550             float min, float max) {
16551         // The expected "nothing bad happened" path
16552         if (value >= min && value <= max) return value;
16553 
16554         if (value < min || value == Float.NEGATIVE_INFINITY) {
16555             if (sThrowOnInvalidFloatProperties) {
16556                 throw new IllegalArgumentException("Cannot set '" + propertyName + "' to "
16557                         + value + ", the value must be >= " + min);
16558             }
16559             return min;
16560         }
16561 
16562         if (value > max || value == Float.POSITIVE_INFINITY) {
16563             if (sThrowOnInvalidFloatProperties) {
16564                 throw new IllegalArgumentException("Cannot set '" + propertyName + "' to "
16565                         + value + ", the value must be <= " + max);
16566             }
16567             return max;
16568         }
16569 
16570         if (Float.isNaN(value)) {
16571             if (sThrowOnInvalidFloatProperties) {
16572                 throw new IllegalArgumentException(
16573                         "Cannot set '" + propertyName + "' to Float.NaN");
16574             }
16575             return 0; // Unclear which direction this NaN went so... 0?
16576         }
16577 
16578         // Shouldn't be possible to reach this.
16579         throw new IllegalStateException("How do you get here?? " + value);
16580     }
16581 
16582     /**
16583      * The visual x position of this view, in pixels. This is equivalent to the
16584      * {@link #setTranslationX(float) translationX} property plus the current
16585      * {@link #getLeft() left} property.
16586      *
16587      * @return The visual x position of this view, in pixels.
16588      */
16589     @ViewDebug.ExportedProperty(category = "drawing")
getX()16590     public float getX() {
16591         return mLeft + getTranslationX();
16592     }
16593 
16594     /**
16595      * Sets the visual x position of this view, in pixels. This is equivalent to setting the
16596      * {@link #setTranslationX(float) translationX} property to be the difference between
16597      * the x value passed in and the current {@link #getLeft() left} property.
16598      *
16599      * @param x The visual x position of this view, in pixels.
16600      */
setX(float x)16601     public void setX(float x) {
16602         setTranslationX(x - mLeft);
16603     }
16604 
16605     /**
16606      * The visual y position of this view, in pixels. This is equivalent to the
16607      * {@link #setTranslationY(float) translationY} property plus the current
16608      * {@link #getTop() top} property.
16609      *
16610      * @return The visual y position of this view, in pixels.
16611      */
16612     @ViewDebug.ExportedProperty(category = "drawing")
getY()16613     public float getY() {
16614         return mTop + getTranslationY();
16615     }
16616 
16617     /**
16618      * Sets the visual y position of this view, in pixels. This is equivalent to setting the
16619      * {@link #setTranslationY(float) translationY} property to be the difference between
16620      * the y value passed in and the current {@link #getTop() top} property.
16621      *
16622      * @param y The visual y position of this view, in pixels.
16623      */
setY(float y)16624     public void setY(float y) {
16625         setTranslationY(y - mTop);
16626     }
16627 
16628     /**
16629      * The visual z position of this view, in pixels. This is equivalent to the
16630      * {@link #setTranslationZ(float) translationZ} property plus the current
16631      * {@link #getElevation() elevation} property.
16632      *
16633      * @return The visual z position of this view, in pixels.
16634      */
16635     @ViewDebug.ExportedProperty(category = "drawing")
getZ()16636     public float getZ() {
16637         return getElevation() + getTranslationZ();
16638     }
16639 
16640     /**
16641      * Sets the visual z position of this view, in pixels. This is equivalent to setting the
16642      * {@link #setTranslationZ(float) translationZ} property to be the difference between
16643      * the z value passed in and the current {@link #getElevation() elevation} property.
16644      *
16645      * @param z The visual z position of this view, in pixels.
16646      */
setZ(float z)16647     public void setZ(float z) {
16648         setTranslationZ(z - getElevation());
16649     }
16650 
16651     /**
16652      * The base elevation of this view relative to its parent, in pixels.
16653      *
16654      * @return The base depth position of the view, in pixels.
16655      */
16656     @ViewDebug.ExportedProperty(category = "drawing")
16657     @InspectableProperty
getElevation()16658     public float getElevation() {
16659         return mRenderNode.getElevation();
16660     }
16661 
16662     /**
16663      * Sets the base elevation of this view, in pixels.
16664      *
16665      * @attr ref android.R.styleable#View_elevation
16666      */
setElevation(float elevation)16667     public void setElevation(float elevation) {
16668         if (elevation != getElevation()) {
16669             elevation = sanitizeFloatPropertyValue(elevation, "elevation");
16670             invalidateViewProperty(true, false);
16671             mRenderNode.setElevation(elevation);
16672             invalidateViewProperty(false, true);
16673 
16674             invalidateParentIfNeededAndWasQuickRejected();
16675         }
16676     }
16677 
16678     /**
16679      * The horizontal location of this view relative to its {@link #getLeft() left} position.
16680      * This position is post-layout, in addition to wherever the object's
16681      * layout placed it.
16682      *
16683      * @return The horizontal position of this view relative to its left position, in pixels.
16684      */
16685     @ViewDebug.ExportedProperty(category = "drawing")
16686     @InspectableProperty
getTranslationX()16687     public float getTranslationX() {
16688         return mRenderNode.getTranslationX();
16689     }
16690 
16691     /**
16692      * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
16693      * This effectively positions the object post-layout, in addition to wherever the object's
16694      * layout placed it.
16695      *
16696      * @param translationX The horizontal position of this view relative to its left position,
16697      * in pixels.
16698      *
16699      * @attr ref android.R.styleable#View_translationX
16700      */
setTranslationX(float translationX)16701     public void setTranslationX(float translationX) {
16702         if (translationX != getTranslationX()) {
16703             invalidateViewProperty(true, false);
16704             mRenderNode.setTranslationX(translationX);
16705             invalidateViewProperty(false, true);
16706 
16707             invalidateParentIfNeededAndWasQuickRejected();
16708             notifySubtreeAccessibilityStateChangedIfNeeded();
16709         }
16710     }
16711 
16712     /**
16713      * The vertical location of this view relative to its {@link #getTop() top} position.
16714      * This position is post-layout, in addition to wherever the object's
16715      * layout placed it.
16716      *
16717      * @return The vertical position of this view relative to its top position,
16718      * in pixels.
16719      */
16720     @ViewDebug.ExportedProperty(category = "drawing")
16721     @InspectableProperty
getTranslationY()16722     public float getTranslationY() {
16723         return mRenderNode.getTranslationY();
16724     }
16725 
16726     /**
16727      * Sets the vertical location of this view relative to its {@link #getTop() top} position.
16728      * This effectively positions the object post-layout, in addition to wherever the object's
16729      * layout placed it.
16730      *
16731      * @param translationY The vertical position of this view relative to its top position,
16732      * in pixels.
16733      *
16734      * @attr ref android.R.styleable#View_translationY
16735      */
setTranslationY(float translationY)16736     public void setTranslationY(float translationY) {
16737         if (translationY != getTranslationY()) {
16738             invalidateViewProperty(true, false);
16739             mRenderNode.setTranslationY(translationY);
16740             invalidateViewProperty(false, true);
16741 
16742             invalidateParentIfNeededAndWasQuickRejected();
16743             notifySubtreeAccessibilityStateChangedIfNeeded();
16744         }
16745     }
16746 
16747     /**
16748      * The depth location of this view relative to its {@link #getElevation() elevation}.
16749      *
16750      * @return The depth of this view relative to its elevation.
16751      */
16752     @ViewDebug.ExportedProperty(category = "drawing")
16753     @InspectableProperty
getTranslationZ()16754     public float getTranslationZ() {
16755         return mRenderNode.getTranslationZ();
16756     }
16757 
16758     /**
16759      * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
16760      *
16761      * @attr ref android.R.styleable#View_translationZ
16762      */
setTranslationZ(float translationZ)16763     public void setTranslationZ(float translationZ) {
16764         if (translationZ != getTranslationZ()) {
16765             translationZ = sanitizeFloatPropertyValue(translationZ, "translationZ");
16766             invalidateViewProperty(true, false);
16767             mRenderNode.setTranslationZ(translationZ);
16768             invalidateViewProperty(false, true);
16769 
16770             invalidateParentIfNeededAndWasQuickRejected();
16771         }
16772     }
16773 
16774     /**
16775      * Changes the transformation matrix on the view. This is used in animation frameworks,
16776      * such as {@link android.transition.Transition}. When the animation finishes, the matrix
16777      * should be cleared by calling this method with <code>null</code> as the matrix parameter.
16778      * Application developers should use transformation methods like {@link #setRotation(float)},
16779      * {@link #setScaleX(float)}, {@link #setScaleX(float)}, {@link #setTranslationX(float)}}
16780      * and {@link #setTranslationY(float)} (float)}} instead.
16781      *
16782      * @param matrix The matrix, null indicates that the matrix should be cleared.
16783      * @see #getAnimationMatrix()
16784      */
setAnimationMatrix(@ullable Matrix matrix)16785     public void setAnimationMatrix(@Nullable Matrix matrix) {
16786         invalidateViewProperty(true, false);
16787         mRenderNode.setAnimationMatrix(matrix);
16788         invalidateViewProperty(false, true);
16789 
16790         invalidateParentIfNeededAndWasQuickRejected();
16791     }
16792 
16793     /**
16794      * Return the current transformation matrix of the view. This is used in animation frameworks,
16795      * such as {@link android.transition.Transition}. Returns <code>null</code> when there is no
16796      * transformation provided by {@link #setAnimationMatrix(Matrix)}.
16797      * Application developers should use transformation methods like {@link #setRotation(float)},
16798      * {@link #setScaleX(float)}, {@link #setScaleX(float)}, {@link #setTranslationX(float)}}
16799      * and {@link #setTranslationY(float)} (float)}} instead.
16800      *
16801      * @return the Matrix, null indicates there is no transformation
16802      * @see #setAnimationMatrix(Matrix)
16803      */
16804     @Nullable
getAnimationMatrix()16805     public Matrix getAnimationMatrix() {
16806         return mRenderNode.getAnimationMatrix();
16807     }
16808 
16809     /**
16810      * Returns the current StateListAnimator if exists.
16811      *
16812      * @return StateListAnimator or null if it does not exists
16813      * @see    #setStateListAnimator(android.animation.StateListAnimator)
16814      */
16815     @InspectableProperty
getStateListAnimator()16816     public StateListAnimator getStateListAnimator() {
16817         return mStateListAnimator;
16818     }
16819 
16820     /**
16821      * Attaches the provided StateListAnimator to this View.
16822      * <p>
16823      * Any previously attached StateListAnimator will be detached.
16824      *
16825      * @param stateListAnimator The StateListAnimator to update the view
16826      * @see android.animation.StateListAnimator
16827      */
setStateListAnimator(StateListAnimator stateListAnimator)16828     public void setStateListAnimator(StateListAnimator stateListAnimator) {
16829         if (mStateListAnimator == stateListAnimator) {
16830             return;
16831         }
16832         if (mStateListAnimator != null) {
16833             mStateListAnimator.setTarget(null);
16834         }
16835         mStateListAnimator = stateListAnimator;
16836         if (stateListAnimator != null) {
16837             stateListAnimator.setTarget(this);
16838             if (isAttachedToWindow()) {
16839                 stateListAnimator.setState(getDrawableState());
16840             }
16841         }
16842     }
16843 
16844     /**
16845      * Returns whether the Outline should be used to clip the contents of the View.
16846      * <p>
16847      * Note that this flag will only be respected if the View's Outline returns true from
16848      * {@link Outline#canClip()}.
16849      *
16850      * @see #setOutlineProvider(ViewOutlineProvider)
16851      * @see #setClipToOutline(boolean)
16852      */
getClipToOutline()16853     public final boolean getClipToOutline() {
16854         return mRenderNode.getClipToOutline();
16855     }
16856 
16857     /**
16858      * Sets whether the View's Outline should be used to clip the contents of the View.
16859      * <p>
16860      * Only a single non-rectangular clip can be applied on a View at any time.
16861      * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
16862      * circular reveal} animation take priority over Outline clipping, and
16863      * child Outline clipping takes priority over Outline clipping done by a
16864      * parent.
16865      * <p>
16866      * Note that this flag will only be respected if the View's Outline returns true from
16867      * {@link Outline#canClip()}.
16868      *
16869      * @see #setOutlineProvider(ViewOutlineProvider)
16870      * @see #getClipToOutline()
16871      */
setClipToOutline(boolean clipToOutline)16872     public void setClipToOutline(boolean clipToOutline) {
16873         damageInParent();
16874         if (getClipToOutline() != clipToOutline) {
16875             mRenderNode.setClipToOutline(clipToOutline);
16876         }
16877     }
16878 
16879     // correspond to the enum values of View_outlineProvider
16880     private static final int PROVIDER_BACKGROUND = 0;
16881     private static final int PROVIDER_NONE = 1;
16882     private static final int PROVIDER_BOUNDS = 2;
16883     private static final int PROVIDER_PADDED_BOUNDS = 3;
setOutlineProviderFromAttribute(int providerInt)16884     private void setOutlineProviderFromAttribute(int providerInt) {
16885         switch (providerInt) {
16886             case PROVIDER_BACKGROUND:
16887                 setOutlineProvider(ViewOutlineProvider.BACKGROUND);
16888                 break;
16889             case PROVIDER_NONE:
16890                 setOutlineProvider(null);
16891                 break;
16892             case PROVIDER_BOUNDS:
16893                 setOutlineProvider(ViewOutlineProvider.BOUNDS);
16894                 break;
16895             case PROVIDER_PADDED_BOUNDS:
16896                 setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
16897                 break;
16898         }
16899     }
16900 
16901     /**
16902      * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
16903      * the shape of the shadow it casts, and enables outline clipping.
16904      * <p>
16905      * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
16906      * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
16907      * outline provider with this method allows this behavior to be overridden.
16908      * <p>
16909      * If the ViewOutlineProvider is null, if querying it for an outline returns false,
16910      * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
16911      * <p>
16912      * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
16913      *
16914      * @see #setClipToOutline(boolean)
16915      * @see #getClipToOutline()
16916      * @see #getOutlineProvider()
16917      */
setOutlineProvider(ViewOutlineProvider provider)16918     public void setOutlineProvider(ViewOutlineProvider provider) {
16919         mOutlineProvider = provider;
16920         invalidateOutline();
16921     }
16922 
16923     /**
16924      * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
16925      * that defines the shape of the shadow it casts, and enables outline clipping.
16926      *
16927      * @see #setOutlineProvider(ViewOutlineProvider)
16928      */
16929     @InspectableProperty
getOutlineProvider()16930     public ViewOutlineProvider getOutlineProvider() {
16931         return mOutlineProvider;
16932     }
16933 
16934     /**
16935      * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
16936      *
16937      * @see #setOutlineProvider(ViewOutlineProvider)
16938      */
invalidateOutline()16939     public void invalidateOutline() {
16940         rebuildOutline();
16941 
16942         notifySubtreeAccessibilityStateChangedIfNeeded();
16943         invalidateViewProperty(false, false);
16944     }
16945 
16946     /**
16947      * Internal version of {@link #invalidateOutline()} which invalidates the
16948      * outline without invalidating the view itself. This is intended to be called from
16949      * within methods in the View class itself which are the result of the view being
16950      * invalidated already. For example, when we are drawing the background of a View,
16951      * we invalidate the outline in case it changed in the meantime, but we do not
16952      * need to invalidate the view because we're already drawing the background as part
16953      * of drawing the view in response to an earlier invalidation of the view.
16954      */
rebuildOutline()16955     private void rebuildOutline() {
16956         // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
16957         if (mAttachInfo == null) return;
16958 
16959         if (mOutlineProvider == null) {
16960             // no provider, remove outline
16961             mRenderNode.setOutline(null);
16962         } else {
16963             final Outline outline = mAttachInfo.mTmpOutline;
16964             outline.setEmpty();
16965             outline.setAlpha(1.0f);
16966 
16967             mOutlineProvider.getOutline(this, outline);
16968             mRenderNode.setOutline(outline);
16969         }
16970     }
16971 
16972     /**
16973      * HierarchyViewer only
16974      *
16975      * @hide
16976      */
16977     @ViewDebug.ExportedProperty(category = "drawing")
hasShadow()16978     public boolean hasShadow() {
16979         return mRenderNode.hasShadow();
16980     }
16981 
16982     /**
16983      * Sets the color of the spot shadow that is drawn when the view has a positive Z or
16984      * elevation value.
16985      * <p>
16986      * By default the shadow color is black. Generally, this color will be opaque so the intensity
16987      * of the shadow is consistent between different views with different colors.
16988      * <p>
16989      * The opacity of the final spot shadow is a function of the shadow caster height, the
16990      * alpha channel of the outlineSpotShadowColor (typically opaque), and the
16991      * {@link android.R.attr#spotShadowAlpha} theme attribute.
16992      *
16993      * @attr ref android.R.styleable#View_outlineSpotShadowColor
16994      * @param color The color this View will cast for its elevation spot shadow.
16995      */
setOutlineSpotShadowColor(@olorInt int color)16996     public void setOutlineSpotShadowColor(@ColorInt int color) {
16997         if (mRenderNode.setSpotShadowColor(color)) {
16998             invalidateViewProperty(true, true);
16999         }
17000     }
17001 
17002     /**
17003      * @return The shadow color set by {@link #setOutlineSpotShadowColor(int)}, or black if nothing
17004      * was set
17005      */
17006     @InspectableProperty
getOutlineSpotShadowColor()17007     public @ColorInt int getOutlineSpotShadowColor() {
17008         return mRenderNode.getSpotShadowColor();
17009     }
17010 
17011     /**
17012      * Sets the color of the ambient shadow that is drawn when the view has a positive Z or
17013      * elevation value.
17014      * <p>
17015      * By default the shadow color is black. Generally, this color will be opaque so the intensity
17016      * of the shadow is consistent between different views with different colors.
17017      * <p>
17018      * The opacity of the final ambient shadow is a function of the shadow caster height, the
17019      * alpha channel of the outlineAmbientShadowColor (typically opaque), and the
17020      * {@link android.R.attr#ambientShadowAlpha} theme attribute.
17021      *
17022      * @attr ref android.R.styleable#View_outlineAmbientShadowColor
17023      * @param color The color this View will cast for its elevation shadow.
17024      */
setOutlineAmbientShadowColor(@olorInt int color)17025     public void setOutlineAmbientShadowColor(@ColorInt int color) {
17026         if (mRenderNode.setAmbientShadowColor(color)) {
17027             invalidateViewProperty(true, true);
17028         }
17029     }
17030 
17031     /**
17032      * @return The shadow color set by {@link #setOutlineAmbientShadowColor(int)}, or black if
17033      * nothing was set
17034      */
17035     @InspectableProperty
getOutlineAmbientShadowColor()17036     public @ColorInt int getOutlineAmbientShadowColor() {
17037         return mRenderNode.getAmbientShadowColor();
17038     }
17039 
17040 
17041     /** @hide */
setRevealClip(boolean shouldClip, float x, float y, float radius)17042     public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
17043         mRenderNode.setRevealClip(shouldClip, x, y, radius);
17044         invalidateViewProperty(false, false);
17045     }
17046 
17047     /**
17048      * Hit rectangle in parent's coordinates
17049      *
17050      * @param outRect The hit rectangle of the view.
17051      */
getHitRect(Rect outRect)17052     public void getHitRect(Rect outRect) {
17053         if (hasIdentityMatrix() || mAttachInfo == null) {
17054             outRect.set(mLeft, mTop, mRight, mBottom);
17055         } else {
17056             final RectF tmpRect = mAttachInfo.mTmpTransformRect;
17057             tmpRect.set(0, 0, getWidth(), getHeight());
17058             getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
17059             outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
17060                     (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
17061         }
17062     }
17063 
17064     /**
17065      * Determines whether the given point, in local coordinates is inside the view.
17066      */
pointInView(float localX, float localY)17067     /*package*/ final boolean pointInView(float localX, float localY) {
17068         return pointInView(localX, localY, 0);
17069     }
17070 
17071     /**
17072      * Utility method to determine whether the given point, in local coordinates,
17073      * is inside the view, where the area of the view is expanded by the slop factor.
17074      * This method is called while processing touch-move events to determine if the event
17075      * is still within the view.
17076      *
17077      * @hide
17078      */
17079     @UnsupportedAppUsage
pointInView(float localX, float localY, float slop)17080     public boolean pointInView(float localX, float localY, float slop) {
17081         return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
17082                 localY < ((mBottom - mTop) + slop);
17083     }
17084 
17085     /**
17086      * When a view has focus and the user navigates away from it, the next view is searched for
17087      * starting from the rectangle filled in by this method.
17088      *
17089      * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
17090      * of the view.  However, if your view maintains some idea of internal selection,
17091      * such as a cursor, or a selected row or column, you should override this method and
17092      * fill in a more specific rectangle.
17093      *
17094      * @param r The rectangle to fill in, in this view's coordinates.
17095      */
getFocusedRect(Rect r)17096     public void getFocusedRect(Rect r) {
17097         getDrawingRect(r);
17098     }
17099 
17100     /**
17101      * If some part of this view is not clipped by any of its parents, then
17102      * return that area in r in global (root) coordinates. To convert r to local
17103      * coordinates (without taking possible View rotations into account), offset
17104      * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
17105      * If the view is completely clipped or translated out, return false.
17106      *
17107      * @param r If true is returned, r holds the global coordinates of the
17108      *        visible portion of this view.
17109      * @param globalOffset If true is returned, globalOffset holds the dx,dy
17110      *        between this view and its root. globalOffet may be null.
17111      * @return true if r is non-empty (i.e. part of the view is visible at the
17112      *         root level.
17113      */
getGlobalVisibleRect(Rect r, Point globalOffset)17114     public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
17115         int width = mRight - mLeft;
17116         int height = mBottom - mTop;
17117         if (width > 0 && height > 0) {
17118             r.set(0, 0, width, height);
17119             if (globalOffset != null) {
17120                 globalOffset.set(-mScrollX, -mScrollY);
17121             }
17122             return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
17123         }
17124         return false;
17125     }
17126 
getGlobalVisibleRect(Rect r)17127     public final boolean getGlobalVisibleRect(Rect r) {
17128         return getGlobalVisibleRect(r, null);
17129     }
17130 
getLocalVisibleRect(Rect r)17131     public final boolean getLocalVisibleRect(Rect r) {
17132         final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
17133         if (getGlobalVisibleRect(r, offset)) {
17134             r.offset(-offset.x, -offset.y); // make r local
17135             return true;
17136         }
17137         return false;
17138     }
17139 
17140     /**
17141      * Offset this view's vertical location by the specified number of pixels.
17142      *
17143      * @param offset the number of pixels to offset the view by
17144      */
offsetTopAndBottom(int offset)17145     public void offsetTopAndBottom(int offset) {
17146         if (offset != 0) {
17147             final boolean matrixIsIdentity = hasIdentityMatrix();
17148             if (matrixIsIdentity) {
17149                 if (isHardwareAccelerated()) {
17150                     invalidateViewProperty(false, false);
17151                 } else {
17152                     final ViewParent p = mParent;
17153                     if (p != null && mAttachInfo != null) {
17154                         final Rect r = mAttachInfo.mTmpInvalRect;
17155                         int minTop;
17156                         int maxBottom;
17157                         int yLoc;
17158                         if (offset < 0) {
17159                             minTop = mTop + offset;
17160                             maxBottom = mBottom;
17161                             yLoc = offset;
17162                         } else {
17163                             minTop = mTop;
17164                             maxBottom = mBottom + offset;
17165                             yLoc = 0;
17166                         }
17167                         r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
17168                         p.invalidateChild(this, r);
17169                     }
17170                 }
17171             } else {
17172                 invalidateViewProperty(false, false);
17173             }
17174 
17175             mTop += offset;
17176             mBottom += offset;
17177             mRenderNode.offsetTopAndBottom(offset);
17178             if (isHardwareAccelerated()) {
17179                 invalidateViewProperty(false, false);
17180                 invalidateParentIfNeededAndWasQuickRejected();
17181             } else {
17182                 if (!matrixIsIdentity) {
17183                     invalidateViewProperty(false, true);
17184                 }
17185                 invalidateParentIfNeeded();
17186             }
17187             notifySubtreeAccessibilityStateChangedIfNeeded();
17188         }
17189     }
17190 
17191     /**
17192      * Offset this view's horizontal location by the specified amount of pixels.
17193      *
17194      * @param offset the number of pixels to offset the view by
17195      */
offsetLeftAndRight(int offset)17196     public void offsetLeftAndRight(int offset) {
17197         if (offset != 0) {
17198             final boolean matrixIsIdentity = hasIdentityMatrix();
17199             if (matrixIsIdentity) {
17200                 if (isHardwareAccelerated()) {
17201                     invalidateViewProperty(false, false);
17202                 } else {
17203                     final ViewParent p = mParent;
17204                     if (p != null && mAttachInfo != null) {
17205                         final Rect r = mAttachInfo.mTmpInvalRect;
17206                         int minLeft;
17207                         int maxRight;
17208                         if (offset < 0) {
17209                             minLeft = mLeft + offset;
17210                             maxRight = mRight;
17211                         } else {
17212                             minLeft = mLeft;
17213                             maxRight = mRight + offset;
17214                         }
17215                         r.set(0, 0, maxRight - minLeft, mBottom - mTop);
17216                         p.invalidateChild(this, r);
17217                     }
17218                 }
17219             } else {
17220                 invalidateViewProperty(false, false);
17221             }
17222 
17223             mLeft += offset;
17224             mRight += offset;
17225             mRenderNode.offsetLeftAndRight(offset);
17226             if (isHardwareAccelerated()) {
17227                 invalidateViewProperty(false, false);
17228                 invalidateParentIfNeededAndWasQuickRejected();
17229             } else {
17230                 if (!matrixIsIdentity) {
17231                     invalidateViewProperty(false, true);
17232                 }
17233                 invalidateParentIfNeeded();
17234             }
17235             notifySubtreeAccessibilityStateChangedIfNeeded();
17236         }
17237     }
17238 
17239     /**
17240      * Get the LayoutParams associated with this view. All views should have
17241      * layout parameters. These supply parameters to the <i>parent</i> of this
17242      * view specifying how it should be arranged. There are many subclasses of
17243      * ViewGroup.LayoutParams, and these correspond to the different subclasses
17244      * of ViewGroup that are responsible for arranging their children.
17245      *
17246      * This method may return null if this View is not attached to a parent
17247      * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
17248      * was not invoked successfully. When a View is attached to a parent
17249      * ViewGroup, this method must not return null.
17250      *
17251      * @return The LayoutParams associated with this view, or null if no
17252      *         parameters have been set yet
17253      */
17254     @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
getLayoutParams()17255     public ViewGroup.LayoutParams getLayoutParams() {
17256         return mLayoutParams;
17257     }
17258 
17259     /**
17260      * Set the layout parameters associated with this view. These supply
17261      * parameters to the <i>parent</i> of this view specifying how it should be
17262      * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
17263      * correspond to the different subclasses of ViewGroup that are responsible
17264      * for arranging their children.
17265      *
17266      * @param params The layout parameters for this view, cannot be null
17267      */
setLayoutParams(ViewGroup.LayoutParams params)17268     public void setLayoutParams(ViewGroup.LayoutParams params) {
17269         if (params == null) {
17270             throw new NullPointerException("Layout parameters cannot be null");
17271         }
17272         mLayoutParams = params;
17273         resolveLayoutParams();
17274         if (mParent instanceof ViewGroup) {
17275             ((ViewGroup) mParent).onSetLayoutParams(this, params);
17276         }
17277         requestLayout();
17278     }
17279 
17280     /**
17281      * Resolve the layout parameters depending on the resolved layout direction
17282      *
17283      * @hide
17284      */
resolveLayoutParams()17285     public void resolveLayoutParams() {
17286         if (mLayoutParams != null) {
17287             mLayoutParams.resolveLayoutDirection(getLayoutDirection());
17288         }
17289     }
17290 
17291     /**
17292      * Set the scrolled position of your view. This will cause a call to
17293      * {@link #onScrollChanged(int, int, int, int)} and the view will be
17294      * invalidated.
17295      * @param x the x position to scroll to
17296      * @param y the y position to scroll to
17297      */
scrollTo(int x, int y)17298     public void scrollTo(int x, int y) {
17299         if (mScrollX != x || mScrollY != y) {
17300             int oldX = mScrollX;
17301             int oldY = mScrollY;
17302             mScrollX = x;
17303             mScrollY = y;
17304             invalidateParentCaches();
17305             onScrollChanged(mScrollX, mScrollY, oldX, oldY);
17306             if (!awakenScrollBars()) {
17307                 postInvalidateOnAnimation();
17308             }
17309         }
17310     }
17311 
17312     /**
17313      * Move the scrolled position of your view. This will cause a call to
17314      * {@link #onScrollChanged(int, int, int, int)} and the view will be
17315      * invalidated.
17316      * @param x the amount of pixels to scroll by horizontally
17317      * @param y the amount of pixels to scroll by vertically
17318      */
scrollBy(int x, int y)17319     public void scrollBy(int x, int y) {
17320         scrollTo(mScrollX + x, mScrollY + y);
17321     }
17322 
17323     /**
17324      * <p>Trigger the scrollbars to draw. When invoked this method starts an
17325      * animation to fade the scrollbars out after a default delay. If a subclass
17326      * provides animated scrolling, the start delay should equal the duration
17327      * of the scrolling animation.</p>
17328      *
17329      * <p>The animation starts only if at least one of the scrollbars is
17330      * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
17331      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
17332      * this method returns true, and false otherwise. If the animation is
17333      * started, this method calls {@link #invalidate()}; in that case the
17334      * caller should not call {@link #invalidate()}.</p>
17335      *
17336      * <p>This method should be invoked every time a subclass directly updates
17337      * the scroll parameters.</p>
17338      *
17339      * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
17340      * and {@link #scrollTo(int, int)}.</p>
17341      *
17342      * @return true if the animation is played, false otherwise
17343      *
17344      * @see #awakenScrollBars(int)
17345      * @see #scrollBy(int, int)
17346      * @see #scrollTo(int, int)
17347      * @see #isHorizontalScrollBarEnabled()
17348      * @see #isVerticalScrollBarEnabled()
17349      * @see #setHorizontalScrollBarEnabled(boolean)
17350      * @see #setVerticalScrollBarEnabled(boolean)
17351      */
awakenScrollBars()17352     protected boolean awakenScrollBars() {
17353         return mScrollCache != null &&
17354                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
17355     }
17356 
17357     /**
17358      * Trigger the scrollbars to draw.
17359      * This method differs from awakenScrollBars() only in its default duration.
17360      * initialAwakenScrollBars() will show the scroll bars for longer than
17361      * usual to give the user more of a chance to notice them.
17362      *
17363      * @return true if the animation is played, false otherwise.
17364      */
initialAwakenScrollBars()17365     private boolean initialAwakenScrollBars() {
17366         return mScrollCache != null &&
17367                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
17368     }
17369 
17370     /**
17371      * <p>
17372      * Trigger the scrollbars to draw. When invoked this method starts an
17373      * animation to fade the scrollbars out after a fixed delay. If a subclass
17374      * provides animated scrolling, the start delay should equal the duration of
17375      * the scrolling animation.
17376      * </p>
17377      *
17378      * <p>
17379      * The animation starts only if at least one of the scrollbars is enabled,
17380      * as specified by {@link #isHorizontalScrollBarEnabled()} and
17381      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
17382      * this method returns true, and false otherwise. If the animation is
17383      * started, this method calls {@link #invalidate()}; in that case the caller
17384      * should not call {@link #invalidate()}.
17385      * </p>
17386      *
17387      * <p>
17388      * This method should be invoked every time a subclass directly updates the
17389      * scroll parameters.
17390      * </p>
17391      *
17392      * @param startDelay the delay, in milliseconds, after which the animation
17393      *        should start; when the delay is 0, the animation starts
17394      *        immediately
17395      * @return true if the animation is played, false otherwise
17396      *
17397      * @see #scrollBy(int, int)
17398      * @see #scrollTo(int, int)
17399      * @see #isHorizontalScrollBarEnabled()
17400      * @see #isVerticalScrollBarEnabled()
17401      * @see #setHorizontalScrollBarEnabled(boolean)
17402      * @see #setVerticalScrollBarEnabled(boolean)
17403      */
awakenScrollBars(int startDelay)17404     protected boolean awakenScrollBars(int startDelay) {
17405         return awakenScrollBars(startDelay, true);
17406     }
17407 
17408     /**
17409      * <p>
17410      * Trigger the scrollbars to draw. When invoked this method starts an
17411      * animation to fade the scrollbars out after a fixed delay. If a subclass
17412      * provides animated scrolling, the start delay should equal the duration of
17413      * the scrolling animation.
17414      * </p>
17415      *
17416      * <p>
17417      * The animation starts only if at least one of the scrollbars is enabled,
17418      * as specified by {@link #isHorizontalScrollBarEnabled()} and
17419      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
17420      * this method returns true, and false otherwise. If the animation is
17421      * started, this method calls {@link #invalidate()} if the invalidate parameter
17422      * is set to true; in that case the caller
17423      * should not call {@link #invalidate()}.
17424      * </p>
17425      *
17426      * <p>
17427      * This method should be invoked every time a subclass directly updates the
17428      * scroll parameters.
17429      * </p>
17430      *
17431      * @param startDelay the delay, in milliseconds, after which the animation
17432      *        should start; when the delay is 0, the animation starts
17433      *        immediately
17434      *
17435      * @param invalidate Whether this method should call invalidate
17436      *
17437      * @return true if the animation is played, false otherwise
17438      *
17439      * @see #scrollBy(int, int)
17440      * @see #scrollTo(int, int)
17441      * @see #isHorizontalScrollBarEnabled()
17442      * @see #isVerticalScrollBarEnabled()
17443      * @see #setHorizontalScrollBarEnabled(boolean)
17444      * @see #setVerticalScrollBarEnabled(boolean)
17445      */
awakenScrollBars(int startDelay, boolean invalidate)17446     protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
17447         final ScrollabilityCache scrollCache = mScrollCache;
17448 
17449         if (scrollCache == null || !scrollCache.fadeScrollBars) {
17450             return false;
17451         }
17452 
17453         if (scrollCache.scrollBar == null) {
17454             scrollCache.scrollBar = new ScrollBarDrawable();
17455             scrollCache.scrollBar.setState(getDrawableState());
17456             scrollCache.scrollBar.setCallback(this);
17457         }
17458 
17459         if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
17460 
17461             if (invalidate) {
17462                 // Invalidate to show the scrollbars
17463                 postInvalidateOnAnimation();
17464             }
17465 
17466             if (scrollCache.state == ScrollabilityCache.OFF) {
17467                 // FIXME: this is copied from WindowManagerService.
17468                 // We should get this value from the system when it
17469                 // is possible to do so.
17470                 final int KEY_REPEAT_FIRST_DELAY = 750;
17471                 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
17472             }
17473 
17474             // Tell mScrollCache when we should start fading. This may
17475             // extend the fade start time if one was already scheduled
17476             long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
17477             scrollCache.fadeStartTime = fadeStartTime;
17478             scrollCache.state = ScrollabilityCache.ON;
17479 
17480             // Schedule our fader to run, unscheduling any old ones first
17481             if (mAttachInfo != null) {
17482                 mAttachInfo.mHandler.removeCallbacks(scrollCache);
17483                 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
17484             }
17485 
17486             return true;
17487         }
17488 
17489         return false;
17490     }
17491 
17492     /**
17493      * Do not invalidate views which are not visible and which are not running an animation. They
17494      * will not get drawn and they should not set dirty flags as if they will be drawn
17495      */
skipInvalidate()17496     private boolean skipInvalidate() {
17497         return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
17498                 (!(mParent instanceof ViewGroup) ||
17499                         !((ViewGroup) mParent).isViewTransitioning(this));
17500     }
17501 
17502     /**
17503      * Mark the area defined by dirty as needing to be drawn. If the view is
17504      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
17505      * point in the future.
17506      * <p>
17507      * This must be called from a UI thread. To call from a non-UI thread, call
17508      * {@link #postInvalidate()}.
17509      * <p>
17510      * <b>WARNING:</b> In API 19 and below, this method may be destructive to
17511      * {@code dirty}.
17512      *
17513      * @param dirty the rectangle representing the bounds of the dirty region
17514      *
17515      * @deprecated The switch to hardware accelerated rendering in API 14 reduced
17516      * the importance of the dirty rectangle. In API 21 the given rectangle is
17517      * ignored entirely in favor of an internally-calculated area instead.
17518      * Because of this, clients are encouraged to just call {@link #invalidate()}.
17519      */
17520     @Deprecated
invalidate(Rect dirty)17521     public void invalidate(Rect dirty) {
17522         final int scrollX = mScrollX;
17523         final int scrollY = mScrollY;
17524         invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
17525                 dirty.right - scrollX, dirty.bottom - scrollY, true, false);
17526     }
17527 
17528     /**
17529      * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
17530      * coordinates of the dirty rect are relative to the view. If the view is
17531      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
17532      * point in the future.
17533      * <p>
17534      * This must be called from a UI thread. To call from a non-UI thread, call
17535      * {@link #postInvalidate()}.
17536      *
17537      * @param l the left position of the dirty region
17538      * @param t the top position of the dirty region
17539      * @param r the right position of the dirty region
17540      * @param b the bottom position of the dirty region
17541      *
17542      * @deprecated The switch to hardware accelerated rendering in API 14 reduced
17543      * the importance of the dirty rectangle. In API 21 the given rectangle is
17544      * ignored entirely in favor of an internally-calculated area instead.
17545      * Because of this, clients are encouraged to just call {@link #invalidate()}.
17546      */
17547     @Deprecated
invalidate(int l, int t, int r, int b)17548     public void invalidate(int l, int t, int r, int b) {
17549         final int scrollX = mScrollX;
17550         final int scrollY = mScrollY;
17551         invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
17552     }
17553 
17554     /**
17555      * Invalidate the whole view. If the view is visible,
17556      * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
17557      * the future.
17558      * <p>
17559      * This must be called from a UI thread. To call from a non-UI thread, call
17560      * {@link #postInvalidate()}.
17561      */
invalidate()17562     public void invalidate() {
17563         invalidate(true);
17564     }
17565 
17566     /**
17567      * This is where the invalidate() work actually happens. A full invalidate()
17568      * causes the drawing cache to be invalidated, but this function can be
17569      * called with invalidateCache set to false to skip that invalidation step
17570      * for cases that do not need it (for example, a component that remains at
17571      * the same dimensions with the same content).
17572      *
17573      * @param invalidateCache Whether the drawing cache for this view should be
17574      *            invalidated as well. This is usually true for a full
17575      *            invalidate, but may be set to false if the View's contents or
17576      *            dimensions have not changed.
17577      * @hide
17578      */
17579     @UnsupportedAppUsage
invalidate(boolean invalidateCache)17580     public void invalidate(boolean invalidateCache) {
17581         invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
17582     }
17583 
invalidateInternal(int l, int t, int r, int b, boolean invalidateCache, boolean fullInvalidate)17584     void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
17585             boolean fullInvalidate) {
17586         if (mGhostView != null) {
17587             mGhostView.invalidate(true);
17588             return;
17589         }
17590 
17591         if (skipInvalidate()) {
17592             return;
17593         }
17594 
17595         // Reset content capture caches
17596         mCachedContentCaptureSession = null;
17597 
17598         if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
17599                 || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
17600                 || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
17601                 || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
17602             if (fullInvalidate) {
17603                 mLastIsOpaque = isOpaque();
17604                 mPrivateFlags &= ~PFLAG_DRAWN;
17605             }
17606 
17607             mPrivateFlags |= PFLAG_DIRTY;
17608 
17609             if (invalidateCache) {
17610                 mPrivateFlags |= PFLAG_INVALIDATED;
17611                 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
17612             }
17613 
17614             // Propagate the damage rectangle to the parent view.
17615             final AttachInfo ai = mAttachInfo;
17616             final ViewParent p = mParent;
17617             if (p != null && ai != null && l < r && t < b) {
17618                 final Rect damage = ai.mTmpInvalRect;
17619                 damage.set(l, t, r, b);
17620                 p.invalidateChild(this, damage);
17621             }
17622 
17623             // Damage the entire projection receiver, if necessary.
17624             if (mBackground != null && mBackground.isProjected()) {
17625                 final View receiver = getProjectionReceiver();
17626                 if (receiver != null) {
17627                     receiver.damageInParent();
17628                 }
17629             }
17630         }
17631     }
17632 
17633     /**
17634      * @return this view's projection receiver, or {@code null} if none exists
17635      */
getProjectionReceiver()17636     private View getProjectionReceiver() {
17637         ViewParent p = getParent();
17638         while (p != null && p instanceof View) {
17639             final View v = (View) p;
17640             if (v.isProjectionReceiver()) {
17641                 return v;
17642             }
17643             p = p.getParent();
17644         }
17645 
17646         return null;
17647     }
17648 
17649     /**
17650      * @return whether the view is a projection receiver
17651      */
isProjectionReceiver()17652     private boolean isProjectionReceiver() {
17653         return mBackground != null;
17654     }
17655 
17656     /**
17657      * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
17658      * set any flags or handle all of the cases handled by the default invalidation methods.
17659      * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
17660      * dirty rect. This method calls into fast invalidation methods in ViewGroup that
17661      * walk up the hierarchy, transforming the dirty rect as necessary.
17662      *
17663      * The method also handles normal invalidation logic if display list properties are not
17664      * being used in this view. The invalidateParent and forceRedraw flags are used by that
17665      * backup approach, to handle these cases used in the various property-setting methods.
17666      *
17667      * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
17668      * are not being used in this view
17669      * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
17670      * list properties are not being used in this view
17671      */
17672     @UnsupportedAppUsage
invalidateViewProperty(boolean invalidateParent, boolean forceRedraw)17673     void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
17674         if (!isHardwareAccelerated()
17675                 || !mRenderNode.hasDisplayList()
17676                 || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
17677             if (invalidateParent) {
17678                 invalidateParentCaches();
17679             }
17680             if (forceRedraw) {
17681                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
17682             }
17683             invalidate(false);
17684         } else {
17685             damageInParent();
17686         }
17687     }
17688 
17689     /**
17690      * Tells the parent view to damage this view's bounds.
17691      *
17692      * @hide
17693      */
damageInParent()17694     protected void damageInParent() {
17695         if (mParent != null && mAttachInfo != null) {
17696             mParent.onDescendantInvalidated(this, this);
17697         }
17698     }
17699 
17700     /**
17701      * Used to indicate that the parent of this view should clear its caches. This functionality
17702      * is used to force the parent to rebuild its display list (when hardware-accelerated),
17703      * which is necessary when various parent-managed properties of the view change, such as
17704      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
17705      * clears the parent caches and does not causes an invalidate event.
17706      *
17707      * @hide
17708      */
17709     @UnsupportedAppUsage
invalidateParentCaches()17710     protected void invalidateParentCaches() {
17711         if (mParent instanceof View) {
17712             ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
17713         }
17714     }
17715 
17716     /**
17717      * Used to indicate that the parent of this view should be invalidated. This functionality
17718      * is used to force the parent to rebuild its display list (when hardware-accelerated),
17719      * which is necessary when various parent-managed properties of the view change, such as
17720      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
17721      * an invalidation event to the parent.
17722      *
17723      * @hide
17724      */
17725     @UnsupportedAppUsage
invalidateParentIfNeeded()17726     protected void invalidateParentIfNeeded() {
17727         if (isHardwareAccelerated() && mParent instanceof View) {
17728             ((View) mParent).invalidate(true);
17729         }
17730     }
17731 
17732     /**
17733      * @hide
17734      */
invalidateParentIfNeededAndWasQuickRejected()17735     protected void invalidateParentIfNeededAndWasQuickRejected() {
17736         if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
17737             // View was rejected last time it was drawn by its parent; this may have changed
17738             invalidateParentIfNeeded();
17739         }
17740     }
17741 
17742     /**
17743      * Indicates whether this View is opaque. An opaque View guarantees that it will
17744      * draw all the pixels overlapping its bounds using a fully opaque color.
17745      *
17746      * Subclasses of View should override this method whenever possible to indicate
17747      * whether an instance is opaque. Opaque Views are treated in a special way by
17748      * the View hierarchy, possibly allowing it to perform optimizations during
17749      * invalidate/draw passes.
17750      *
17751      * @return True if this View is guaranteed to be fully opaque, false otherwise.
17752      */
17753     @ViewDebug.ExportedProperty(category = "drawing")
isOpaque()17754     public boolean isOpaque() {
17755         return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
17756                 getFinalAlpha() >= 1.0f;
17757     }
17758 
17759     /**
17760      * @hide
17761      */
17762     @UnsupportedAppUsage
computeOpaqueFlags()17763     protected void computeOpaqueFlags() {
17764         // Opaque if:
17765         //   - Has a background
17766         //   - Background is opaque
17767         //   - Doesn't have scrollbars or scrollbars overlay
17768 
17769         if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
17770             mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
17771         } else {
17772             mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
17773         }
17774 
17775         final int flags = mViewFlags;
17776         if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
17777                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
17778                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
17779             mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
17780         } else {
17781             mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
17782         }
17783     }
17784 
17785     /**
17786      * @hide
17787      */
hasOpaqueScrollbars()17788     protected boolean hasOpaqueScrollbars() {
17789         return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
17790     }
17791 
17792     /**
17793      * @return A handler associated with the thread running the View. This
17794      * handler can be used to pump events in the UI events queue.
17795      */
getHandler()17796     public Handler getHandler() {
17797         final AttachInfo attachInfo = mAttachInfo;
17798         if (attachInfo != null) {
17799             return attachInfo.mHandler;
17800         }
17801         return null;
17802     }
17803 
17804     /**
17805      * Returns the queue of runnable for this view.
17806      *
17807      * @return the queue of runnables for this view
17808      */
getRunQueue()17809     private HandlerActionQueue getRunQueue() {
17810         if (mRunQueue == null) {
17811             mRunQueue = new HandlerActionQueue();
17812         }
17813         return mRunQueue;
17814     }
17815 
17816     /**
17817      * Gets the view root associated with the View.
17818      * @return The view root, or null if none.
17819      * @hide
17820      */
17821     @UnsupportedAppUsage
getViewRootImpl()17822     public ViewRootImpl getViewRootImpl() {
17823         if (mAttachInfo != null) {
17824             return mAttachInfo.mViewRootImpl;
17825         }
17826         return null;
17827     }
17828 
17829     /**
17830      * @hide
17831      */
17832     @UnsupportedAppUsage
getThreadedRenderer()17833     public ThreadedRenderer getThreadedRenderer() {
17834         return mAttachInfo != null ? mAttachInfo.mThreadedRenderer : null;
17835     }
17836 
17837     /**
17838      * <p>Causes the Runnable to be added to the message queue.
17839      * The runnable will be run on the user interface thread.</p>
17840      *
17841      * @param action The Runnable that will be executed.
17842      *
17843      * @return Returns true if the Runnable was successfully placed in to the
17844      *         message queue.  Returns false on failure, usually because the
17845      *         looper processing the message queue is exiting.
17846      *
17847      * @see #postDelayed
17848      * @see #removeCallbacks
17849      */
post(Runnable action)17850     public boolean post(Runnable action) {
17851         final AttachInfo attachInfo = mAttachInfo;
17852         if (attachInfo != null) {
17853             return attachInfo.mHandler.post(action);
17854         }
17855 
17856         // Postpone the runnable until we know on which thread it needs to run.
17857         // Assume that the runnable will be successfully placed after attach.
17858         getRunQueue().post(action);
17859         return true;
17860     }
17861 
17862     /**
17863      * <p>Causes the Runnable to be added to the message queue, to be run
17864      * after the specified amount of time elapses.
17865      * The runnable will be run on the user interface thread.</p>
17866      *
17867      * @param action The Runnable that will be executed.
17868      * @param delayMillis The delay (in milliseconds) until the Runnable
17869      *        will be executed.
17870      *
17871      * @return true if the Runnable was successfully placed in to the
17872      *         message queue.  Returns false on failure, usually because the
17873      *         looper processing the message queue is exiting.  Note that a
17874      *         result of true does not mean the Runnable will be processed --
17875      *         if the looper is quit before the delivery time of the message
17876      *         occurs then the message will be dropped.
17877      *
17878      * @see #post
17879      * @see #removeCallbacks
17880      */
postDelayed(Runnable action, long delayMillis)17881     public boolean postDelayed(Runnable action, long delayMillis) {
17882         final AttachInfo attachInfo = mAttachInfo;
17883         if (attachInfo != null) {
17884             return attachInfo.mHandler.postDelayed(action, delayMillis);
17885         }
17886 
17887         // Postpone the runnable until we know on which thread it needs to run.
17888         // Assume that the runnable will be successfully placed after attach.
17889         getRunQueue().postDelayed(action, delayMillis);
17890         return true;
17891     }
17892 
17893     /**
17894      * <p>Causes the Runnable to execute on the next animation time step.
17895      * The runnable will be run on the user interface thread.</p>
17896      *
17897      * @param action The Runnable that will be executed.
17898      *
17899      * @see #postOnAnimationDelayed
17900      * @see #removeCallbacks
17901      */
postOnAnimation(Runnable action)17902     public void postOnAnimation(Runnable action) {
17903         final AttachInfo attachInfo = mAttachInfo;
17904         if (attachInfo != null) {
17905             attachInfo.mViewRootImpl.mChoreographer.postCallback(
17906                     Choreographer.CALLBACK_ANIMATION, action, null);
17907         } else {
17908             // Postpone the runnable until we know
17909             // on which thread it needs to run.
17910             getRunQueue().post(action);
17911         }
17912     }
17913 
17914     /**
17915      * <p>Causes the Runnable to execute on the next animation time step,
17916      * after the specified amount of time elapses.
17917      * The runnable will be run on the user interface thread.</p>
17918      *
17919      * @param action The Runnable that will be executed.
17920      * @param delayMillis The delay (in milliseconds) until the Runnable
17921      *        will be executed.
17922      *
17923      * @see #postOnAnimation
17924      * @see #removeCallbacks
17925      */
postOnAnimationDelayed(Runnable action, long delayMillis)17926     public void postOnAnimationDelayed(Runnable action, long delayMillis) {
17927         final AttachInfo attachInfo = mAttachInfo;
17928         if (attachInfo != null) {
17929             attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
17930                     Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
17931         } else {
17932             // Postpone the runnable until we know
17933             // on which thread it needs to run.
17934             getRunQueue().postDelayed(action, delayMillis);
17935         }
17936     }
17937 
17938     /**
17939      * <p>Removes the specified Runnable from the message queue.</p>
17940      *
17941      * @param action The Runnable to remove from the message handling queue
17942      *
17943      * @return true if this view could ask the Handler to remove the Runnable,
17944      *         false otherwise. When the returned value is true, the Runnable
17945      *         may or may not have been actually removed from the message queue
17946      *         (for instance, if the Runnable was not in the queue already.)
17947      *
17948      * @see #post
17949      * @see #postDelayed
17950      * @see #postOnAnimation
17951      * @see #postOnAnimationDelayed
17952      */
removeCallbacks(Runnable action)17953     public boolean removeCallbacks(Runnable action) {
17954         if (action != null) {
17955             final AttachInfo attachInfo = mAttachInfo;
17956             if (attachInfo != null) {
17957                 attachInfo.mHandler.removeCallbacks(action);
17958                 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
17959                         Choreographer.CALLBACK_ANIMATION, action, null);
17960             }
17961             getRunQueue().removeCallbacks(action);
17962         }
17963         return true;
17964     }
17965 
17966     /**
17967      * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
17968      * Use this to invalidate the View from a non-UI thread.</p>
17969      *
17970      * <p>This method can be invoked from outside of the UI thread
17971      * only when this View is attached to a window.</p>
17972      *
17973      * @see #invalidate()
17974      * @see #postInvalidateDelayed(long)
17975      */
postInvalidate()17976     public void postInvalidate() {
17977         postInvalidateDelayed(0);
17978     }
17979 
17980     /**
17981      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
17982      * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
17983      *
17984      * <p>This method can be invoked from outside of the UI thread
17985      * only when this View is attached to a window.</p>
17986      *
17987      * @param left The left coordinate of the rectangle to invalidate.
17988      * @param top The top coordinate of the rectangle to invalidate.
17989      * @param right The right coordinate of the rectangle to invalidate.
17990      * @param bottom The bottom coordinate of the rectangle to invalidate.
17991      *
17992      * @see #invalidate(int, int, int, int)
17993      * @see #invalidate(Rect)
17994      * @see #postInvalidateDelayed(long, int, int, int, int)
17995      */
postInvalidate(int left, int top, int right, int bottom)17996     public void postInvalidate(int left, int top, int right, int bottom) {
17997         postInvalidateDelayed(0, left, top, right, bottom);
17998     }
17999 
18000     /**
18001      * <p>Cause an invalidate to happen on a subsequent cycle through the event
18002      * loop. Waits for the specified amount of time.</p>
18003      *
18004      * <p>This method can be invoked from outside of the UI thread
18005      * only when this View is attached to a window.</p>
18006      *
18007      * @param delayMilliseconds the duration in milliseconds to delay the
18008      *         invalidation by
18009      *
18010      * @see #invalidate()
18011      * @see #postInvalidate()
18012      */
postInvalidateDelayed(long delayMilliseconds)18013     public void postInvalidateDelayed(long delayMilliseconds) {
18014         // We try only with the AttachInfo because there's no point in invalidating
18015         // if we are not attached to our window
18016         final AttachInfo attachInfo = mAttachInfo;
18017         if (attachInfo != null) {
18018             attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
18019         }
18020     }
18021 
18022     /**
18023      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
18024      * through the event loop. Waits for the specified amount of time.</p>
18025      *
18026      * <p>This method can be invoked from outside of the UI thread
18027      * only when this View is attached to a window.</p>
18028      *
18029      * @param delayMilliseconds the duration in milliseconds to delay the
18030      *         invalidation by
18031      * @param left The left coordinate of the rectangle to invalidate.
18032      * @param top The top coordinate of the rectangle to invalidate.
18033      * @param right The right coordinate of the rectangle to invalidate.
18034      * @param bottom The bottom coordinate of the rectangle to invalidate.
18035      *
18036      * @see #invalidate(int, int, int, int)
18037      * @see #invalidate(Rect)
18038      * @see #postInvalidate(int, int, int, int)
18039      */
postInvalidateDelayed(long delayMilliseconds, int left, int top, int right, int bottom)18040     public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
18041             int right, int bottom) {
18042 
18043         // We try only with the AttachInfo because there's no point in invalidating
18044         // if we are not attached to our window
18045         final AttachInfo attachInfo = mAttachInfo;
18046         if (attachInfo != null) {
18047             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
18048             info.target = this;
18049             info.left = left;
18050             info.top = top;
18051             info.right = right;
18052             info.bottom = bottom;
18053 
18054             attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
18055         }
18056     }
18057 
18058     /**
18059      * <p>Cause an invalidate to happen on the next animation time step, typically the
18060      * next display frame.</p>
18061      *
18062      * <p>This method can be invoked from outside of the UI thread
18063      * only when this View is attached to a window.</p>
18064      *
18065      * @see #invalidate()
18066      */
postInvalidateOnAnimation()18067     public void postInvalidateOnAnimation() {
18068         // We try only with the AttachInfo because there's no point in invalidating
18069         // if we are not attached to our window
18070         final AttachInfo attachInfo = mAttachInfo;
18071         if (attachInfo != null) {
18072             attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
18073         }
18074     }
18075 
18076     /**
18077      * <p>Cause an invalidate of the specified area to happen on the next animation
18078      * time step, typically the next display frame.</p>
18079      *
18080      * <p>This method can be invoked from outside of the UI thread
18081      * only when this View is attached to a window.</p>
18082      *
18083      * @param left The left coordinate of the rectangle to invalidate.
18084      * @param top The top coordinate of the rectangle to invalidate.
18085      * @param right The right coordinate of the rectangle to invalidate.
18086      * @param bottom The bottom coordinate of the rectangle to invalidate.
18087      *
18088      * @see #invalidate(int, int, int, int)
18089      * @see #invalidate(Rect)
18090      */
postInvalidateOnAnimation(int left, int top, int right, int bottom)18091     public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
18092         // We try only with the AttachInfo because there's no point in invalidating
18093         // if we are not attached to our window
18094         final AttachInfo attachInfo = mAttachInfo;
18095         if (attachInfo != null) {
18096             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
18097             info.target = this;
18098             info.left = left;
18099             info.top = top;
18100             info.right = right;
18101             info.bottom = bottom;
18102 
18103             attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
18104         }
18105     }
18106 
18107     /**
18108      * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
18109      * This event is sent at most once every
18110      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
18111      */
postSendViewScrolledAccessibilityEventCallback(int dx, int dy)18112     private void postSendViewScrolledAccessibilityEventCallback(int dx, int dy) {
18113         if (mSendViewScrolledAccessibilityEvent == null) {
18114             mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
18115         }
18116         mSendViewScrolledAccessibilityEvent.post(dx, dy);
18117     }
18118 
18119     /**
18120      * Called by a parent to request that a child update its values for mScrollX
18121      * and mScrollY if necessary. This will typically be done if the child is
18122      * animating a scroll using a {@link android.widget.Scroller Scroller}
18123      * object.
18124      */
computeScroll()18125     public void computeScroll() {
18126     }
18127 
18128     /**
18129      * <p>Indicate whether the horizontal edges are faded when the view is
18130      * scrolled horizontally.</p>
18131      *
18132      * @return true if the horizontal edges should are faded on scroll, false
18133      *         otherwise
18134      *
18135      * @see #setHorizontalFadingEdgeEnabled(boolean)
18136      *
18137      * @attr ref android.R.styleable#View_requiresFadingEdge
18138      */
isHorizontalFadingEdgeEnabled()18139     public boolean isHorizontalFadingEdgeEnabled() {
18140         return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
18141     }
18142 
18143     /**
18144      * <p>Define whether the horizontal edges should be faded when this view
18145      * is scrolled horizontally.</p>
18146      *
18147      * @param horizontalFadingEdgeEnabled true if the horizontal edges should
18148      *                                    be faded when the view is scrolled
18149      *                                    horizontally
18150      *
18151      * @see #isHorizontalFadingEdgeEnabled()
18152      *
18153      * @attr ref android.R.styleable#View_requiresFadingEdge
18154      */
setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled)18155     public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
18156         if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
18157             if (horizontalFadingEdgeEnabled) {
18158                 initScrollCache();
18159             }
18160 
18161             mViewFlags ^= FADING_EDGE_HORIZONTAL;
18162         }
18163     }
18164 
18165     /**
18166      * <p>Indicate whether the vertical edges are faded when the view is
18167      * scrolled horizontally.</p>
18168      *
18169      * @return true if the vertical edges should are faded on scroll, false
18170      *         otherwise
18171      *
18172      * @see #setVerticalFadingEdgeEnabled(boolean)
18173      *
18174      * @attr ref android.R.styleable#View_requiresFadingEdge
18175      */
isVerticalFadingEdgeEnabled()18176     public boolean isVerticalFadingEdgeEnabled() {
18177         return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
18178     }
18179 
18180     /**
18181      * <p>Define whether the vertical edges should be faded when this view
18182      * is scrolled vertically.</p>
18183      *
18184      * @param verticalFadingEdgeEnabled true if the vertical edges should
18185      *                                  be faded when the view is scrolled
18186      *                                  vertically
18187      *
18188      * @see #isVerticalFadingEdgeEnabled()
18189      *
18190      * @attr ref android.R.styleable#View_requiresFadingEdge
18191      */
setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled)18192     public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
18193         if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
18194             if (verticalFadingEdgeEnabled) {
18195                 initScrollCache();
18196             }
18197 
18198             mViewFlags ^= FADING_EDGE_VERTICAL;
18199         }
18200     }
18201 
18202     /**
18203      * Get the fading edge flags, used for inspection.
18204      *
18205      * @return One of {@link #FADING_EDGE_NONE}, {@link #FADING_EDGE_VERTICAL},
18206      *         or {@link #FADING_EDGE_HORIZONTAL}
18207      * @hide
18208      */
18209     @InspectableProperty(name = "requiresFadingEdge", flagMapping = {
18210             @FlagEntry(target = FADING_EDGE_NONE, mask = FADING_EDGE_MASK, name = "none"),
18211             @FlagEntry(target = FADING_EDGE_VERTICAL, name = "vertical"),
18212             @FlagEntry(target = FADING_EDGE_HORIZONTAL, name = "horizontal")
18213     })
getFadingEdge()18214     public int getFadingEdge() {
18215         return mViewFlags & FADING_EDGE_MASK;
18216     }
18217 
18218     /**
18219      * Get the fading edge length, used for inspection
18220      *
18221      * @return The fading edge length or 0
18222      * @hide
18223      */
18224     @InspectableProperty
getFadingEdgeLength()18225     public int getFadingEdgeLength() {
18226         if (mScrollCache != null && (mViewFlags & FADING_EDGE_MASK) != FADING_EDGE_NONE) {
18227             return mScrollCache.fadingEdgeLength;
18228         }
18229         return 0;
18230     }
18231 
18232     /**
18233      * Returns the strength, or intensity, of the top faded edge. The strength is
18234      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
18235      * returns 0.0 or 1.0 but no value in between.
18236      *
18237      * Subclasses should override this method to provide a smoother fade transition
18238      * when scrolling occurs.
18239      *
18240      * @return the intensity of the top fade as a float between 0.0f and 1.0f
18241      */
getTopFadingEdgeStrength()18242     protected float getTopFadingEdgeStrength() {
18243         return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
18244     }
18245 
18246     /**
18247      * Returns the strength, or intensity, of the bottom faded edge. The strength is
18248      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
18249      * returns 0.0 or 1.0 but no value in between.
18250      *
18251      * Subclasses should override this method to provide a smoother fade transition
18252      * when scrolling occurs.
18253      *
18254      * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
18255      */
getBottomFadingEdgeStrength()18256     protected float getBottomFadingEdgeStrength() {
18257         return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
18258                 computeVerticalScrollRange() ? 1.0f : 0.0f;
18259     }
18260 
18261     /**
18262      * Returns the strength, or intensity, of the left faded edge. The strength is
18263      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
18264      * returns 0.0 or 1.0 but no value in between.
18265      *
18266      * Subclasses should override this method to provide a smoother fade transition
18267      * when scrolling occurs.
18268      *
18269      * @return the intensity of the left fade as a float between 0.0f and 1.0f
18270      */
getLeftFadingEdgeStrength()18271     protected float getLeftFadingEdgeStrength() {
18272         return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
18273     }
18274 
18275     /**
18276      * Returns the strength, or intensity, of the right faded edge. The strength is
18277      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
18278      * returns 0.0 or 1.0 but no value in between.
18279      *
18280      * Subclasses should override this method to provide a smoother fade transition
18281      * when scrolling occurs.
18282      *
18283      * @return the intensity of the right fade as a float between 0.0f and 1.0f
18284      */
getRightFadingEdgeStrength()18285     protected float getRightFadingEdgeStrength() {
18286         return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
18287                 computeHorizontalScrollRange() ? 1.0f : 0.0f;
18288     }
18289 
18290     /**
18291      * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
18292      * scrollbar is not drawn by default.</p>
18293      *
18294      * @return true if the horizontal scrollbar should be painted, false
18295      *         otherwise
18296      *
18297      * @see #setHorizontalScrollBarEnabled(boolean)
18298      */
isHorizontalScrollBarEnabled()18299     public boolean isHorizontalScrollBarEnabled() {
18300         return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
18301     }
18302 
18303     /**
18304      * <p>Define whether the horizontal scrollbar should be drawn or not. The
18305      * scrollbar is not drawn by default.</p>
18306      *
18307      * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
18308      *                                   be painted
18309      *
18310      * @see #isHorizontalScrollBarEnabled()
18311      */
setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled)18312     public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
18313         if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
18314             mViewFlags ^= SCROLLBARS_HORIZONTAL;
18315             computeOpaqueFlags();
18316             resolvePadding();
18317         }
18318     }
18319 
18320     /**
18321      * <p>Indicate whether the vertical scrollbar should be drawn or not. The
18322      * scrollbar is not drawn by default.</p>
18323      *
18324      * @return true if the vertical scrollbar should be painted, false
18325      *         otherwise
18326      *
18327      * @see #setVerticalScrollBarEnabled(boolean)
18328      */
isVerticalScrollBarEnabled()18329     public boolean isVerticalScrollBarEnabled() {
18330         return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
18331     }
18332 
18333     /**
18334      * <p>Define whether the vertical scrollbar should be drawn or not. The
18335      * scrollbar is not drawn by default.</p>
18336      *
18337      * @param verticalScrollBarEnabled true if the vertical scrollbar should
18338      *                                 be painted
18339      *
18340      * @see #isVerticalScrollBarEnabled()
18341      */
setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled)18342     public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
18343         if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
18344             mViewFlags ^= SCROLLBARS_VERTICAL;
18345             computeOpaqueFlags();
18346             resolvePadding();
18347         }
18348     }
18349 
18350     /**
18351      * @hide
18352      */
18353     @UnsupportedAppUsage
recomputePadding()18354     protected void recomputePadding() {
18355         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
18356     }
18357 
18358     /**
18359      * Define whether scrollbars will fade when the view is not scrolling.
18360      *
18361      * @param fadeScrollbars whether to enable fading
18362      *
18363      * @attr ref android.R.styleable#View_fadeScrollbars
18364      */
setScrollbarFadingEnabled(boolean fadeScrollbars)18365     public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
18366         initScrollCache();
18367         final ScrollabilityCache scrollabilityCache = mScrollCache;
18368         scrollabilityCache.fadeScrollBars = fadeScrollbars;
18369         if (fadeScrollbars) {
18370             scrollabilityCache.state = ScrollabilityCache.OFF;
18371         } else {
18372             scrollabilityCache.state = ScrollabilityCache.ON;
18373         }
18374     }
18375 
18376     /**
18377      *
18378      * Returns true if scrollbars will fade when this view is not scrolling
18379      *
18380      * @return true if scrollbar fading is enabled
18381      *
18382      * @attr ref android.R.styleable#View_fadeScrollbars
18383      */
isScrollbarFadingEnabled()18384     public boolean isScrollbarFadingEnabled() {
18385         return mScrollCache != null && mScrollCache.fadeScrollBars;
18386     }
18387 
18388     /**
18389      *
18390      * Returns the delay before scrollbars fade.
18391      *
18392      * @return the delay before scrollbars fade
18393      *
18394      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
18395      */
18396     @InspectableProperty(name = "scrollbarDefaultDelayBeforeFade")
getScrollBarDefaultDelayBeforeFade()18397     public int getScrollBarDefaultDelayBeforeFade() {
18398         return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
18399                 mScrollCache.scrollBarDefaultDelayBeforeFade;
18400     }
18401 
18402     /**
18403      * Define the delay before scrollbars fade.
18404      *
18405      * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
18406      *
18407      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
18408      */
setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade)18409     public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
18410         getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
18411     }
18412 
18413     /**
18414      *
18415      * Returns the scrollbar fade duration.
18416      *
18417      * @return the scrollbar fade duration, in milliseconds
18418      *
18419      * @attr ref android.R.styleable#View_scrollbarFadeDuration
18420      */
18421     @InspectableProperty(name = "scrollbarFadeDuration")
getScrollBarFadeDuration()18422     public int getScrollBarFadeDuration() {
18423         return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
18424                 mScrollCache.scrollBarFadeDuration;
18425     }
18426 
18427     /**
18428      * Define the scrollbar fade duration.
18429      *
18430      * @param scrollBarFadeDuration - the scrollbar fade duration, in milliseconds
18431      *
18432      * @attr ref android.R.styleable#View_scrollbarFadeDuration
18433      */
setScrollBarFadeDuration(int scrollBarFadeDuration)18434     public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
18435         getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
18436     }
18437 
18438     /**
18439      *
18440      * Returns the scrollbar size.
18441      *
18442      * @return the scrollbar size
18443      *
18444      * @attr ref android.R.styleable#View_scrollbarSize
18445      */
18446     @InspectableProperty(name = "scrollbarSize")
getScrollBarSize()18447     public int getScrollBarSize() {
18448         return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
18449                 mScrollCache.scrollBarSize;
18450     }
18451 
18452     /**
18453      * Define the scrollbar size.
18454      *
18455      * @param scrollBarSize - the scrollbar size
18456      *
18457      * @attr ref android.R.styleable#View_scrollbarSize
18458      */
setScrollBarSize(int scrollBarSize)18459     public void setScrollBarSize(int scrollBarSize) {
18460         getScrollCache().scrollBarSize = scrollBarSize;
18461     }
18462 
18463     /**
18464      * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
18465      * inset. When inset, they add to the padding of the view. And the scrollbars
18466      * can be drawn inside the padding area or on the edge of the view. For example,
18467      * if a view has a background drawable and you want to draw the scrollbars
18468      * inside the padding specified by the drawable, you can use
18469      * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
18470      * appear at the edge of the view, ignoring the padding, then you can use
18471      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
18472      * @param style the style of the scrollbars. Should be one of
18473      * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
18474      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
18475      * @see #SCROLLBARS_INSIDE_OVERLAY
18476      * @see #SCROLLBARS_INSIDE_INSET
18477      * @see #SCROLLBARS_OUTSIDE_OVERLAY
18478      * @see #SCROLLBARS_OUTSIDE_INSET
18479      *
18480      * @attr ref android.R.styleable#View_scrollbarStyle
18481      */
setScrollBarStyle(@crollBarStyle int style)18482     public void setScrollBarStyle(@ScrollBarStyle int style) {
18483         if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
18484             mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
18485             computeOpaqueFlags();
18486             resolvePadding();
18487         }
18488     }
18489 
18490     /**
18491      * <p>Returns the current scrollbar style.</p>
18492      * @return the current scrollbar style
18493      * @see #SCROLLBARS_INSIDE_OVERLAY
18494      * @see #SCROLLBARS_INSIDE_INSET
18495      * @see #SCROLLBARS_OUTSIDE_OVERLAY
18496      * @see #SCROLLBARS_OUTSIDE_INSET
18497      *
18498      * @attr ref android.R.styleable#View_scrollbarStyle
18499      */
18500     @ViewDebug.ExportedProperty(mapping = {
18501             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
18502             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
18503             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
18504             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
18505     })
18506     @InspectableProperty(name = "scrollbarStyle", enumMapping = {
18507             @EnumEntry(value = SCROLLBARS_INSIDE_OVERLAY, name = "insideOverlay"),
18508             @EnumEntry(value = SCROLLBARS_INSIDE_INSET, name = "insideInset"),
18509             @EnumEntry(value = SCROLLBARS_OUTSIDE_OVERLAY, name = "outsideOverlay"),
18510             @EnumEntry(value = SCROLLBARS_OUTSIDE_INSET, name = "outsideInset")
18511     })
18512     @ScrollBarStyle
getScrollBarStyle()18513     public int getScrollBarStyle() {
18514         return mViewFlags & SCROLLBARS_STYLE_MASK;
18515     }
18516 
18517     /**
18518      * <p>Compute the horizontal range that the horizontal scrollbar
18519      * represents.</p>
18520      *
18521      * <p>The range is expressed in arbitrary units that must be the same as the
18522      * units used by {@link #computeHorizontalScrollExtent()} and
18523      * {@link #computeHorizontalScrollOffset()}.</p>
18524      *
18525      * <p>The default range is the drawing width of this view.</p>
18526      *
18527      * @return the total horizontal range represented by the horizontal
18528      *         scrollbar
18529      *
18530      * @see #computeHorizontalScrollExtent()
18531      * @see #computeHorizontalScrollOffset()
18532      */
computeHorizontalScrollRange()18533     protected int computeHorizontalScrollRange() {
18534         return getWidth();
18535     }
18536 
18537     /**
18538      * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
18539      * within the horizontal range. This value is used to compute the position
18540      * of the thumb within the scrollbar's track.</p>
18541      *
18542      * <p>The range is expressed in arbitrary units that must be the same as the
18543      * units used by {@link #computeHorizontalScrollRange()} and
18544      * {@link #computeHorizontalScrollExtent()}.</p>
18545      *
18546      * <p>The default offset is the scroll offset of this view.</p>
18547      *
18548      * @return the horizontal offset of the scrollbar's thumb
18549      *
18550      * @see #computeHorizontalScrollRange()
18551      * @see #computeHorizontalScrollExtent()
18552      */
computeHorizontalScrollOffset()18553     protected int computeHorizontalScrollOffset() {
18554         return mScrollX;
18555     }
18556 
18557     /**
18558      * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
18559      * within the horizontal range. This value is used to compute the length
18560      * of the thumb within the scrollbar's track.</p>
18561      *
18562      * <p>The range is expressed in arbitrary units that must be the same as the
18563      * units used by {@link #computeHorizontalScrollRange()} and
18564      * {@link #computeHorizontalScrollOffset()}.</p>
18565      *
18566      * <p>The default extent is the drawing width of this view.</p>
18567      *
18568      * @return the horizontal extent of the scrollbar's thumb
18569      *
18570      * @see #computeHorizontalScrollRange()
18571      * @see #computeHorizontalScrollOffset()
18572      */
computeHorizontalScrollExtent()18573     protected int computeHorizontalScrollExtent() {
18574         return getWidth();
18575     }
18576 
18577     /**
18578      * <p>Compute the vertical range that the vertical scrollbar represents.</p>
18579      *
18580      * <p>The range is expressed in arbitrary units that must be the same as the
18581      * units used by {@link #computeVerticalScrollExtent()} and
18582      * {@link #computeVerticalScrollOffset()}.</p>
18583      *
18584      * @return the total vertical range represented by the vertical scrollbar
18585      *
18586      * <p>The default range is the drawing height of this view.</p>
18587      *
18588      * @see #computeVerticalScrollExtent()
18589      * @see #computeVerticalScrollOffset()
18590      */
computeVerticalScrollRange()18591     protected int computeVerticalScrollRange() {
18592         return getHeight();
18593     }
18594 
18595     /**
18596      * <p>Compute the vertical offset of the vertical scrollbar's thumb
18597      * within the horizontal range. This value is used to compute the position
18598      * of the thumb within the scrollbar's track.</p>
18599      *
18600      * <p>The range is expressed in arbitrary units that must be the same as the
18601      * units used by {@link #computeVerticalScrollRange()} and
18602      * {@link #computeVerticalScrollExtent()}.</p>
18603      *
18604      * <p>The default offset is the scroll offset of this view.</p>
18605      *
18606      * @return the vertical offset of the scrollbar's thumb
18607      *
18608      * @see #computeVerticalScrollRange()
18609      * @see #computeVerticalScrollExtent()
18610      */
computeVerticalScrollOffset()18611     protected int computeVerticalScrollOffset() {
18612         return mScrollY;
18613     }
18614 
18615     /**
18616      * <p>Compute the vertical extent of the vertical scrollbar's thumb
18617      * within the vertical range. This value is used to compute the length
18618      * of the thumb within the scrollbar's track.</p>
18619      *
18620      * <p>The range is expressed in arbitrary units that must be the same as the
18621      * units used by {@link #computeVerticalScrollRange()} and
18622      * {@link #computeVerticalScrollOffset()}.</p>
18623      *
18624      * <p>The default extent is the drawing height of this view.</p>
18625      *
18626      * @return the vertical extent of the scrollbar's thumb
18627      *
18628      * @see #computeVerticalScrollRange()
18629      * @see #computeVerticalScrollOffset()
18630      */
computeVerticalScrollExtent()18631     protected int computeVerticalScrollExtent() {
18632         return getHeight();
18633     }
18634 
18635     /**
18636      * Check if this view can be scrolled horizontally in a certain direction.
18637      *
18638      * @param direction Negative to check scrolling left, positive to check scrolling right.
18639      * @return true if this view can be scrolled in the specified direction, false otherwise.
18640      */
canScrollHorizontally(int direction)18641     public boolean canScrollHorizontally(int direction) {
18642         final int offset = computeHorizontalScrollOffset();
18643         final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
18644         if (range == 0) return false;
18645         if (direction < 0) {
18646             return offset > 0;
18647         } else {
18648             return offset < range - 1;
18649         }
18650     }
18651 
18652     /**
18653      * Check if this view can be scrolled vertically in a certain direction.
18654      *
18655      * @param direction Negative to check scrolling up, positive to check scrolling down.
18656      * @return true if this view can be scrolled in the specified direction, false otherwise.
18657      */
canScrollVertically(int direction)18658     public boolean canScrollVertically(int direction) {
18659         final int offset = computeVerticalScrollOffset();
18660         final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
18661         if (range == 0) return false;
18662         if (direction < 0) {
18663             return offset > 0;
18664         } else {
18665             return offset < range - 1;
18666         }
18667     }
18668 
getScrollIndicatorBounds(@onNull Rect out)18669     void getScrollIndicatorBounds(@NonNull Rect out) {
18670         out.left = mScrollX;
18671         out.right = mScrollX + mRight - mLeft;
18672         out.top = mScrollY;
18673         out.bottom = mScrollY + mBottom - mTop;
18674     }
18675 
onDrawScrollIndicators(Canvas c)18676     private void onDrawScrollIndicators(Canvas c) {
18677         if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
18678             // No scroll indicators enabled.
18679             return;
18680         }
18681 
18682         final Drawable dr = mScrollIndicatorDrawable;
18683         if (dr == null) {
18684             // Scroll indicators aren't supported here.
18685             return;
18686         }
18687 
18688         final int h = dr.getIntrinsicHeight();
18689         final int w = dr.getIntrinsicWidth();
18690         final Rect rect = mAttachInfo.mTmpInvalRect;
18691         getScrollIndicatorBounds(rect);
18692 
18693         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
18694             final boolean canScrollUp = canScrollVertically(-1);
18695             if (canScrollUp) {
18696                 dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
18697                 dr.draw(c);
18698             }
18699         }
18700 
18701         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
18702             final boolean canScrollDown = canScrollVertically(1);
18703             if (canScrollDown) {
18704                 dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
18705                 dr.draw(c);
18706             }
18707         }
18708 
18709         final int leftRtl;
18710         final int rightRtl;
18711         if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
18712             leftRtl = PFLAG3_SCROLL_INDICATOR_END;
18713             rightRtl = PFLAG3_SCROLL_INDICATOR_START;
18714         } else {
18715             leftRtl = PFLAG3_SCROLL_INDICATOR_START;
18716             rightRtl = PFLAG3_SCROLL_INDICATOR_END;
18717         }
18718 
18719         final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
18720         if ((mPrivateFlags3 & leftMask) != 0) {
18721             final boolean canScrollLeft = canScrollHorizontally(-1);
18722             if (canScrollLeft) {
18723                 dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
18724                 dr.draw(c);
18725             }
18726         }
18727 
18728         final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
18729         if ((mPrivateFlags3 & rightMask) != 0) {
18730             final boolean canScrollRight = canScrollHorizontally(1);
18731             if (canScrollRight) {
18732                 dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
18733                 dr.draw(c);
18734             }
18735         }
18736     }
18737 
getHorizontalScrollBarBounds(@ullable Rect drawBounds, @Nullable Rect touchBounds)18738     private void getHorizontalScrollBarBounds(@Nullable Rect drawBounds,
18739             @Nullable Rect touchBounds) {
18740         final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
18741         if (bounds == null) {
18742             return;
18743         }
18744         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
18745         final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
18746                 && !isVerticalScrollBarHidden();
18747         final int size = getHorizontalScrollbarHeight();
18748         final int verticalScrollBarGap = drawVerticalScrollBar ?
18749                 getVerticalScrollbarWidth() : 0;
18750         final int width = mRight - mLeft;
18751         final int height = mBottom - mTop;
18752         bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
18753         bounds.left = mScrollX + (mPaddingLeft & inside);
18754         bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
18755         bounds.bottom = bounds.top + size;
18756 
18757         if (touchBounds == null) {
18758             return;
18759         }
18760         if (touchBounds != bounds) {
18761             touchBounds.set(bounds);
18762         }
18763         final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
18764         if (touchBounds.height() < minTouchTarget) {
18765             final int adjust = (minTouchTarget - touchBounds.height()) / 2;
18766             touchBounds.bottom = Math.min(touchBounds.bottom + adjust, mScrollY + height);
18767             touchBounds.top = touchBounds.bottom - minTouchTarget;
18768         }
18769         if (touchBounds.width() < minTouchTarget) {
18770             final int adjust = (minTouchTarget - touchBounds.width()) / 2;
18771             touchBounds.left -= adjust;
18772             touchBounds.right = touchBounds.left + minTouchTarget;
18773         }
18774     }
18775 
getVerticalScrollBarBounds(@ullable Rect bounds, @Nullable Rect touchBounds)18776     private void getVerticalScrollBarBounds(@Nullable Rect bounds, @Nullable Rect touchBounds) {
18777         if (mRoundScrollbarRenderer == null) {
18778             getStraightVerticalScrollBarBounds(bounds, touchBounds);
18779         } else {
18780             getRoundVerticalScrollBarBounds(bounds != null ? bounds : touchBounds);
18781         }
18782     }
18783 
getRoundVerticalScrollBarBounds(Rect bounds)18784     private void getRoundVerticalScrollBarBounds(Rect bounds) {
18785         final int width = mRight - mLeft;
18786         final int height = mBottom - mTop;
18787         // Do not take padding into account as we always want the scrollbars
18788         // to hug the screen for round wearable devices.
18789         bounds.left = mScrollX;
18790         bounds.top = mScrollY;
18791         bounds.right = bounds.left + width;
18792         bounds.bottom = mScrollY + height;
18793     }
18794 
getStraightVerticalScrollBarBounds(@ullable Rect drawBounds, @Nullable Rect touchBounds)18795     private void getStraightVerticalScrollBarBounds(@Nullable Rect drawBounds,
18796             @Nullable Rect touchBounds) {
18797         final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
18798         if (bounds == null) {
18799             return;
18800         }
18801         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
18802         final int size = getVerticalScrollbarWidth();
18803         int verticalScrollbarPosition = mVerticalScrollbarPosition;
18804         if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
18805             verticalScrollbarPosition = isLayoutRtl() ?
18806                     SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
18807         }
18808         final int width = mRight - mLeft;
18809         final int height = mBottom - mTop;
18810         switch (verticalScrollbarPosition) {
18811             default:
18812             case SCROLLBAR_POSITION_RIGHT:
18813                 bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
18814                 break;
18815             case SCROLLBAR_POSITION_LEFT:
18816                 bounds.left = mScrollX + (mUserPaddingLeft & inside);
18817                 break;
18818         }
18819         bounds.top = mScrollY + (mPaddingTop & inside);
18820         bounds.right = bounds.left + size;
18821         bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
18822 
18823         if (touchBounds == null) {
18824             return;
18825         }
18826         if (touchBounds != bounds) {
18827             touchBounds.set(bounds);
18828         }
18829         final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
18830         if (touchBounds.width() < minTouchTarget) {
18831             final int adjust = (minTouchTarget - touchBounds.width()) / 2;
18832             if (verticalScrollbarPosition == SCROLLBAR_POSITION_RIGHT) {
18833                 touchBounds.right = Math.min(touchBounds.right + adjust, mScrollX + width);
18834                 touchBounds.left = touchBounds.right - minTouchTarget;
18835             } else {
18836                 touchBounds.left = Math.max(touchBounds.left + adjust, mScrollX);
18837                 touchBounds.right = touchBounds.left + minTouchTarget;
18838             }
18839         }
18840         if (touchBounds.height() < minTouchTarget) {
18841             final int adjust = (minTouchTarget - touchBounds.height()) / 2;
18842             touchBounds.top -= adjust;
18843             touchBounds.bottom = touchBounds.top + minTouchTarget;
18844         }
18845     }
18846 
18847     /**
18848      * <p>Request the drawing of the horizontal and the vertical scrollbar. The
18849      * scrollbars are painted only if they have been awakened first.</p>
18850      *
18851      * @param canvas the canvas on which to draw the scrollbars
18852      *
18853      * @see #awakenScrollBars(int)
18854      */
onDrawScrollBars(Canvas canvas)18855     protected final void onDrawScrollBars(Canvas canvas) {
18856         // scrollbars are drawn only when the animation is running
18857         final ScrollabilityCache cache = mScrollCache;
18858 
18859         if (cache != null) {
18860 
18861             int state = cache.state;
18862 
18863             if (state == ScrollabilityCache.OFF) {
18864                 return;
18865             }
18866 
18867             boolean invalidate = false;
18868 
18869             if (state == ScrollabilityCache.FADING) {
18870                 // We're fading -- get our fade interpolation
18871                 if (cache.interpolatorValues == null) {
18872                     cache.interpolatorValues = new float[1];
18873                 }
18874 
18875                 float[] values = cache.interpolatorValues;
18876 
18877                 // Stops the animation if we're done
18878                 if (cache.scrollBarInterpolator.timeToValues(values) ==
18879                         Interpolator.Result.FREEZE_END) {
18880                     cache.state = ScrollabilityCache.OFF;
18881                 } else {
18882                     cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
18883                 }
18884 
18885                 // This will make the scroll bars inval themselves after
18886                 // drawing. We only want this when we're fading so that
18887                 // we prevent excessive redraws
18888                 invalidate = true;
18889             } else {
18890                 // We're just on -- but we may have been fading before so
18891                 // reset alpha
18892                 cache.scrollBar.mutate().setAlpha(255);
18893             }
18894 
18895             final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
18896             final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
18897                     && !isVerticalScrollBarHidden();
18898 
18899             // Fork out the scroll bar drawing for round wearable devices.
18900             if (mRoundScrollbarRenderer != null) {
18901                 if (drawVerticalScrollBar) {
18902                     final Rect bounds = cache.mScrollBarBounds;
18903                     getVerticalScrollBarBounds(bounds, null);
18904                     mRoundScrollbarRenderer.drawRoundScrollbars(
18905                             canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
18906                     if (invalidate) {
18907                         invalidate();
18908                     }
18909                 }
18910                 // Do not draw horizontal scroll bars for round wearable devices.
18911             } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
18912                 final ScrollBarDrawable scrollBar = cache.scrollBar;
18913 
18914                 if (drawHorizontalScrollBar) {
18915                     scrollBar.setParameters(computeHorizontalScrollRange(),
18916                             computeHorizontalScrollOffset(),
18917                             computeHorizontalScrollExtent(), false);
18918                     final Rect bounds = cache.mScrollBarBounds;
18919                     getHorizontalScrollBarBounds(bounds, null);
18920                     onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
18921                             bounds.right, bounds.bottom);
18922                     if (invalidate) {
18923                         invalidate(bounds);
18924                     }
18925                 }
18926 
18927                 if (drawVerticalScrollBar) {
18928                     scrollBar.setParameters(computeVerticalScrollRange(),
18929                             computeVerticalScrollOffset(),
18930                             computeVerticalScrollExtent(), true);
18931                     final Rect bounds = cache.mScrollBarBounds;
18932                     getVerticalScrollBarBounds(bounds, null);
18933                     onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
18934                             bounds.right, bounds.bottom);
18935                     if (invalidate) {
18936                         invalidate(bounds);
18937                     }
18938                 }
18939             }
18940         }
18941     }
18942 
18943     /**
18944      * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
18945      * FastScroller is visible.
18946      * @return whether to temporarily hide the vertical scrollbar
18947      * @hide
18948      */
isVerticalScrollBarHidden()18949     protected boolean isVerticalScrollBarHidden() {
18950         return false;
18951     }
18952 
18953     /**
18954      * <p>Draw the horizontal scrollbar if
18955      * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
18956      *
18957      * @param canvas the canvas on which to draw the scrollbar
18958      * @param scrollBar the scrollbar's drawable
18959      *
18960      * @see #isHorizontalScrollBarEnabled()
18961      * @see #computeHorizontalScrollRange()
18962      * @see #computeHorizontalScrollExtent()
18963      * @see #computeHorizontalScrollOffset()
18964      * @hide
18965      */
18966     @UnsupportedAppUsage
onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t, int r, int b)18967     protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
18968             int l, int t, int r, int b) {
18969         scrollBar.setBounds(l, t, r, b);
18970         scrollBar.draw(canvas);
18971     }
18972 
18973     /**
18974      * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
18975      * returns true.</p>
18976      *
18977      * @param canvas the canvas on which to draw the scrollbar
18978      * @param scrollBar the scrollbar's drawable
18979      *
18980      * @see #isVerticalScrollBarEnabled()
18981      * @see #computeVerticalScrollRange()
18982      * @see #computeVerticalScrollExtent()
18983      * @see #computeVerticalScrollOffset()
18984      * @hide
18985      */
18986     @UnsupportedAppUsage
onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t, int r, int b)18987     protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
18988             int l, int t, int r, int b) {
18989         scrollBar.setBounds(l, t, r, b);
18990         scrollBar.draw(canvas);
18991     }
18992 
18993     /**
18994      * Implement this to do your drawing.
18995      *
18996      * @param canvas the canvas on which the background will be drawn
18997      */
onDraw(Canvas canvas)18998     protected void onDraw(Canvas canvas) {
18999     }
19000 
19001     /*
19002      * Caller is responsible for calling requestLayout if necessary.
19003      * (This allows addViewInLayout to not request a new layout.)
19004      */
19005     @UnsupportedAppUsage
assignParent(ViewParent parent)19006     void assignParent(ViewParent parent) {
19007         if (mParent == null) {
19008             mParent = parent;
19009         } else if (parent == null) {
19010             mParent = null;
19011         } else {
19012             throw new RuntimeException("view " + this + " being added, but"
19013                     + " it already has a parent");
19014         }
19015     }
19016 
19017     /**
19018      * This is called when the view is attached to a window.  At this point it
19019      * has a Surface and will start drawing.  Note that this function is
19020      * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
19021      * however it may be called any time before the first onDraw -- including
19022      * before or after {@link #onMeasure(int, int)}.
19023      *
19024      * @see #onDetachedFromWindow()
19025      */
19026     @CallSuper
onAttachedToWindow()19027     protected void onAttachedToWindow() {
19028         if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
19029             mParent.requestTransparentRegion(this);
19030         }
19031 
19032         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
19033 
19034         jumpDrawablesToCurrentState();
19035 
19036         AccessibilityNodeIdManager.getInstance().registerViewWithId(this, getAccessibilityViewId());
19037         resetSubtreeAccessibilityStateChanged();
19038 
19039         // rebuild, since Outline not maintained while View is detached
19040         rebuildOutline();
19041 
19042         if (isFocused()) {
19043             notifyFocusChangeToInputMethodManager(true /* hasFocus */);
19044         }
19045     }
19046 
19047     /**
19048      * Resolve all RTL related properties.
19049      *
19050      * @return true if resolution of RTL properties has been done
19051      *
19052      * @hide
19053      */
resolveRtlPropertiesIfNeeded()19054     public boolean resolveRtlPropertiesIfNeeded() {
19055         if (!needRtlPropertiesResolution()) return false;
19056 
19057         // Order is important here: LayoutDirection MUST be resolved first
19058         if (!isLayoutDirectionResolved()) {
19059             resolveLayoutDirection();
19060             resolveLayoutParams();
19061         }
19062         // ... then we can resolve the others properties depending on the resolved LayoutDirection.
19063         if (!isTextDirectionResolved()) {
19064             resolveTextDirection();
19065         }
19066         if (!isTextAlignmentResolved()) {
19067             resolveTextAlignment();
19068         }
19069         // Should resolve Drawables before Padding because we need the layout direction of the
19070         // Drawable to correctly resolve Padding.
19071         if (!areDrawablesResolved()) {
19072             resolveDrawables();
19073         }
19074         if (!isPaddingResolved()) {
19075             resolvePadding();
19076         }
19077         onRtlPropertiesChanged(getLayoutDirection());
19078         return true;
19079     }
19080 
19081     /**
19082      * Reset resolution of all RTL related properties.
19083      *
19084      * @hide
19085      */
19086     @TestApi
resetRtlProperties()19087     public void resetRtlProperties() {
19088         resetResolvedLayoutDirection();
19089         resetResolvedTextDirection();
19090         resetResolvedTextAlignment();
19091         resetResolvedPadding();
19092         resetResolvedDrawables();
19093     }
19094 
19095     /**
19096      * @see #onScreenStateChanged(int)
19097      */
dispatchScreenStateChanged(int screenState)19098     void dispatchScreenStateChanged(int screenState) {
19099         onScreenStateChanged(screenState);
19100     }
19101 
19102     /**
19103      * This method is called whenever the state of the screen this view is
19104      * attached to changes. A state change will usually occurs when the screen
19105      * turns on or off (whether it happens automatically or the user does it
19106      * manually.)
19107      *
19108      * @param screenState The new state of the screen. Can be either
19109      *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
19110      */
onScreenStateChanged(int screenState)19111     public void onScreenStateChanged(int screenState) {
19112     }
19113 
19114     /**
19115      * @see #onMovedToDisplay(int, Configuration)
19116      */
dispatchMovedToDisplay(Display display, Configuration config)19117     void dispatchMovedToDisplay(Display display, Configuration config) {
19118         mAttachInfo.mDisplay = display;
19119         mAttachInfo.mDisplayState = display.getState();
19120         onMovedToDisplay(display.getDisplayId(), config);
19121     }
19122 
19123     /**
19124      * Called by the system when the hosting activity is moved from one display to another without
19125      * recreation. This means that the activity is declared to handle all changes to configuration
19126      * that happened when it was switched to another display, so it wasn't destroyed and created
19127      * again.
19128      *
19129      * <p>This call will be followed by {@link #onConfigurationChanged(Configuration)} if the
19130      * applied configuration actually changed. It is up to app developer to choose whether to handle
19131      * the change in this method or in the following {@link #onConfigurationChanged(Configuration)}
19132      * call.
19133      *
19134      * <p>Use this callback to track changes to the displays if some functionality relies on an
19135      * association with some display properties.
19136      *
19137      * @param displayId The id of the display to which the view was moved.
19138      * @param config Configuration of the resources on new display after move.
19139      *
19140      * @see #onConfigurationChanged(Configuration)
19141      * @hide
19142      */
onMovedToDisplay(int displayId, Configuration config)19143     public void onMovedToDisplay(int displayId, Configuration config) {
19144     }
19145 
19146     /**
19147      * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
19148      */
19149     @UnsupportedAppUsage
hasRtlSupport()19150     private boolean hasRtlSupport() {
19151         return mContext.getApplicationInfo().hasRtlSupport();
19152     }
19153 
19154     /**
19155      * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
19156      * RTL not supported)
19157      */
isRtlCompatibilityMode()19158     private boolean isRtlCompatibilityMode() {
19159         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
19160         return targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1 || !hasRtlSupport();
19161     }
19162 
19163     /**
19164      * @return true if RTL properties need resolution.
19165      *
19166      */
needRtlPropertiesResolution()19167     private boolean needRtlPropertiesResolution() {
19168         return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
19169     }
19170 
19171     /**
19172      * Called when any RTL property (layout direction or text direction or text alignment) has
19173      * been changed.
19174      *
19175      * Subclasses need to override this method to take care of cached information that depends on the
19176      * resolved layout direction, or to inform child views that inherit their layout direction.
19177      *
19178      * The default implementation does nothing.
19179      *
19180      * @param layoutDirection the direction of the layout
19181      *
19182      * @see #LAYOUT_DIRECTION_LTR
19183      * @see #LAYOUT_DIRECTION_RTL
19184      */
onRtlPropertiesChanged(@esolvedLayoutDir int layoutDirection)19185     public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
19186     }
19187 
19188     /**
19189      * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
19190      * that the parent directionality can and will be resolved before its children.
19191      *
19192      * @return true if resolution has been done, false otherwise.
19193      *
19194      * @hide
19195      */
resolveLayoutDirection()19196     public boolean resolveLayoutDirection() {
19197         // Clear any previous layout direction resolution
19198         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
19199 
19200         if (hasRtlSupport()) {
19201             // Set resolved depending on layout direction
19202             switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
19203                     PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
19204                 case LAYOUT_DIRECTION_INHERIT:
19205                     // We cannot resolve yet. LTR is by default and let the resolution happen again
19206                     // later to get the correct resolved value
19207                     if (!canResolveLayoutDirection()) return false;
19208 
19209                     // Parent has not yet resolved, LTR is still the default
19210                     try {
19211                         if (!mParent.isLayoutDirectionResolved()) return false;
19212 
19213                         if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
19214                             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
19215                         }
19216                     } catch (AbstractMethodError e) {
19217                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19218                                 " does not fully implement ViewParent", e);
19219                     }
19220                     break;
19221                 case LAYOUT_DIRECTION_RTL:
19222                     mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
19223                     break;
19224                 case LAYOUT_DIRECTION_LOCALE:
19225                     if((LAYOUT_DIRECTION_RTL ==
19226                             TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
19227                         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
19228                     }
19229                     break;
19230                 default:
19231                     // Nothing to do, LTR by default
19232             }
19233         }
19234 
19235         // Set to resolved
19236         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
19237         return true;
19238     }
19239 
19240     /**
19241      * Check if layout direction resolution can be done.
19242      *
19243      * @return true if layout direction resolution can be done otherwise return false.
19244      */
canResolveLayoutDirection()19245     public boolean canResolveLayoutDirection() {
19246         switch (getRawLayoutDirection()) {
19247             case LAYOUT_DIRECTION_INHERIT:
19248                 if (mParent != null) {
19249                     try {
19250                         return mParent.canResolveLayoutDirection();
19251                     } catch (AbstractMethodError e) {
19252                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19253                                 " does not fully implement ViewParent", e);
19254                     }
19255                 }
19256                 return false;
19257 
19258             default:
19259                 return true;
19260         }
19261     }
19262 
19263     /**
19264      * Reset the resolved layout direction. Layout direction will be resolved during a call to
19265      * {@link #onMeasure(int, int)}.
19266      *
19267      * @hide
19268      */
19269     @TestApi
resetResolvedLayoutDirection()19270     public void resetResolvedLayoutDirection() {
19271         // Reset the current resolved bits
19272         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
19273     }
19274 
19275     /**
19276      * @return true if the layout direction is inherited.
19277      *
19278      * @hide
19279      */
isLayoutDirectionInherited()19280     public boolean isLayoutDirectionInherited() {
19281         return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
19282     }
19283 
19284     /**
19285      * @return true if layout direction has been resolved.
19286      */
isLayoutDirectionResolved()19287     public boolean isLayoutDirectionResolved() {
19288         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
19289     }
19290 
19291     /**
19292      * Return if padding has been resolved
19293      *
19294      * @hide
19295      */
19296     @UnsupportedAppUsage
isPaddingResolved()19297     boolean isPaddingResolved() {
19298         return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
19299     }
19300 
19301     /**
19302      * Resolves padding depending on layout direction, if applicable, and
19303      * recomputes internal padding values to adjust for scroll bars.
19304      *
19305      * @hide
19306      */
19307     @UnsupportedAppUsage
resolvePadding()19308     public void resolvePadding() {
19309         final int resolvedLayoutDirection = getLayoutDirection();
19310 
19311         if (!isRtlCompatibilityMode()) {
19312             // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
19313             // If start / end padding are defined, they will be resolved (hence overriding) to
19314             // left / right or right / left depending on the resolved layout direction.
19315             // If start / end padding are not defined, use the left / right ones.
19316             if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
19317                 Rect padding = sThreadLocal.get();
19318                 if (padding == null) {
19319                     padding = new Rect();
19320                     sThreadLocal.set(padding);
19321                 }
19322                 mBackground.getPadding(padding);
19323                 if (!mLeftPaddingDefined) {
19324                     mUserPaddingLeftInitial = padding.left;
19325                 }
19326                 if (!mRightPaddingDefined) {
19327                     mUserPaddingRightInitial = padding.right;
19328                 }
19329             }
19330             switch (resolvedLayoutDirection) {
19331                 case LAYOUT_DIRECTION_RTL:
19332                     if (mUserPaddingStart != UNDEFINED_PADDING) {
19333                         mUserPaddingRight = mUserPaddingStart;
19334                     } else {
19335                         mUserPaddingRight = mUserPaddingRightInitial;
19336                     }
19337                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
19338                         mUserPaddingLeft = mUserPaddingEnd;
19339                     } else {
19340                         mUserPaddingLeft = mUserPaddingLeftInitial;
19341                     }
19342                     break;
19343                 case LAYOUT_DIRECTION_LTR:
19344                 default:
19345                     if (mUserPaddingStart != UNDEFINED_PADDING) {
19346                         mUserPaddingLeft = mUserPaddingStart;
19347                     } else {
19348                         mUserPaddingLeft = mUserPaddingLeftInitial;
19349                     }
19350                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
19351                         mUserPaddingRight = mUserPaddingEnd;
19352                     } else {
19353                         mUserPaddingRight = mUserPaddingRightInitial;
19354                     }
19355             }
19356 
19357             mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
19358         }
19359 
19360         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
19361         onRtlPropertiesChanged(resolvedLayoutDirection);
19362 
19363         mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
19364     }
19365 
19366     /**
19367      * Reset the resolved layout direction.
19368      *
19369      * @hide
19370      */
19371     @TestApi
resetResolvedPadding()19372     public void resetResolvedPadding() {
19373         resetResolvedPaddingInternal();
19374     }
19375 
19376     /**
19377      * Used when we only want to reset *this* view's padding and not trigger overrides
19378      * in ViewGroup that reset children too.
19379      */
resetResolvedPaddingInternal()19380     void resetResolvedPaddingInternal() {
19381         mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
19382     }
19383 
19384     /**
19385      * This is called when the view is detached from a window.  At this point it
19386      * no longer has a surface for drawing.
19387      *
19388      * @see #onAttachedToWindow()
19389      */
19390     @CallSuper
onDetachedFromWindow()19391     protected void onDetachedFromWindow() {
19392     }
19393 
19394     /**
19395      * This is a framework-internal mirror of onDetachedFromWindow() that's called
19396      * after onDetachedFromWindow().
19397      *
19398      * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
19399      * The super method should be called at the end of the overridden method to ensure
19400      * subclasses are destroyed first
19401      *
19402      * @hide
19403      */
19404     @CallSuper
19405     @UnsupportedAppUsage
onDetachedFromWindowInternal()19406     protected void onDetachedFromWindowInternal() {
19407         mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
19408         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
19409         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
19410 
19411         removeUnsetPressCallback();
19412         removeLongPressCallback();
19413         removePerformClickCallback();
19414         cancel(mSendViewScrolledAccessibilityEvent);
19415         stopNestedScroll();
19416 
19417         // Anything that started animating right before detach should already
19418         // be in its final state when re-attached.
19419         jumpDrawablesToCurrentState();
19420 
19421         destroyDrawingCache();
19422 
19423         cleanupDraw();
19424         mCurrentAnimation = null;
19425 
19426         if ((mViewFlags & TOOLTIP) == TOOLTIP) {
19427             hideTooltip();
19428         }
19429 
19430         AccessibilityNodeIdManager.getInstance().unregisterViewWithId(getAccessibilityViewId());
19431     }
19432 
cleanupDraw()19433     private void cleanupDraw() {
19434         resetDisplayList();
19435         if (mAttachInfo != null) {
19436             mAttachInfo.mViewRootImpl.cancelInvalidate(this);
19437         }
19438     }
19439 
invalidateInheritedLayoutMode(int layoutModeOfRoot)19440     void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
19441     }
19442 
19443     /**
19444      * @return The number of times this view has been attached to a window
19445      */
getWindowAttachCount()19446     protected int getWindowAttachCount() {
19447         return mWindowAttachCount;
19448     }
19449 
19450     /**
19451      * Retrieve a unique token identifying the window this view is attached to.
19452      * @return Return the window's token for use in
19453      * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
19454      */
getWindowToken()19455     public IBinder getWindowToken() {
19456         return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
19457     }
19458 
19459     /**
19460      * Retrieve the {@link WindowId} for the window this view is
19461      * currently attached to.
19462      */
getWindowId()19463     public WindowId getWindowId() {
19464         AttachInfo ai = mAttachInfo;
19465         if (ai == null) {
19466             return null;
19467         }
19468         if (ai.mWindowId == null) {
19469             try {
19470                 ai.mIWindowId = ai.mSession.getWindowId(ai.mWindowToken);
19471                 if (ai.mIWindowId != null) {
19472                     ai.mWindowId = new WindowId(ai.mIWindowId);
19473                 }
19474             } catch (RemoteException e) {
19475             }
19476         }
19477         return ai.mWindowId;
19478     }
19479 
19480     /**
19481      * Retrieve a unique token identifying the top-level "real" window of
19482      * the window that this view is attached to.  That is, this is like
19483      * {@link #getWindowToken}, except if the window this view in is a panel
19484      * window (attached to another containing window), then the token of
19485      * the containing window is returned instead.
19486      *
19487      * @return Returns the associated window token, either
19488      * {@link #getWindowToken()} or the containing window's token.
19489      */
getApplicationWindowToken()19490     public IBinder getApplicationWindowToken() {
19491         AttachInfo ai = mAttachInfo;
19492         if (ai != null) {
19493             IBinder appWindowToken = ai.mPanelParentWindowToken;
19494             if (appWindowToken == null) {
19495                 appWindowToken = ai.mWindowToken;
19496             }
19497             return appWindowToken;
19498         }
19499         return null;
19500     }
19501 
19502     /**
19503      * Gets the logical display to which the view's window has been attached.
19504      *
19505      * @return The logical display, or null if the view is not currently attached to a window.
19506      */
getDisplay()19507     public Display getDisplay() {
19508         return mAttachInfo != null ? mAttachInfo.mDisplay : null;
19509     }
19510 
19511     /**
19512      * Retrieve private session object this view hierarchy is using to
19513      * communicate with the window manager.
19514      * @return the session object to communicate with the window manager
19515      */
19516     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
getWindowSession()19517     /*package*/ IWindowSession getWindowSession() {
19518         return mAttachInfo != null ? mAttachInfo.mSession : null;
19519     }
19520 
19521     /**
19522      * Return the window this view is currently attached to. Used in
19523      * {@link android.app.ActivityView} to communicate with WM.
19524      * @hide
19525      */
getWindow()19526     protected IWindow getWindow() {
19527         return mAttachInfo != null ? mAttachInfo.mWindow : null;
19528     }
19529 
19530     /**
19531      * Return the visibility value of the least visible component passed.
19532      */
combineVisibility(int vis1, int vis2)19533     int combineVisibility(int vis1, int vis2) {
19534         // This works because VISIBLE < INVISIBLE < GONE.
19535         return Math.max(vis1, vis2);
19536     }
19537 
19538     /**
19539      * @param info the {@link android.view.View.AttachInfo} to associated with
19540      *        this view
19541      */
19542     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
dispatchAttachedToWindow(AttachInfo info, int visibility)19543     void dispatchAttachedToWindow(AttachInfo info, int visibility) {
19544         mAttachInfo = info;
19545         if (mOverlay != null) {
19546             mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
19547         }
19548         mWindowAttachCount++;
19549         // We will need to evaluate the drawable state at least once.
19550         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
19551         if (mFloatingTreeObserver != null) {
19552             info.mTreeObserver.merge(mFloatingTreeObserver);
19553             mFloatingTreeObserver = null;
19554         }
19555 
19556         registerPendingFrameMetricsObservers();
19557 
19558         if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
19559             mAttachInfo.mScrollContainers.add(this);
19560             mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
19561         }
19562         // Transfer all pending runnables.
19563         if (mRunQueue != null) {
19564             mRunQueue.executeActions(info.mHandler);
19565             mRunQueue = null;
19566         }
19567         performCollectViewAttributes(mAttachInfo, visibility);
19568         onAttachedToWindow();
19569 
19570         ListenerInfo li = mListenerInfo;
19571         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
19572                 li != null ? li.mOnAttachStateChangeListeners : null;
19573         if (listeners != null && listeners.size() > 0) {
19574             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
19575             // perform the dispatching. The iterator is a safe guard against listeners that
19576             // could mutate the list by calling the various add/remove methods. This prevents
19577             // the array from being modified while we iterate it.
19578             for (OnAttachStateChangeListener listener : listeners) {
19579                 listener.onViewAttachedToWindow(this);
19580             }
19581         }
19582 
19583         int vis = info.mWindowVisibility;
19584         if (vis != GONE) {
19585             onWindowVisibilityChanged(vis);
19586             if (isShown()) {
19587                 // Calling onVisibilityAggregated directly here since the subtree will also
19588                 // receive dispatchAttachedToWindow and this same call
19589                 onVisibilityAggregated(vis == VISIBLE);
19590             }
19591         }
19592 
19593         // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
19594         // As all views in the subtree will already receive dispatchAttachedToWindow
19595         // traversing the subtree again here is not desired.
19596         onVisibilityChanged(this, visibility);
19597 
19598         if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
19599             // If nobody has evaluated the drawable state yet, then do it now.
19600             refreshDrawableState();
19601         }
19602         needGlobalAttributesUpdate(false);
19603 
19604         notifyEnterOrExitForAutoFillIfNeeded(true);
19605     }
19606 
19607     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
dispatchDetachedFromWindow()19608     void dispatchDetachedFromWindow() {
19609         AttachInfo info = mAttachInfo;
19610         if (info != null) {
19611             int vis = info.mWindowVisibility;
19612             if (vis != GONE) {
19613                 onWindowVisibilityChanged(GONE);
19614                 if (isShown()) {
19615                     // Invoking onVisibilityAggregated directly here since the subtree
19616                     // will also receive detached from window
19617                     onVisibilityAggregated(false);
19618                 }
19619             }
19620         }
19621 
19622         onDetachedFromWindow();
19623         onDetachedFromWindowInternal();
19624 
19625         InputMethodManager imm = getContext().getSystemService(InputMethodManager.class);
19626         if (imm != null) {
19627             imm.onViewDetachedFromWindow(this);
19628         }
19629 
19630         ListenerInfo li = mListenerInfo;
19631         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
19632                 li != null ? li.mOnAttachStateChangeListeners : null;
19633         if (listeners != null && listeners.size() > 0) {
19634             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
19635             // perform the dispatching. The iterator is a safe guard against listeners that
19636             // could mutate the list by calling the various add/remove methods. This prevents
19637             // the array from being modified while we iterate it.
19638             for (OnAttachStateChangeListener listener : listeners) {
19639                 listener.onViewDetachedFromWindow(this);
19640             }
19641         }
19642 
19643         if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
19644             mAttachInfo.mScrollContainers.remove(this);
19645             mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
19646         }
19647 
19648         mAttachInfo = null;
19649         if (mOverlay != null) {
19650             mOverlay.getOverlayView().dispatchDetachedFromWindow();
19651         }
19652 
19653         notifyEnterOrExitForAutoFillIfNeeded(false);
19654     }
19655 
19656     /**
19657      * Cancel any deferred high-level input events that were previously posted to the event queue.
19658      *
19659      * <p>Many views post high-level events such as click handlers to the event queue
19660      * to run deferred in order to preserve a desired user experience - clearing visible
19661      * pressed states before executing, etc. This method will abort any events of this nature
19662      * that are currently in flight.</p>
19663      *
19664      * <p>Custom views that generate their own high-level deferred input events should override
19665      * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
19666      *
19667      * <p>This will also cancel pending input events for any child views.</p>
19668      *
19669      * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
19670      * This will not impact newer events posted after this call that may occur as a result of
19671      * lower-level input events still waiting in the queue. If you are trying to prevent
19672      * double-submitted  events for the duration of some sort of asynchronous transaction
19673      * you should also take other steps to protect against unexpected double inputs e.g. calling
19674      * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
19675      * the transaction completes, tracking already submitted transaction IDs, etc.</p>
19676      */
cancelPendingInputEvents()19677     public final void cancelPendingInputEvents() {
19678         dispatchCancelPendingInputEvents();
19679     }
19680 
19681     /**
19682      * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
19683      * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
19684      */
dispatchCancelPendingInputEvents()19685     void dispatchCancelPendingInputEvents() {
19686         mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
19687         onCancelPendingInputEvents();
19688         if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
19689             throw new SuperNotCalledException("View " + getClass().getSimpleName() +
19690                     " did not call through to super.onCancelPendingInputEvents()");
19691         }
19692     }
19693 
19694     /**
19695      * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
19696      * a parent view.
19697      *
19698      * <p>This method is responsible for removing any pending high-level input events that were
19699      * posted to the event queue to run later. Custom view classes that post their own deferred
19700      * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
19701      * {@link android.os.Handler} should override this method, call
19702      * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
19703      * </p>
19704      */
onCancelPendingInputEvents()19705     public void onCancelPendingInputEvents() {
19706         removePerformClickCallback();
19707         cancelLongPress();
19708         mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
19709     }
19710 
19711     /**
19712      * Store this view hierarchy's frozen state into the given container.
19713      *
19714      * @param container The SparseArray in which to save the view's state.
19715      *
19716      * @see #restoreHierarchyState(android.util.SparseArray)
19717      * @see #dispatchSaveInstanceState(android.util.SparseArray)
19718      * @see #onSaveInstanceState()
19719      */
saveHierarchyState(SparseArray<Parcelable> container)19720     public void saveHierarchyState(SparseArray<Parcelable> container) {
19721         dispatchSaveInstanceState(container);
19722     }
19723 
19724     /**
19725      * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
19726      * this view and its children. May be overridden to modify how freezing happens to a
19727      * view's children; for example, some views may want to not store state for their children.
19728      *
19729      * @param container The SparseArray in which to save the view's state.
19730      *
19731      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
19732      * @see #saveHierarchyState(android.util.SparseArray)
19733      * @see #onSaveInstanceState()
19734      */
dispatchSaveInstanceState(SparseArray<Parcelable> container)19735     protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
19736         if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
19737             mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
19738             Parcelable state = onSaveInstanceState();
19739             if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
19740                 throw new IllegalStateException(
19741                         "Derived class did not call super.onSaveInstanceState()");
19742             }
19743             if (state != null) {
19744                 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
19745                 // + ": " + state);
19746                 container.put(mID, state);
19747             }
19748         }
19749     }
19750 
19751     /**
19752      * Hook allowing a view to generate a representation of its internal state
19753      * that can later be used to create a new instance with that same state.
19754      * This state should only contain information that is not persistent or can
19755      * not be reconstructed later. For example, you will never store your
19756      * current position on screen because that will be computed again when a
19757      * new instance of the view is placed in its view hierarchy.
19758      * <p>
19759      * Some examples of things you may store here: the current cursor position
19760      * in a text view (but usually not the text itself since that is stored in a
19761      * content provider or other persistent storage), the currently selected
19762      * item in a list view.
19763      *
19764      * @return Returns a Parcelable object containing the view's current dynamic
19765      *         state, or null if there is nothing interesting to save.
19766      * @see #onRestoreInstanceState(Parcelable)
19767      * @see #saveHierarchyState(SparseArray)
19768      * @see #dispatchSaveInstanceState(SparseArray)
19769      * @see #setSaveEnabled(boolean)
19770      */
19771     @CallSuper
onSaveInstanceState()19772     @Nullable protected Parcelable onSaveInstanceState() {
19773         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
19774         if (mStartActivityRequestWho != null || isAutofilled()
19775                 || mAutofillViewId > LAST_APP_AUTOFILL_ID) {
19776             BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
19777 
19778             if (mStartActivityRequestWho != null) {
19779                 state.mSavedData |= BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED;
19780             }
19781 
19782             if (isAutofilled()) {
19783                 state.mSavedData |= BaseSavedState.IS_AUTOFILLED;
19784             }
19785 
19786             if (mAutofillViewId > LAST_APP_AUTOFILL_ID) {
19787                 state.mSavedData |= BaseSavedState.AUTOFILL_ID;
19788             }
19789 
19790             state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
19791             state.mIsAutofilled = isAutofilled();
19792             state.mAutofillViewId = mAutofillViewId;
19793             return state;
19794         }
19795         return BaseSavedState.EMPTY_STATE;
19796     }
19797 
19798     /**
19799      * Restore this view hierarchy's frozen state from the given container.
19800      *
19801      * @param container The SparseArray which holds previously frozen states.
19802      *
19803      * @see #saveHierarchyState(android.util.SparseArray)
19804      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
19805      * @see #onRestoreInstanceState(android.os.Parcelable)
19806      */
restoreHierarchyState(SparseArray<Parcelable> container)19807     public void restoreHierarchyState(SparseArray<Parcelable> container) {
19808         dispatchRestoreInstanceState(container);
19809     }
19810 
19811     /**
19812      * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
19813      * state for this view and its children. May be overridden to modify how restoring
19814      * happens to a view's children; for example, some views may want to not store state
19815      * for their children.
19816      *
19817      * @param container The SparseArray which holds previously saved state.
19818      *
19819      * @see #dispatchSaveInstanceState(android.util.SparseArray)
19820      * @see #restoreHierarchyState(android.util.SparseArray)
19821      * @see #onRestoreInstanceState(android.os.Parcelable)
19822      */
dispatchRestoreInstanceState(SparseArray<Parcelable> container)19823     protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
19824         if (mID != NO_ID) {
19825             Parcelable state = container.get(mID);
19826             if (state != null) {
19827                 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
19828                 // + ": " + state);
19829                 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
19830                 onRestoreInstanceState(state);
19831                 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
19832                     throw new IllegalStateException(
19833                             "Derived class did not call super.onRestoreInstanceState()");
19834                 }
19835             }
19836         }
19837     }
19838 
19839     /**
19840      * Hook allowing a view to re-apply a representation of its internal state that had previously
19841      * been generated by {@link #onSaveInstanceState}. This function will never be called with a
19842      * null state.
19843      *
19844      * @param state The frozen state that had previously been returned by
19845      *        {@link #onSaveInstanceState}.
19846      *
19847      * @see #onSaveInstanceState()
19848      * @see #restoreHierarchyState(android.util.SparseArray)
19849      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
19850      */
19851     @CallSuper
onRestoreInstanceState(Parcelable state)19852     protected void onRestoreInstanceState(Parcelable state) {
19853         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
19854         if (state != null && !(state instanceof AbsSavedState)) {
19855             throw new IllegalArgumentException("Wrong state class, expecting View State but "
19856                     + "received " + state.getClass().toString() + " instead. This usually happens "
19857                     + "when two views of different type have the same id in the same hierarchy. "
19858                     + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
19859                     + "other views do not use the same id.");
19860         }
19861         if (state != null && state instanceof BaseSavedState) {
19862             BaseSavedState baseState = (BaseSavedState) state;
19863 
19864             if ((baseState.mSavedData & BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED) != 0) {
19865                 mStartActivityRequestWho = baseState.mStartActivityRequestWhoSaved;
19866             }
19867             if ((baseState.mSavedData & BaseSavedState.IS_AUTOFILLED) != 0) {
19868                 setAutofilled(baseState.mIsAutofilled);
19869             }
19870             if ((baseState.mSavedData & BaseSavedState.AUTOFILL_ID) != 0) {
19871                 // It can happen that views have the same view id and the restoration path will not
19872                 // be able to distinguish between them. The autofill id needs to be unique though.
19873                 // Hence prevent the same autofill view id from being restored multiple times.
19874                 ((BaseSavedState) state).mSavedData &= ~BaseSavedState.AUTOFILL_ID;
19875 
19876                 if ((mPrivateFlags3 & PFLAG3_AUTOFILLID_EXPLICITLY_SET) != 0) {
19877                     // Ignore when view already set it through setAutofillId();
19878                     if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.DEBUG)) {
19879                         Log.d(AUTOFILL_LOG_TAG, "onRestoreInstanceState(): not setting autofillId "
19880                                 + "to " + baseState.mAutofillViewId + " because view explicitly set"
19881                                 + " it to " + mAutofillId);
19882                     }
19883                 } else {
19884                     mAutofillViewId = baseState.mAutofillViewId;
19885                     mAutofillId = null; // will be set on demand by getAutofillId()
19886                 }
19887             }
19888         }
19889     }
19890 
19891     /**
19892      * <p>Return the time at which the drawing of the view hierarchy started.</p>
19893      *
19894      * @return the drawing start time in milliseconds
19895      */
getDrawingTime()19896     public long getDrawingTime() {
19897         return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
19898     }
19899 
19900     /**
19901      * <p>Enables or disables the duplication of the parent's state into this view. When
19902      * duplication is enabled, this view gets its drawable state from its parent rather
19903      * than from its own internal properties.</p>
19904      *
19905      * <p>Note: in the current implementation, setting this property to true after the
19906      * view was added to a ViewGroup might have no effect at all. This property should
19907      * always be used from XML or set to true before adding this view to a ViewGroup.</p>
19908      *
19909      * <p>Note: if this view's parent addStateFromChildren property is enabled and this
19910      * property is enabled, an exception will be thrown.</p>
19911      *
19912      * <p>Note: if the child view uses and updates additional states which are unknown to the
19913      * parent, these states should not be affected by this method.</p>
19914      *
19915      * @param enabled True to enable duplication of the parent's drawable state, false
19916      *                to disable it.
19917      *
19918      * @see #getDrawableState()
19919      * @see #isDuplicateParentStateEnabled()
19920      */
setDuplicateParentStateEnabled(boolean enabled)19921     public void setDuplicateParentStateEnabled(boolean enabled) {
19922         setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
19923     }
19924 
19925     /**
19926      * <p>Indicates whether this duplicates its drawable state from its parent.</p>
19927      *
19928      * @return True if this view's drawable state is duplicated from the parent,
19929      *         false otherwise
19930      *
19931      * @see #getDrawableState()
19932      * @see #setDuplicateParentStateEnabled(boolean)
19933      */
19934     @InspectableProperty(name = "duplicateParentState")
isDuplicateParentStateEnabled()19935     public boolean isDuplicateParentStateEnabled() {
19936         return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
19937     }
19938 
19939     /**
19940      * <p>Specifies the type of layer backing this view. The layer can be
19941      * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
19942      * {@link #LAYER_TYPE_HARDWARE}.</p>
19943      *
19944      * <p>A layer is associated with an optional {@link android.graphics.Paint}
19945      * instance that controls how the layer is composed on screen. The following
19946      * properties of the paint are taken into account when composing the layer:</p>
19947      * <ul>
19948      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
19949      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
19950      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
19951      * </ul>
19952      *
19953      * <p>If this view has an alpha value set to < 1.0 by calling
19954      * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
19955      * by this view's alpha value.</p>
19956      *
19957      * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
19958      * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
19959      * for more information on when and how to use layers.</p>
19960      *
19961      * @param layerType The type of layer to use with this view, must be one of
19962      *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
19963      *        {@link #LAYER_TYPE_HARDWARE}
19964      * @param paint The paint used to compose the layer. This argument is optional
19965      *        and can be null. It is ignored when the layer type is
19966      *        {@link #LAYER_TYPE_NONE}
19967      *
19968      * @see #getLayerType()
19969      * @see #LAYER_TYPE_NONE
19970      * @see #LAYER_TYPE_SOFTWARE
19971      * @see #LAYER_TYPE_HARDWARE
19972      * @see #setAlpha(float)
19973      *
19974      * @attr ref android.R.styleable#View_layerType
19975      */
setLayerType(@ayerType int layerType, @Nullable Paint paint)19976     public void setLayerType(@LayerType int layerType, @Nullable Paint paint) {
19977         if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
19978             throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
19979                     + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
19980         }
19981 
19982         boolean typeChanged = mRenderNode.setLayerType(layerType);
19983 
19984         if (!typeChanged) {
19985             setLayerPaint(paint);
19986             return;
19987         }
19988 
19989         if (layerType != LAYER_TYPE_SOFTWARE) {
19990             // Destroy any previous software drawing cache if present
19991             // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
19992             // drawing cache created in View#draw when drawing to a SW canvas.
19993             destroyDrawingCache();
19994         }
19995 
19996         mLayerType = layerType;
19997         mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
19998         mRenderNode.setLayerPaint(mLayerPaint);
19999 
20000         // draw() behaves differently if we are on a layer, so we need to
20001         // invalidate() here
20002         invalidateParentCaches();
20003         invalidate(true);
20004     }
20005 
20006     /**
20007      * Updates the {@link Paint} object used with the current layer (used only if the current
20008      * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
20009      * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
20010      * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
20011      * ensure that the view gets redrawn immediately.
20012      *
20013      * <p>A layer is associated with an optional {@link android.graphics.Paint}
20014      * instance that controls how the layer is composed on screen. The following
20015      * properties of the paint are taken into account when composing the layer:</p>
20016      * <ul>
20017      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
20018      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
20019      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
20020      * </ul>
20021      *
20022      * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
20023      * alpha value of the layer's paint is superseded by this view's alpha value.</p>
20024      *
20025      * @param paint The paint used to compose the layer. This argument is optional
20026      *        and can be null. It is ignored when the layer type is
20027      *        {@link #LAYER_TYPE_NONE}
20028      *
20029      * @see #setLayerType(int, android.graphics.Paint)
20030      */
setLayerPaint(@ullable Paint paint)20031     public void setLayerPaint(@Nullable Paint paint) {
20032         int layerType = getLayerType();
20033         if (layerType != LAYER_TYPE_NONE) {
20034             mLayerPaint = paint;
20035             if (layerType == LAYER_TYPE_HARDWARE) {
20036                 if (mRenderNode.setLayerPaint(paint)) {
20037                     invalidateViewProperty(false, false);
20038                 }
20039             } else {
20040                 invalidate();
20041             }
20042         }
20043     }
20044 
20045     /**
20046      * Indicates what type of layer is currently associated with this view. By default
20047      * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
20048      * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
20049      * for more information on the different types of layers.
20050      *
20051      * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
20052      *         {@link #LAYER_TYPE_HARDWARE}
20053      *
20054      * @see #setLayerType(int, android.graphics.Paint)
20055      * @see #buildLayer()
20056      * @see #LAYER_TYPE_NONE
20057      * @see #LAYER_TYPE_SOFTWARE
20058      * @see #LAYER_TYPE_HARDWARE
20059      */
20060     @InspectableProperty(enumMapping = {
20061             @EnumEntry(value = LAYER_TYPE_NONE, name = "none"),
20062             @EnumEntry(value = LAYER_TYPE_SOFTWARE, name = "software"),
20063             @EnumEntry(value = LAYER_TYPE_HARDWARE, name = "hardware")
20064     })
20065     @LayerType
getLayerType()20066     public int getLayerType() {
20067         return mLayerType;
20068     }
20069 
20070     /**
20071      * Forces this view's layer to be created and this view to be rendered
20072      * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
20073      * invoking this method will have no effect.
20074      *
20075      * This method can for instance be used to render a view into its layer before
20076      * starting an animation. If this view is complex, rendering into the layer
20077      * before starting the animation will avoid skipping frames.
20078      *
20079      * @throws IllegalStateException If this view is not attached to a window
20080      *
20081      * @see #setLayerType(int, android.graphics.Paint)
20082      */
buildLayer()20083     public void buildLayer() {
20084         if (mLayerType == LAYER_TYPE_NONE) return;
20085 
20086         final AttachInfo attachInfo = mAttachInfo;
20087         if (attachInfo == null) {
20088             throw new IllegalStateException("This view must be attached to a window first");
20089         }
20090 
20091         if (getWidth() == 0 || getHeight() == 0) {
20092             return;
20093         }
20094 
20095         switch (mLayerType) {
20096             case LAYER_TYPE_HARDWARE:
20097                 updateDisplayListIfDirty();
20098                 if (attachInfo.mThreadedRenderer != null && mRenderNode.hasDisplayList()) {
20099                     attachInfo.mThreadedRenderer.buildLayer(mRenderNode);
20100                 }
20101                 break;
20102             case LAYER_TYPE_SOFTWARE:
20103                 buildDrawingCache(true);
20104                 break;
20105         }
20106     }
20107 
20108     /**
20109      * Destroys all hardware rendering resources. This method is invoked
20110      * when the system needs to reclaim resources. Upon execution of this
20111      * method, you should free any OpenGL resources created by the view.
20112      *
20113      * Note: you <strong>must</strong> call
20114      * <code>super.destroyHardwareResources()</code> when overriding
20115      * this method.
20116      *
20117      * @hide
20118      */
20119     @CallSuper
20120     @UnsupportedAppUsage
destroyHardwareResources()20121     protected void destroyHardwareResources() {
20122         if (mOverlay != null) {
20123             mOverlay.getOverlayView().destroyHardwareResources();
20124         }
20125         if (mGhostView != null) {
20126             mGhostView.destroyHardwareResources();
20127         }
20128     }
20129 
20130     /**
20131      * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
20132      * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
20133      * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
20134      * the cache is enabled. To benefit from the cache, you must request the drawing cache by
20135      * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
20136      * null.</p>
20137      *
20138      * <p>Enabling the drawing cache is similar to
20139      * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
20140      * acceleration is turned off. When hardware acceleration is turned on, enabling the
20141      * drawing cache has no effect on rendering because the system uses a different mechanism
20142      * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
20143      * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
20144      * for information on how to enable software and hardware layers.</p>
20145      *
20146      * <p>This API can be used to manually generate
20147      * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
20148      * {@link #getDrawingCache()}.</p>
20149      *
20150      * @param enabled true to enable the drawing cache, false otherwise
20151      *
20152      * @see #isDrawingCacheEnabled()
20153      * @see #getDrawingCache()
20154      * @see #buildDrawingCache()
20155      * @see #setLayerType(int, android.graphics.Paint)
20156      *
20157      * @deprecated The view drawing cache was largely made obsolete with the introduction of
20158      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
20159      * layers are largely unnecessary and can easily result in a net loss in performance due to the
20160      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
20161      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
20162      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
20163      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
20164      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
20165      * software-rendered usages are discouraged and have compatibility issues with hardware-only
20166      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
20167      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
20168      * reports or unit testing the {@link PixelCopy} API is recommended.
20169      */
20170     @Deprecated
setDrawingCacheEnabled(boolean enabled)20171     public void setDrawingCacheEnabled(boolean enabled) {
20172         mCachingFailed = false;
20173         setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
20174     }
20175 
20176     /**
20177      * <p>Indicates whether the drawing cache is enabled for this view.</p>
20178      *
20179      * @return true if the drawing cache is enabled
20180      *
20181      * @see #setDrawingCacheEnabled(boolean)
20182      * @see #getDrawingCache()
20183      *
20184      * @deprecated The view drawing cache was largely made obsolete with the introduction of
20185      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
20186      * layers are largely unnecessary and can easily result in a net loss in performance due to the
20187      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
20188      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
20189      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
20190      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
20191      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
20192      * software-rendered usages are discouraged and have compatibility issues with hardware-only
20193      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
20194      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
20195      * reports or unit testing the {@link PixelCopy} API is recommended.
20196      */
20197     @Deprecated
20198     @ViewDebug.ExportedProperty(category = "drawing")
isDrawingCacheEnabled()20199     public boolean isDrawingCacheEnabled() {
20200         return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
20201     }
20202 
20203     /**
20204      * Debugging utility which recursively outputs the dirty state of a view and its
20205      * descendants.
20206      *
20207      * @hide
20208      */
20209     @SuppressWarnings({"UnusedDeclaration"})
outputDirtyFlags(String indent, boolean clear, int clearMask)20210     public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
20211         Log.d(VIEW_LOG_TAG, indent + this + "             DIRTY("
20212                 + (mPrivateFlags & View.PFLAG_DIRTY_MASK)
20213                 + ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID("
20214                 + (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID)
20215                 + ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
20216         if (clear) {
20217             mPrivateFlags &= clearMask;
20218         }
20219         if (this instanceof ViewGroup) {
20220             ViewGroup parent = (ViewGroup) this;
20221             final int count = parent.getChildCount();
20222             for (int i = 0; i < count; i++) {
20223                 final View child = parent.getChildAt(i);
20224                 child.outputDirtyFlags(indent + "  ", clear, clearMask);
20225             }
20226         }
20227     }
20228 
20229     /**
20230      * This method is used by ViewGroup to cause its children to restore or recreate their
20231      * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
20232      * to recreate its own display list, which would happen if it went through the normal
20233      * draw/dispatchDraw mechanisms.
20234      *
20235      * @hide
20236      */
dispatchGetDisplayList()20237     protected void dispatchGetDisplayList() {}
20238 
20239     /**
20240      * A view that is not attached or hardware accelerated cannot create a display list.
20241      * This method checks these conditions and returns the appropriate result.
20242      *
20243      * @return true if view has the ability to create a display list, false otherwise.
20244      *
20245      * @hide
20246      */
canHaveDisplayList()20247     public boolean canHaveDisplayList() {
20248         return !(mAttachInfo == null || mAttachInfo.mThreadedRenderer == null);
20249     }
20250 
20251     /**
20252      * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
20253      * @hide
20254      */
20255     @NonNull
20256     @UnsupportedAppUsage
updateDisplayListIfDirty()20257     public RenderNode updateDisplayListIfDirty() {
20258         final RenderNode renderNode = mRenderNode;
20259         if (!canHaveDisplayList()) {
20260             // can't populate RenderNode, don't try
20261             return renderNode;
20262         }
20263 
20264         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
20265                 || !renderNode.hasDisplayList()
20266                 || (mRecreateDisplayList)) {
20267             // Don't need to recreate the display list, just need to tell our
20268             // children to restore/recreate theirs
20269             if (renderNode.hasDisplayList()
20270                     && !mRecreateDisplayList) {
20271                 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
20272                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
20273                 dispatchGetDisplayList();
20274 
20275                 return renderNode; // no work needed
20276             }
20277 
20278             // If we got here, we're recreating it. Mark it as such to ensure that
20279             // we copy in child display lists into ours in drawChild()
20280             mRecreateDisplayList = true;
20281 
20282             int width = mRight - mLeft;
20283             int height = mBottom - mTop;
20284             int layerType = getLayerType();
20285 
20286             final RecordingCanvas canvas = renderNode.beginRecording(width, height);
20287 
20288             try {
20289                 if (layerType == LAYER_TYPE_SOFTWARE) {
20290                     buildDrawingCache(true);
20291                     Bitmap cache = getDrawingCache(true);
20292                     if (cache != null) {
20293                         canvas.drawBitmap(cache, 0, 0, mLayerPaint);
20294                     }
20295                 } else {
20296                     computeScroll();
20297 
20298                     canvas.translate(-mScrollX, -mScrollY);
20299                     mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
20300                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
20301 
20302                     // Fast path for layouts with no backgrounds
20303                     if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
20304                         dispatchDraw(canvas);
20305                         drawAutofilledHighlight(canvas);
20306                         if (mOverlay != null && !mOverlay.isEmpty()) {
20307                             mOverlay.getOverlayView().draw(canvas);
20308                         }
20309                         if (debugDraw()) {
20310                             debugDrawFocus(canvas);
20311                         }
20312                     } else {
20313                         draw(canvas);
20314                     }
20315                 }
20316             } finally {
20317                 renderNode.endRecording();
20318                 setDisplayListProperties(renderNode);
20319             }
20320         } else {
20321             mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
20322             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
20323         }
20324         return renderNode;
20325     }
20326 
20327     @UnsupportedAppUsage
resetDisplayList()20328     private void resetDisplayList() {
20329         mRenderNode.discardDisplayList();
20330         if (mBackgroundRenderNode != null) {
20331             mBackgroundRenderNode.discardDisplayList();
20332         }
20333     }
20334 
20335     /**
20336      * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
20337      *
20338      * @return A non-scaled bitmap representing this view or null if cache is disabled.
20339      *
20340      * @see #getDrawingCache(boolean)
20341      *
20342      * @deprecated The view drawing cache was largely made obsolete with the introduction of
20343      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
20344      * layers are largely unnecessary and can easily result in a net loss in performance due to the
20345      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
20346      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
20347      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
20348      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
20349      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
20350      * software-rendered usages are discouraged and have compatibility issues with hardware-only
20351      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
20352      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
20353      * reports or unit testing the {@link PixelCopy} API is recommended.
20354      */
20355     @Deprecated
getDrawingCache()20356     public Bitmap getDrawingCache() {
20357         return getDrawingCache(false);
20358     }
20359 
20360     /**
20361      * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
20362      * is null when caching is disabled. If caching is enabled and the cache is not ready,
20363      * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
20364      * draw from the cache when the cache is enabled. To benefit from the cache, you must
20365      * request the drawing cache by calling this method and draw it on screen if the
20366      * returned bitmap is not null.</p>
20367      *
20368      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
20369      * this method will create a bitmap of the same size as this view. Because this bitmap
20370      * will be drawn scaled by the parent ViewGroup, the result on screen might show
20371      * scaling artifacts. To avoid such artifacts, you should call this method by setting
20372      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
20373      * size than the view. This implies that your application must be able to handle this
20374      * size.</p>
20375      *
20376      * @param autoScale Indicates whether the generated bitmap should be scaled based on
20377      *        the current density of the screen when the application is in compatibility
20378      *        mode.
20379      *
20380      * @return A bitmap representing this view or null if cache is disabled.
20381      *
20382      * @see #setDrawingCacheEnabled(boolean)
20383      * @see #isDrawingCacheEnabled()
20384      * @see #buildDrawingCache(boolean)
20385      * @see #destroyDrawingCache()
20386      *
20387      * @deprecated The view drawing cache was largely made obsolete with the introduction of
20388      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
20389      * layers are largely unnecessary and can easily result in a net loss in performance due to the
20390      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
20391      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
20392      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
20393      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
20394      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
20395      * software-rendered usages are discouraged and have compatibility issues with hardware-only
20396      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
20397      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
20398      * reports or unit testing the {@link PixelCopy} API is recommended.
20399      */
20400     @Deprecated
getDrawingCache(boolean autoScale)20401     public Bitmap getDrawingCache(boolean autoScale) {
20402         if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
20403             return null;
20404         }
20405         if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
20406             buildDrawingCache(autoScale);
20407         }
20408         return autoScale ? mDrawingCache : mUnscaledDrawingCache;
20409     }
20410 
20411     /**
20412      * <p>Frees the resources used by the drawing cache. If you call
20413      * {@link #buildDrawingCache()} manually without calling
20414      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
20415      * should cleanup the cache with this method afterwards.</p>
20416      *
20417      * @see #setDrawingCacheEnabled(boolean)
20418      * @see #buildDrawingCache()
20419      * @see #getDrawingCache()
20420      *
20421      * @deprecated The view drawing cache was largely made obsolete with the introduction of
20422      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
20423      * layers are largely unnecessary and can easily result in a net loss in performance due to the
20424      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
20425      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
20426      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
20427      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
20428      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
20429      * software-rendered usages are discouraged and have compatibility issues with hardware-only
20430      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
20431      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
20432      * reports or unit testing the {@link PixelCopy} API is recommended.
20433      */
20434     @Deprecated
destroyDrawingCache()20435     public void destroyDrawingCache() {
20436         if (mDrawingCache != null) {
20437             mDrawingCache.recycle();
20438             mDrawingCache = null;
20439         }
20440         if (mUnscaledDrawingCache != null) {
20441             mUnscaledDrawingCache.recycle();
20442             mUnscaledDrawingCache = null;
20443         }
20444     }
20445 
20446     /**
20447      * Setting a solid background color for the drawing cache's bitmaps will improve
20448      * performance and memory usage. Note, though that this should only be used if this
20449      * view will always be drawn on top of a solid color.
20450      *
20451      * @param color The background color to use for the drawing cache's bitmap
20452      *
20453      * @see #setDrawingCacheEnabled(boolean)
20454      * @see #buildDrawingCache()
20455      * @see #getDrawingCache()
20456      *
20457      * @deprecated The view drawing cache was largely made obsolete with the introduction of
20458      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
20459      * layers are largely unnecessary and can easily result in a net loss in performance due to the
20460      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
20461      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
20462      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
20463      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
20464      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
20465      * software-rendered usages are discouraged and have compatibility issues with hardware-only
20466      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
20467      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
20468      * reports or unit testing the {@link PixelCopy} API is recommended.
20469      */
20470     @Deprecated
setDrawingCacheBackgroundColor(@olorInt int color)20471     public void setDrawingCacheBackgroundColor(@ColorInt int color) {
20472         if (color != mDrawingCacheBackgroundColor) {
20473             mDrawingCacheBackgroundColor = color;
20474             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
20475         }
20476     }
20477 
20478     /**
20479      * @see #setDrawingCacheBackgroundColor(int)
20480      *
20481      * @return The background color to used for the drawing cache's bitmap
20482      *
20483      * @deprecated The view drawing cache was largely made obsolete with the introduction of
20484      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
20485      * layers are largely unnecessary and can easily result in a net loss in performance due to the
20486      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
20487      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
20488      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
20489      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
20490      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
20491      * software-rendered usages are discouraged and have compatibility issues with hardware-only
20492      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
20493      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
20494      * reports or unit testing the {@link PixelCopy} API is recommended.
20495      */
20496     @Deprecated
20497     @ColorInt
getDrawingCacheBackgroundColor()20498     public int getDrawingCacheBackgroundColor() {
20499         return mDrawingCacheBackgroundColor;
20500     }
20501 
20502     /**
20503      * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
20504      *
20505      * @see #buildDrawingCache(boolean)
20506      *
20507      * @deprecated The view drawing cache was largely made obsolete with the introduction of
20508      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
20509      * layers are largely unnecessary and can easily result in a net loss in performance due to the
20510      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
20511      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
20512      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
20513      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
20514      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
20515      * software-rendered usages are discouraged and have compatibility issues with hardware-only
20516      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
20517      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
20518      * reports or unit testing the {@link PixelCopy} API is recommended.
20519      */
20520     @Deprecated
buildDrawingCache()20521     public void buildDrawingCache() {
20522         buildDrawingCache(false);
20523     }
20524 
20525     /**
20526      * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
20527      *
20528      * <p>If you call {@link #buildDrawingCache()} manually without calling
20529      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
20530      * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
20531      *
20532      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
20533      * this method will create a bitmap of the same size as this view. Because this bitmap
20534      * will be drawn scaled by the parent ViewGroup, the result on screen might show
20535      * scaling artifacts. To avoid such artifacts, you should call this method by setting
20536      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
20537      * size than the view. This implies that your application must be able to handle this
20538      * size.</p>
20539      *
20540      * <p>You should avoid calling this method when hardware acceleration is enabled. If
20541      * you do not need the drawing cache bitmap, calling this method will increase memory
20542      * usage and cause the view to be rendered in software once, thus negatively impacting
20543      * performance.</p>
20544      *
20545      * @see #getDrawingCache()
20546      * @see #destroyDrawingCache()
20547      *
20548      * @deprecated The view drawing cache was largely made obsolete with the introduction of
20549      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
20550      * layers are largely unnecessary and can easily result in a net loss in performance due to the
20551      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
20552      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
20553      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
20554      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
20555      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
20556      * software-rendered usages are discouraged and have compatibility issues with hardware-only
20557      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
20558      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
20559      * reports or unit testing the {@link PixelCopy} API is recommended.
20560      */
20561     @Deprecated
buildDrawingCache(boolean autoScale)20562     public void buildDrawingCache(boolean autoScale) {
20563         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
20564                 mDrawingCache == null : mUnscaledDrawingCache == null)) {
20565             if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
20566                 Trace.traceBegin(Trace.TRACE_TAG_VIEW,
20567                         "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
20568             }
20569             try {
20570                 buildDrawingCacheImpl(autoScale);
20571             } finally {
20572                 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
20573             }
20574         }
20575     }
20576 
20577     /**
20578      * private, internal implementation of buildDrawingCache, used to enable tracing
20579      */
buildDrawingCacheImpl(boolean autoScale)20580     private void buildDrawingCacheImpl(boolean autoScale) {
20581         mCachingFailed = false;
20582 
20583         int width = mRight - mLeft;
20584         int height = mBottom - mTop;
20585 
20586         final AttachInfo attachInfo = mAttachInfo;
20587         final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
20588 
20589         if (autoScale && scalingRequired) {
20590             width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
20591             height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
20592         }
20593 
20594         final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
20595         final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
20596         final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
20597 
20598         final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
20599         final long drawingCacheSize =
20600                 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
20601         if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
20602             if (width > 0 && height > 0) {
20603                 Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
20604                         + " too large to fit into a software layer (or drawing cache), needs "
20605                         + projectedBitmapSize + " bytes, only "
20606                         + drawingCacheSize + " available");
20607             }
20608             destroyDrawingCache();
20609             mCachingFailed = true;
20610             return;
20611         }
20612 
20613         boolean clear = true;
20614         Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
20615 
20616         if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
20617             Bitmap.Config quality;
20618             if (!opaque) {
20619                 // Never pick ARGB_4444 because it looks awful
20620                 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
20621                 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
20622                     case DRAWING_CACHE_QUALITY_AUTO:
20623                     case DRAWING_CACHE_QUALITY_LOW:
20624                     case DRAWING_CACHE_QUALITY_HIGH:
20625                     default:
20626                         quality = Bitmap.Config.ARGB_8888;
20627                         break;
20628                 }
20629             } else {
20630                 // Optimization for translucent windows
20631                 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
20632                 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
20633             }
20634 
20635             // Try to cleanup memory
20636             if (bitmap != null) bitmap.recycle();
20637 
20638             try {
20639                 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
20640                         width, height, quality);
20641                 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
20642                 if (autoScale) {
20643                     mDrawingCache = bitmap;
20644                 } else {
20645                     mUnscaledDrawingCache = bitmap;
20646                 }
20647                 if (opaque && use32BitCache) bitmap.setHasAlpha(false);
20648             } catch (OutOfMemoryError e) {
20649                 // If there is not enough memory to create the bitmap cache, just
20650                 // ignore the issue as bitmap caches are not required to draw the
20651                 // view hierarchy
20652                 if (autoScale) {
20653                     mDrawingCache = null;
20654                 } else {
20655                     mUnscaledDrawingCache = null;
20656                 }
20657                 mCachingFailed = true;
20658                 return;
20659             }
20660 
20661             clear = drawingCacheBackgroundColor != 0;
20662         }
20663 
20664         Canvas canvas;
20665         if (attachInfo != null) {
20666             canvas = attachInfo.mCanvas;
20667             if (canvas == null) {
20668                 canvas = new Canvas();
20669             }
20670             canvas.setBitmap(bitmap);
20671             // Temporarily clobber the cached Canvas in case one of our children
20672             // is also using a drawing cache. Without this, the children would
20673             // steal the canvas by attaching their own bitmap to it and bad, bad
20674             // thing would happen (invisible views, corrupted drawings, etc.)
20675             attachInfo.mCanvas = null;
20676         } else {
20677             // This case should hopefully never or seldom happen
20678             canvas = new Canvas(bitmap);
20679         }
20680 
20681         if (clear) {
20682             bitmap.eraseColor(drawingCacheBackgroundColor);
20683         }
20684 
20685         computeScroll();
20686         final int restoreCount = canvas.save();
20687 
20688         if (autoScale && scalingRequired) {
20689             final float scale = attachInfo.mApplicationScale;
20690             canvas.scale(scale, scale);
20691         }
20692 
20693         canvas.translate(-mScrollX, -mScrollY);
20694 
20695         mPrivateFlags |= PFLAG_DRAWN;
20696         if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
20697                 mLayerType != LAYER_TYPE_NONE) {
20698             mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
20699         }
20700 
20701         // Fast path for layouts with no backgrounds
20702         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
20703             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
20704             dispatchDraw(canvas);
20705             drawAutofilledHighlight(canvas);
20706             if (mOverlay != null && !mOverlay.isEmpty()) {
20707                 mOverlay.getOverlayView().draw(canvas);
20708             }
20709         } else {
20710             draw(canvas);
20711         }
20712 
20713         canvas.restoreToCount(restoreCount);
20714         canvas.setBitmap(null);
20715 
20716         if (attachInfo != null) {
20717             // Restore the cached Canvas for our siblings
20718             attachInfo.mCanvas = canvas;
20719         }
20720     }
20721 
20722     /**
20723      * Create a snapshot of the view into a bitmap.  We should probably make
20724      * some form of this public, but should think about the API.
20725      *
20726      * @hide
20727      */
20728     @UnsupportedAppUsage
createSnapshot(ViewDebug.CanvasProvider canvasProvider, boolean skipChildren)20729     public Bitmap createSnapshot(ViewDebug.CanvasProvider canvasProvider, boolean skipChildren) {
20730         int width = mRight - mLeft;
20731         int height = mBottom - mTop;
20732 
20733         final AttachInfo attachInfo = mAttachInfo;
20734         final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
20735         width = (int) ((width * scale) + 0.5f);
20736         height = (int) ((height * scale) + 0.5f);
20737 
20738         Canvas oldCanvas = null;
20739         try {
20740             Canvas canvas = canvasProvider.getCanvas(this,
20741                     width > 0 ? width : 1, height > 0 ? height : 1);
20742 
20743             if (attachInfo != null) {
20744                 oldCanvas = attachInfo.mCanvas;
20745                 // Temporarily clobber the cached Canvas in case one of our children
20746                 // is also using a drawing cache. Without this, the children would
20747                 // steal the canvas by attaching their own bitmap to it and bad, bad
20748                 // things would happen (invisible views, corrupted drawings, etc.)
20749                 attachInfo.mCanvas = null;
20750             }
20751 
20752             computeScroll();
20753             final int restoreCount = canvas.save();
20754             canvas.scale(scale, scale);
20755             canvas.translate(-mScrollX, -mScrollY);
20756 
20757             // Temporarily remove the dirty mask
20758             int flags = mPrivateFlags;
20759             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
20760 
20761             // Fast path for layouts with no backgrounds
20762             if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
20763                 dispatchDraw(canvas);
20764                 drawAutofilledHighlight(canvas);
20765                 if (mOverlay != null && !mOverlay.isEmpty()) {
20766                     mOverlay.getOverlayView().draw(canvas);
20767                 }
20768             } else {
20769                 draw(canvas);
20770             }
20771 
20772             mPrivateFlags = flags;
20773             canvas.restoreToCount(restoreCount);
20774             return canvasProvider.createBitmap();
20775         } finally {
20776             if (oldCanvas != null) {
20777                 attachInfo.mCanvas = oldCanvas;
20778             }
20779         }
20780     }
20781 
20782     /**
20783      * Indicates whether this View is currently in edit mode. A View is usually
20784      * in edit mode when displayed within a developer tool. For instance, if
20785      * this View is being drawn by a visual user interface builder, this method
20786      * should return true.
20787      *
20788      * Subclasses should check the return value of this method to provide
20789      * different behaviors if their normal behavior might interfere with the
20790      * host environment. For instance: the class spawns a thread in its
20791      * constructor, the drawing code relies on device-specific features, etc.
20792      *
20793      * This method is usually checked in the drawing code of custom widgets.
20794      *
20795      * @return True if this View is in edit mode, false otherwise.
20796      */
isInEditMode()20797     public boolean isInEditMode() {
20798         return false;
20799     }
20800 
20801     /**
20802      * If the View draws content inside its padding and enables fading edges,
20803      * it needs to support padding offsets. Padding offsets are added to the
20804      * fading edges to extend the length of the fade so that it covers pixels
20805      * drawn inside the padding.
20806      *
20807      * Subclasses of this class should override this method if they need
20808      * to draw content inside the padding.
20809      *
20810      * @return True if padding offset must be applied, false otherwise.
20811      *
20812      * @see #getLeftPaddingOffset()
20813      * @see #getRightPaddingOffset()
20814      * @see #getTopPaddingOffset()
20815      * @see #getBottomPaddingOffset()
20816      *
20817      * @since CURRENT
20818      */
isPaddingOffsetRequired()20819     protected boolean isPaddingOffsetRequired() {
20820         return false;
20821     }
20822 
20823     /**
20824      * Amount by which to extend the left fading region. Called only when
20825      * {@link #isPaddingOffsetRequired()} returns true.
20826      *
20827      * @return The left padding offset in pixels.
20828      *
20829      * @see #isPaddingOffsetRequired()
20830      *
20831      * @since CURRENT
20832      */
getLeftPaddingOffset()20833     protected int getLeftPaddingOffset() {
20834         return 0;
20835     }
20836 
20837     /**
20838      * Amount by which to extend the right fading region. Called only when
20839      * {@link #isPaddingOffsetRequired()} returns true.
20840      *
20841      * @return The right padding offset in pixels.
20842      *
20843      * @see #isPaddingOffsetRequired()
20844      *
20845      * @since CURRENT
20846      */
getRightPaddingOffset()20847     protected int getRightPaddingOffset() {
20848         return 0;
20849     }
20850 
20851     /**
20852      * Amount by which to extend the top fading region. Called only when
20853      * {@link #isPaddingOffsetRequired()} returns true.
20854      *
20855      * @return The top padding offset in pixels.
20856      *
20857      * @see #isPaddingOffsetRequired()
20858      *
20859      * @since CURRENT
20860      */
getTopPaddingOffset()20861     protected int getTopPaddingOffset() {
20862         return 0;
20863     }
20864 
20865     /**
20866      * Amount by which to extend the bottom fading region. Called only when
20867      * {@link #isPaddingOffsetRequired()} returns true.
20868      *
20869      * @return The bottom padding offset in pixels.
20870      *
20871      * @see #isPaddingOffsetRequired()
20872      *
20873      * @since CURRENT
20874      */
getBottomPaddingOffset()20875     protected int getBottomPaddingOffset() {
20876         return 0;
20877     }
20878 
20879     /**
20880      * @hide
20881      * @param offsetRequired
20882      */
getFadeTop(boolean offsetRequired)20883     protected int getFadeTop(boolean offsetRequired) {
20884         int top = mPaddingTop;
20885         if (offsetRequired) top += getTopPaddingOffset();
20886         return top;
20887     }
20888 
20889     /**
20890      * @hide
20891      * @param offsetRequired
20892      */
getFadeHeight(boolean offsetRequired)20893     protected int getFadeHeight(boolean offsetRequired) {
20894         int padding = mPaddingTop;
20895         if (offsetRequired) padding += getTopPaddingOffset();
20896         return mBottom - mTop - mPaddingBottom - padding;
20897     }
20898 
20899     /**
20900      * <p>Indicates whether this view is attached to a hardware accelerated
20901      * window or not.</p>
20902      *
20903      * <p>Even if this method returns true, it does not mean that every call
20904      * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
20905      * accelerated {@link android.graphics.Canvas}. For instance, if this view
20906      * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
20907      * window is hardware accelerated,
20908      * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
20909      * return false, and this method will return true.</p>
20910      *
20911      * @return True if the view is attached to a window and the window is
20912      *         hardware accelerated; false in any other case.
20913      */
20914     @ViewDebug.ExportedProperty(category = "drawing")
isHardwareAccelerated()20915     public boolean isHardwareAccelerated() {
20916         return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
20917     }
20918 
20919     /**
20920      * Sets a rectangular area on this view to which the view will be clipped
20921      * when it is drawn. Setting the value to null will remove the clip bounds
20922      * and the view will draw normally, using its full bounds.
20923      *
20924      * @param clipBounds The rectangular area, in the local coordinates of
20925      * this view, to which future drawing operations will be clipped.
20926      */
setClipBounds(Rect clipBounds)20927     public void setClipBounds(Rect clipBounds) {
20928         if (clipBounds == mClipBounds
20929                 || (clipBounds != null && clipBounds.equals(mClipBounds))) {
20930             return;
20931         }
20932         if (clipBounds != null) {
20933             if (mClipBounds == null) {
20934                 mClipBounds = new Rect(clipBounds);
20935             } else {
20936                 mClipBounds.set(clipBounds);
20937             }
20938         } else {
20939             mClipBounds = null;
20940         }
20941         mRenderNode.setClipRect(mClipBounds);
20942         invalidateViewProperty(false, false);
20943     }
20944 
20945     /**
20946      * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
20947      *
20948      * @return A copy of the current clip bounds if clip bounds are set,
20949      * otherwise null.
20950      */
getClipBounds()20951     public Rect getClipBounds() {
20952         return (mClipBounds != null) ? new Rect(mClipBounds) : null;
20953     }
20954 
20955 
20956     /**
20957      * Populates an output rectangle with the clip bounds of the view,
20958      * returning {@code true} if successful or {@code false} if the view's
20959      * clip bounds are {@code null}.
20960      *
20961      * @param outRect rectangle in which to place the clip bounds of the view
20962      * @return {@code true} if successful or {@code false} if the view's
20963      *         clip bounds are {@code null}
20964      */
getClipBounds(Rect outRect)20965     public boolean getClipBounds(Rect outRect) {
20966         if (mClipBounds != null) {
20967             outRect.set(mClipBounds);
20968             return true;
20969         }
20970         return false;
20971     }
20972 
20973     /**
20974      * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
20975      * case of an active Animation being run on the view.
20976      */
applyLegacyAnimation(ViewGroup parent, long drawingTime, Animation a, boolean scalingRequired)20977     private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
20978             Animation a, boolean scalingRequired) {
20979         Transformation invalidationTransform;
20980         final int flags = parent.mGroupFlags;
20981         final boolean initialized = a.isInitialized();
20982         if (!initialized) {
20983             a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
20984             a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
20985             if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
20986             onAnimationStart();
20987         }
20988 
20989         final Transformation t = parent.getChildTransformation();
20990         boolean more = a.getTransformation(drawingTime, t, 1f);
20991         if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
20992             if (parent.mInvalidationTransformation == null) {
20993                 parent.mInvalidationTransformation = new Transformation();
20994             }
20995             invalidationTransform = parent.mInvalidationTransformation;
20996             a.getTransformation(drawingTime, invalidationTransform, 1f);
20997         } else {
20998             invalidationTransform = t;
20999         }
21000 
21001         if (more) {
21002             if (!a.willChangeBounds()) {
21003                 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
21004                         ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
21005                     parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
21006                 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
21007                     // The child need to draw an animation, potentially offscreen, so
21008                     // make sure we do not cancel invalidate requests
21009                     parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
21010                     parent.invalidate(mLeft, mTop, mRight, mBottom);
21011                 }
21012             } else {
21013                 if (parent.mInvalidateRegion == null) {
21014                     parent.mInvalidateRegion = new RectF();
21015                 }
21016                 final RectF region = parent.mInvalidateRegion;
21017                 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
21018                         invalidationTransform);
21019 
21020                 // The child need to draw an animation, potentially offscreen, so
21021                 // make sure we do not cancel invalidate requests
21022                 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
21023 
21024                 final int left = mLeft + (int) region.left;
21025                 final int top = mTop + (int) region.top;
21026                 parent.invalidate(left, top, left + (int) (region.width() + .5f),
21027                         top + (int) (region.height() + .5f));
21028             }
21029         }
21030         return more;
21031     }
21032 
21033     /**
21034      * This method is called by getDisplayList() when a display list is recorded for a View.
21035      * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
21036      */
setDisplayListProperties(RenderNode renderNode)21037     void setDisplayListProperties(RenderNode renderNode) {
21038         if (renderNode != null) {
21039             renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
21040             renderNode.setClipToBounds(mParent instanceof ViewGroup
21041                     && ((ViewGroup) mParent).getClipChildren());
21042 
21043             float alpha = 1;
21044             if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
21045                     ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
21046                 ViewGroup parentVG = (ViewGroup) mParent;
21047                 final Transformation t = parentVG.getChildTransformation();
21048                 if (parentVG.getChildStaticTransformation(this, t)) {
21049                     final int transformType = t.getTransformationType();
21050                     if (transformType != Transformation.TYPE_IDENTITY) {
21051                         if ((transformType & Transformation.TYPE_ALPHA) != 0) {
21052                             alpha = t.getAlpha();
21053                         }
21054                         if ((transformType & Transformation.TYPE_MATRIX) != 0) {
21055                             renderNode.setStaticMatrix(t.getMatrix());
21056                         }
21057                     }
21058                 }
21059             }
21060             if (mTransformationInfo != null) {
21061                 alpha *= getFinalAlpha();
21062                 if (alpha < 1) {
21063                     final int multipliedAlpha = (int) (255 * alpha);
21064                     if (onSetAlpha(multipliedAlpha)) {
21065                         alpha = 1;
21066                     }
21067                 }
21068                 renderNode.setAlpha(alpha);
21069             } else if (alpha < 1) {
21070                 renderNode.setAlpha(alpha);
21071             }
21072         }
21073     }
21074 
21075     /**
21076      * This method is called by ViewGroup.drawChild() to have each child view draw itself.
21077      *
21078      * This is where the View specializes rendering behavior based on layer type,
21079      * and hardware acceleration.
21080      */
draw(Canvas canvas, ViewGroup parent, long drawingTime)21081     boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
21082         final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
21083         /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
21084          *
21085          * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
21086          * HW accelerated, it can't handle drawing RenderNodes.
21087          */
21088         boolean drawingWithRenderNode = mAttachInfo != null
21089                 && mAttachInfo.mHardwareAccelerated
21090                 && hardwareAcceleratedCanvas;
21091 
21092         boolean more = false;
21093         final boolean childHasIdentityMatrix = hasIdentityMatrix();
21094         final int parentFlags = parent.mGroupFlags;
21095 
21096         if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
21097             parent.getChildTransformation().clear();
21098             parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
21099         }
21100 
21101         Transformation transformToApply = null;
21102         boolean concatMatrix = false;
21103         final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
21104         final Animation a = getAnimation();
21105         if (a != null) {
21106             more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
21107             concatMatrix = a.willChangeTransformationMatrix();
21108             if (concatMatrix) {
21109                 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
21110             }
21111             transformToApply = parent.getChildTransformation();
21112         } else {
21113             if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
21114                 // No longer animating: clear out old animation matrix
21115                 mRenderNode.setAnimationMatrix(null);
21116                 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
21117             }
21118             if (!drawingWithRenderNode
21119                     && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
21120                 final Transformation t = parent.getChildTransformation();
21121                 final boolean hasTransform = parent.getChildStaticTransformation(this, t);
21122                 if (hasTransform) {
21123                     final int transformType = t.getTransformationType();
21124                     transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
21125                     concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
21126                 }
21127             }
21128         }
21129 
21130         concatMatrix |= !childHasIdentityMatrix;
21131 
21132         // Sets the flag as early as possible to allow draw() implementations
21133         // to call invalidate() successfully when doing animations
21134         mPrivateFlags |= PFLAG_DRAWN;
21135 
21136         if (!concatMatrix &&
21137                 (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
21138                         ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
21139                 canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
21140                 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
21141             mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
21142             return more;
21143         }
21144         mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
21145 
21146         if (hardwareAcceleratedCanvas) {
21147             // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
21148             // retain the flag's value temporarily in the mRecreateDisplayList flag
21149             mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
21150             mPrivateFlags &= ~PFLAG_INVALIDATED;
21151         }
21152 
21153         RenderNode renderNode = null;
21154         Bitmap cache = null;
21155         int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
21156         if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
21157              if (layerType != LAYER_TYPE_NONE) {
21158                  // If not drawing with RenderNode, treat HW layers as SW
21159                  layerType = LAYER_TYPE_SOFTWARE;
21160                  buildDrawingCache(true);
21161             }
21162             cache = getDrawingCache(true);
21163         }
21164 
21165         if (drawingWithRenderNode) {
21166             // Delay getting the display list until animation-driven alpha values are
21167             // set up and possibly passed on to the view
21168             renderNode = updateDisplayListIfDirty();
21169             if (!renderNode.hasDisplayList()) {
21170                 // Uncommon, but possible. If a view is removed from the hierarchy during the call
21171                 // to getDisplayList(), the display list will be marked invalid and we should not
21172                 // try to use it again.
21173                 renderNode = null;
21174                 drawingWithRenderNode = false;
21175             }
21176         }
21177 
21178         int sx = 0;
21179         int sy = 0;
21180         if (!drawingWithRenderNode) {
21181             computeScroll();
21182             sx = mScrollX;
21183             sy = mScrollY;
21184         }
21185 
21186         final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
21187         final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
21188 
21189         int restoreTo = -1;
21190         if (!drawingWithRenderNode || transformToApply != null) {
21191             restoreTo = canvas.save();
21192         }
21193         if (offsetForScroll) {
21194             canvas.translate(mLeft - sx, mTop - sy);
21195         } else {
21196             if (!drawingWithRenderNode) {
21197                 canvas.translate(mLeft, mTop);
21198             }
21199             if (scalingRequired) {
21200                 if (drawingWithRenderNode) {
21201                     // TODO: Might not need this if we put everything inside the DL
21202                     restoreTo = canvas.save();
21203                 }
21204                 // mAttachInfo cannot be null, otherwise scalingRequired == false
21205                 final float scale = 1.0f / mAttachInfo.mApplicationScale;
21206                 canvas.scale(scale, scale);
21207             }
21208         }
21209 
21210         float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
21211         if (transformToApply != null
21212                 || alpha < 1
21213                 || !hasIdentityMatrix()
21214                 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
21215             if (transformToApply != null || !childHasIdentityMatrix) {
21216                 int transX = 0;
21217                 int transY = 0;
21218 
21219                 if (offsetForScroll) {
21220                     transX = -sx;
21221                     transY = -sy;
21222                 }
21223 
21224                 if (transformToApply != null) {
21225                     if (concatMatrix) {
21226                         if (drawingWithRenderNode) {
21227                             renderNode.setAnimationMatrix(transformToApply.getMatrix());
21228                         } else {
21229                             // Undo the scroll translation, apply the transformation matrix,
21230                             // then redo the scroll translate to get the correct result.
21231                             canvas.translate(-transX, -transY);
21232                             canvas.concat(transformToApply.getMatrix());
21233                             canvas.translate(transX, transY);
21234                         }
21235                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
21236                     }
21237 
21238                     float transformAlpha = transformToApply.getAlpha();
21239                     if (transformAlpha < 1) {
21240                         alpha *= transformAlpha;
21241                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
21242                     }
21243                 }
21244 
21245                 if (!childHasIdentityMatrix && !drawingWithRenderNode) {
21246                     canvas.translate(-transX, -transY);
21247                     canvas.concat(getMatrix());
21248                     canvas.translate(transX, transY);
21249                 }
21250             }
21251 
21252             // Deal with alpha if it is or used to be <1
21253             if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
21254                 if (alpha < 1) {
21255                     mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
21256                 } else {
21257                     mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
21258                 }
21259                 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
21260                 if (!drawingWithDrawingCache) {
21261                     final int multipliedAlpha = (int) (255 * alpha);
21262                     if (!onSetAlpha(multipliedAlpha)) {
21263                         if (drawingWithRenderNode) {
21264                             renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
21265                         } else if (layerType == LAYER_TYPE_NONE) {
21266                             canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
21267                                     multipliedAlpha);
21268                         }
21269                     } else {
21270                         // Alpha is handled by the child directly, clobber the layer's alpha
21271                         mPrivateFlags |= PFLAG_ALPHA_SET;
21272                     }
21273                 }
21274             }
21275         } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
21276             onSetAlpha(255);
21277             mPrivateFlags &= ~PFLAG_ALPHA_SET;
21278         }
21279 
21280         if (!drawingWithRenderNode) {
21281             // apply clips directly, since RenderNode won't do it for this draw
21282             if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
21283                 if (offsetForScroll) {
21284                     canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
21285                 } else {
21286                     if (!scalingRequired || cache == null) {
21287                         canvas.clipRect(0, 0, getWidth(), getHeight());
21288                     } else {
21289                         canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
21290                     }
21291                 }
21292             }
21293 
21294             if (mClipBounds != null) {
21295                 // clip bounds ignore scroll
21296                 canvas.clipRect(mClipBounds);
21297             }
21298         }
21299 
21300         if (!drawingWithDrawingCache) {
21301             if (drawingWithRenderNode) {
21302                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
21303                 ((RecordingCanvas) canvas).drawRenderNode(renderNode);
21304             } else {
21305                 // Fast path for layouts with no backgrounds
21306                 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
21307                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
21308                     dispatchDraw(canvas);
21309                 } else {
21310                     draw(canvas);
21311                 }
21312             }
21313         } else if (cache != null) {
21314             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
21315             if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
21316                 // no layer paint, use temporary paint to draw bitmap
21317                 Paint cachePaint = parent.mCachePaint;
21318                 if (cachePaint == null) {
21319                     cachePaint = new Paint();
21320                     cachePaint.setDither(false);
21321                     parent.mCachePaint = cachePaint;
21322                 }
21323                 cachePaint.setAlpha((int) (alpha * 255));
21324                 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
21325             } else {
21326                 // use layer paint to draw the bitmap, merging the two alphas, but also restore
21327                 int layerPaintAlpha = mLayerPaint.getAlpha();
21328                 if (alpha < 1) {
21329                     mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
21330                 }
21331                 canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
21332                 if (alpha < 1) {
21333                     mLayerPaint.setAlpha(layerPaintAlpha);
21334                 }
21335             }
21336         }
21337 
21338         if (restoreTo >= 0) {
21339             canvas.restoreToCount(restoreTo);
21340         }
21341 
21342         if (a != null && !more) {
21343             if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
21344                 onSetAlpha(255);
21345             }
21346             parent.finishAnimatingView(this, a);
21347         }
21348 
21349         if (more && hardwareAcceleratedCanvas) {
21350             if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
21351                 // alpha animations should cause the child to recreate its display list
21352                 invalidate(true);
21353             }
21354         }
21355 
21356         mRecreateDisplayList = false;
21357 
21358         return more;
21359     }
21360 
getDebugPaint()21361     static Paint getDebugPaint() {
21362         if (sDebugPaint == null) {
21363             sDebugPaint = new Paint();
21364             sDebugPaint.setAntiAlias(false);
21365         }
21366         return sDebugPaint;
21367     }
21368 
dipsToPixels(int dips)21369     final int dipsToPixels(int dips) {
21370         float scale = getContext().getResources().getDisplayMetrics().density;
21371         return (int) (dips * scale + 0.5f);
21372     }
21373 
debugDrawFocus(Canvas canvas)21374     final private void debugDrawFocus(Canvas canvas) {
21375         if (isFocused()) {
21376             final int cornerSquareSize = dipsToPixels(DEBUG_CORNERS_SIZE_DIP);
21377             final int l = mScrollX;
21378             final int r = l + mRight - mLeft;
21379             final int t = mScrollY;
21380             final int b = t + mBottom - mTop;
21381 
21382             final Paint paint = getDebugPaint();
21383             paint.setColor(DEBUG_CORNERS_COLOR);
21384 
21385             // Draw squares in corners.
21386             paint.setStyle(Paint.Style.FILL);
21387             canvas.drawRect(l, t, l + cornerSquareSize, t + cornerSquareSize, paint);
21388             canvas.drawRect(r - cornerSquareSize, t, r, t + cornerSquareSize, paint);
21389             canvas.drawRect(l, b - cornerSquareSize, l + cornerSquareSize, b, paint);
21390             canvas.drawRect(r - cornerSquareSize, b - cornerSquareSize, r, b, paint);
21391 
21392             // Draw big X across the view.
21393             paint.setStyle(Paint.Style.STROKE);
21394             canvas.drawLine(l, t, r, b, paint);
21395             canvas.drawLine(l, b, r, t, paint);
21396         }
21397     }
21398 
21399     /**
21400      * Manually render this view (and all of its children) to the given Canvas.
21401      * The view must have already done a full layout before this function is
21402      * called.  When implementing a view, implement
21403      * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
21404      * If you do need to override this method, call the superclass version.
21405      *
21406      * @param canvas The Canvas to which the View is rendered.
21407      */
21408     @CallSuper
draw(Canvas canvas)21409     public void draw(Canvas canvas) {
21410         final int privateFlags = mPrivateFlags;
21411         mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
21412 
21413         /*
21414          * Draw traversal performs several drawing steps which must be executed
21415          * in the appropriate order:
21416          *
21417          *      1. Draw the background
21418          *      2. If necessary, save the canvas' layers to prepare for fading
21419          *      3. Draw view's content
21420          *      4. Draw children
21421          *      5. If necessary, draw the fading edges and restore layers
21422          *      6. Draw decorations (scrollbars for instance)
21423          */
21424 
21425         // Step 1, draw the background, if needed
21426         int saveCount;
21427 
21428         drawBackground(canvas);
21429 
21430         // skip step 2 & 5 if possible (common case)
21431         final int viewFlags = mViewFlags;
21432         boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
21433         boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
21434         if (!verticalEdges && !horizontalEdges) {
21435             // Step 3, draw the content
21436             onDraw(canvas);
21437 
21438             // Step 4, draw the children
21439             dispatchDraw(canvas);
21440 
21441             drawAutofilledHighlight(canvas);
21442 
21443             // Overlay is part of the content and draws beneath Foreground
21444             if (mOverlay != null && !mOverlay.isEmpty()) {
21445                 mOverlay.getOverlayView().dispatchDraw(canvas);
21446             }
21447 
21448             // Step 6, draw decorations (foreground, scrollbars)
21449             onDrawForeground(canvas);
21450 
21451             // Step 7, draw the default focus highlight
21452             drawDefaultFocusHighlight(canvas);
21453 
21454             if (debugDraw()) {
21455                 debugDrawFocus(canvas);
21456             }
21457 
21458             // we're done...
21459             return;
21460         }
21461 
21462         /*
21463          * Here we do the full fledged routine...
21464          * (this is an uncommon case where speed matters less,
21465          * this is why we repeat some of the tests that have been
21466          * done above)
21467          */
21468 
21469         boolean drawTop = false;
21470         boolean drawBottom = false;
21471         boolean drawLeft = false;
21472         boolean drawRight = false;
21473 
21474         float topFadeStrength = 0.0f;
21475         float bottomFadeStrength = 0.0f;
21476         float leftFadeStrength = 0.0f;
21477         float rightFadeStrength = 0.0f;
21478 
21479         // Step 2, save the canvas' layers
21480         int paddingLeft = mPaddingLeft;
21481 
21482         final boolean offsetRequired = isPaddingOffsetRequired();
21483         if (offsetRequired) {
21484             paddingLeft += getLeftPaddingOffset();
21485         }
21486 
21487         int left = mScrollX + paddingLeft;
21488         int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
21489         int top = mScrollY + getFadeTop(offsetRequired);
21490         int bottom = top + getFadeHeight(offsetRequired);
21491 
21492         if (offsetRequired) {
21493             right += getRightPaddingOffset();
21494             bottom += getBottomPaddingOffset();
21495         }
21496 
21497         final ScrollabilityCache scrollabilityCache = mScrollCache;
21498         final float fadeHeight = scrollabilityCache.fadingEdgeLength;
21499         int length = (int) fadeHeight;
21500 
21501         // clip the fade length if top and bottom fades overlap
21502         // overlapping fades produce odd-looking artifacts
21503         if (verticalEdges && (top + length > bottom - length)) {
21504             length = (bottom - top) / 2;
21505         }
21506 
21507         // also clip horizontal fades if necessary
21508         if (horizontalEdges && (left + length > right - length)) {
21509             length = (right - left) / 2;
21510         }
21511 
21512         if (verticalEdges) {
21513             topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
21514             drawTop = topFadeStrength * fadeHeight > 1.0f;
21515             bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
21516             drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
21517         }
21518 
21519         if (horizontalEdges) {
21520             leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
21521             drawLeft = leftFadeStrength * fadeHeight > 1.0f;
21522             rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
21523             drawRight = rightFadeStrength * fadeHeight > 1.0f;
21524         }
21525 
21526         saveCount = canvas.getSaveCount();
21527         int topSaveCount = -1;
21528         int bottomSaveCount = -1;
21529         int leftSaveCount = -1;
21530         int rightSaveCount = -1;
21531 
21532         int solidColor = getSolidColor();
21533         if (solidColor == 0) {
21534             if (drawTop) {
21535                 topSaveCount = canvas.saveUnclippedLayer(left, top, right, top + length);
21536             }
21537 
21538             if (drawBottom) {
21539                 bottomSaveCount = canvas.saveUnclippedLayer(left, bottom - length, right, bottom);
21540             }
21541 
21542             if (drawLeft) {
21543                 leftSaveCount = canvas.saveUnclippedLayer(left, top, left + length, bottom);
21544             }
21545 
21546             if (drawRight) {
21547                 rightSaveCount = canvas.saveUnclippedLayer(right - length, top, right, bottom);
21548             }
21549         } else {
21550             scrollabilityCache.setFadeColor(solidColor);
21551         }
21552 
21553         // Step 3, draw the content
21554         onDraw(canvas);
21555 
21556         // Step 4, draw the children
21557         dispatchDraw(canvas);
21558 
21559         // Step 5, draw the fade effect and restore layers
21560         final Paint p = scrollabilityCache.paint;
21561         final Matrix matrix = scrollabilityCache.matrix;
21562         final Shader fade = scrollabilityCache.shader;
21563 
21564         // must be restored in the reverse order that they were saved
21565         if (drawRight) {
21566             matrix.setScale(1, fadeHeight * rightFadeStrength);
21567             matrix.postRotate(90);
21568             matrix.postTranslate(right, top);
21569             fade.setLocalMatrix(matrix);
21570             p.setShader(fade);
21571             if (solidColor == 0) {
21572                 canvas.restoreUnclippedLayer(rightSaveCount, p);
21573 
21574             } else {
21575                 canvas.drawRect(right - length, top, right, bottom, p);
21576             }
21577         }
21578 
21579         if (drawLeft) {
21580             matrix.setScale(1, fadeHeight * leftFadeStrength);
21581             matrix.postRotate(-90);
21582             matrix.postTranslate(left, top);
21583             fade.setLocalMatrix(matrix);
21584             p.setShader(fade);
21585             if (solidColor == 0) {
21586                 canvas.restoreUnclippedLayer(leftSaveCount, p);
21587             } else {
21588                 canvas.drawRect(left, top, left + length, bottom, p);
21589             }
21590         }
21591 
21592         if (drawBottom) {
21593             matrix.setScale(1, fadeHeight * bottomFadeStrength);
21594             matrix.postRotate(180);
21595             matrix.postTranslate(left, bottom);
21596             fade.setLocalMatrix(matrix);
21597             p.setShader(fade);
21598             if (solidColor == 0) {
21599                 canvas.restoreUnclippedLayer(bottomSaveCount, p);
21600             } else {
21601                 canvas.drawRect(left, bottom - length, right, bottom, p);
21602             }
21603         }
21604 
21605         if (drawTop) {
21606             matrix.setScale(1, fadeHeight * topFadeStrength);
21607             matrix.postTranslate(left, top);
21608             fade.setLocalMatrix(matrix);
21609             p.setShader(fade);
21610             if (solidColor == 0) {
21611                 canvas.restoreUnclippedLayer(topSaveCount, p);
21612             } else {
21613                 canvas.drawRect(left, top, right, top + length, p);
21614             }
21615         }
21616 
21617         canvas.restoreToCount(saveCount);
21618 
21619         drawAutofilledHighlight(canvas);
21620 
21621         // Overlay is part of the content and draws beneath Foreground
21622         if (mOverlay != null && !mOverlay.isEmpty()) {
21623             mOverlay.getOverlayView().dispatchDraw(canvas);
21624         }
21625 
21626         // Step 6, draw decorations (foreground, scrollbars)
21627         onDrawForeground(canvas);
21628 
21629         if (debugDraw()) {
21630             debugDrawFocus(canvas);
21631         }
21632     }
21633 
21634     /**
21635      * Draws the background onto the specified canvas.
21636      *
21637      * @param canvas Canvas on which to draw the background
21638      */
21639     @UnsupportedAppUsage
drawBackground(Canvas canvas)21640     private void drawBackground(Canvas canvas) {
21641         final Drawable background = mBackground;
21642         if (background == null) {
21643             return;
21644         }
21645 
21646         setBackgroundBounds();
21647 
21648         // Attempt to use a display list if requested.
21649         if (canvas.isHardwareAccelerated() && mAttachInfo != null
21650                 && mAttachInfo.mThreadedRenderer != null) {
21651             mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
21652 
21653             final RenderNode renderNode = mBackgroundRenderNode;
21654             if (renderNode != null && renderNode.hasDisplayList()) {
21655                 setBackgroundRenderNodeProperties(renderNode);
21656                 ((RecordingCanvas) canvas).drawRenderNode(renderNode);
21657                 return;
21658             }
21659         }
21660 
21661         final int scrollX = mScrollX;
21662         final int scrollY = mScrollY;
21663         if ((scrollX | scrollY) == 0) {
21664             background.draw(canvas);
21665         } else {
21666             canvas.translate(scrollX, scrollY);
21667             background.draw(canvas);
21668             canvas.translate(-scrollX, -scrollY);
21669         }
21670     }
21671 
21672     /**
21673      * Sets the correct background bounds and rebuilds the outline, if needed.
21674      * <p/>
21675      * This is called by LayoutLib.
21676      */
setBackgroundBounds()21677     void setBackgroundBounds() {
21678         if (mBackgroundSizeChanged && mBackground != null) {
21679             mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
21680             mBackgroundSizeChanged = false;
21681             rebuildOutline();
21682         }
21683     }
21684 
setBackgroundRenderNodeProperties(RenderNode renderNode)21685     private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
21686         renderNode.setTranslationX(mScrollX);
21687         renderNode.setTranslationY(mScrollY);
21688     }
21689 
21690     /**
21691      * Creates a new display list or updates the existing display list for the
21692      * specified Drawable.
21693      *
21694      * @param drawable Drawable for which to create a display list
21695      * @param renderNode Existing RenderNode, or {@code null}
21696      * @return A valid display list for the specified drawable
21697      */
getDrawableRenderNode(Drawable drawable, RenderNode renderNode)21698     private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
21699         if (renderNode == null) {
21700             renderNode = RenderNode.create(drawable.getClass().getName(),
21701                     new ViewAnimationHostBridge(this));
21702             renderNode.setUsageHint(RenderNode.USAGE_BACKGROUND);
21703         }
21704 
21705         final Rect bounds = drawable.getBounds();
21706         final int width = bounds.width();
21707         final int height = bounds.height();
21708         final RecordingCanvas canvas = renderNode.beginRecording(width, height);
21709 
21710         // Reverse left/top translation done by drawable canvas, which will
21711         // instead be applied by rendernode's LTRB bounds below. This way, the
21712         // drawable's bounds match with its rendernode bounds and its content
21713         // will lie within those bounds in the rendernode tree.
21714         canvas.translate(-bounds.left, -bounds.top);
21715 
21716         try {
21717             drawable.draw(canvas);
21718         } finally {
21719             renderNode.endRecording();
21720         }
21721 
21722         // Set up drawable properties that are view-independent.
21723         renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
21724         renderNode.setProjectBackwards(drawable.isProjected());
21725         renderNode.setProjectionReceiver(true);
21726         renderNode.setClipToBounds(false);
21727         return renderNode;
21728     }
21729 
21730     /**
21731      * Returns the overlay for this view, creating it if it does not yet exist.
21732      * Adding drawables to the overlay will cause them to be displayed whenever
21733      * the view itself is redrawn. Objects in the overlay should be actively
21734      * managed: remove them when they should not be displayed anymore. The
21735      * overlay will always have the same size as its host view.
21736      *
21737      * <p>Note: Overlays do not currently work correctly with {@link
21738      * SurfaceView} or {@link TextureView}; contents in overlays for these
21739      * types of views may not display correctly.</p>
21740      *
21741      * @return The ViewOverlay object for this view.
21742      * @see ViewOverlay
21743      */
getOverlay()21744     public ViewOverlay getOverlay() {
21745         if (mOverlay == null) {
21746             mOverlay = new ViewOverlay(mContext, this);
21747         }
21748         return mOverlay;
21749     }
21750 
21751     /**
21752      * Override this if your view is known to always be drawn on top of a solid color background,
21753      * and needs to draw fading edges. Returning a non-zero color enables the view system to
21754      * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
21755      * should be set to 0xFF.
21756      *
21757      * @see #setVerticalFadingEdgeEnabled(boolean)
21758      * @see #setHorizontalFadingEdgeEnabled(boolean)
21759      *
21760      * @return The known solid color background for this view, or 0 if the color may vary
21761      */
21762     @ViewDebug.ExportedProperty(category = "drawing")
21763     @InspectableProperty
21764     @ColorInt
getSolidColor()21765     public int getSolidColor() {
21766         return 0;
21767     }
21768 
21769     /**
21770      * Build a human readable string representation of the specified view flags.
21771      *
21772      * @param flags the view flags to convert to a string
21773      * @return a String representing the supplied flags
21774      */
printFlags(int flags)21775     private static String printFlags(int flags) {
21776         String output = "";
21777         int numFlags = 0;
21778         if ((flags & FOCUSABLE) == FOCUSABLE) {
21779             output += "TAKES_FOCUS";
21780             numFlags++;
21781         }
21782 
21783         switch (flags & VISIBILITY_MASK) {
21784         case INVISIBLE:
21785             if (numFlags > 0) {
21786                 output += " ";
21787             }
21788             output += "INVISIBLE";
21789             // USELESS HERE numFlags++;
21790             break;
21791         case GONE:
21792             if (numFlags > 0) {
21793                 output += " ";
21794             }
21795             output += "GONE";
21796             // USELESS HERE numFlags++;
21797             break;
21798         default:
21799             break;
21800         }
21801         return output;
21802     }
21803 
21804     /**
21805      * Build a human readable string representation of the specified private
21806      * view flags.
21807      *
21808      * @param privateFlags the private view flags to convert to a string
21809      * @return a String representing the supplied flags
21810      */
printPrivateFlags(int privateFlags)21811     private static String printPrivateFlags(int privateFlags) {
21812         String output = "";
21813         int numFlags = 0;
21814 
21815         if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
21816             output += "WANTS_FOCUS";
21817             numFlags++;
21818         }
21819 
21820         if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
21821             if (numFlags > 0) {
21822                 output += " ";
21823             }
21824             output += "FOCUSED";
21825             numFlags++;
21826         }
21827 
21828         if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
21829             if (numFlags > 0) {
21830                 output += " ";
21831             }
21832             output += "SELECTED";
21833             numFlags++;
21834         }
21835 
21836         if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
21837             if (numFlags > 0) {
21838                 output += " ";
21839             }
21840             output += "IS_ROOT_NAMESPACE";
21841             numFlags++;
21842         }
21843 
21844         if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
21845             if (numFlags > 0) {
21846                 output += " ";
21847             }
21848             output += "HAS_BOUNDS";
21849             numFlags++;
21850         }
21851 
21852         if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
21853             if (numFlags > 0) {
21854                 output += " ";
21855             }
21856             output += "DRAWN";
21857             // USELESS HERE numFlags++;
21858         }
21859         return output;
21860     }
21861 
21862     /**
21863      * <p>Indicates whether or not this view's layout will be requested during
21864      * the next hierarchy layout pass.</p>
21865      *
21866      * @return true if the layout will be forced during next layout pass
21867      */
isLayoutRequested()21868     public boolean isLayoutRequested() {
21869         return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
21870     }
21871 
21872     /**
21873      * Return true if o is a ViewGroup that is laying out using optical bounds.
21874      * @hide
21875      */
isLayoutModeOptical(Object o)21876     public static boolean isLayoutModeOptical(Object o) {
21877         return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
21878     }
21879 
setOpticalFrame(int left, int top, int right, int bottom)21880     private boolean setOpticalFrame(int left, int top, int right, int bottom) {
21881         Insets parentInsets = mParent instanceof View ?
21882                 ((View) mParent).getOpticalInsets() : Insets.NONE;
21883         Insets childInsets = getOpticalInsets();
21884         return setFrame(
21885                 left   + parentInsets.left - childInsets.left,
21886                 top    + parentInsets.top  - childInsets.top,
21887                 right  + parentInsets.left + childInsets.right,
21888                 bottom + parentInsets.top  + childInsets.bottom);
21889     }
21890 
21891     /**
21892      * Assign a size and position to a view and all of its
21893      * descendants
21894      *
21895      * <p>This is the second phase of the layout mechanism.
21896      * (The first is measuring). In this phase, each parent calls
21897      * layout on all of its children to position them.
21898      * This is typically done using the child measurements
21899      * that were stored in the measure pass().</p>
21900      *
21901      * <p>Derived classes should not override this method.
21902      * Derived classes with children should override
21903      * onLayout. In that method, they should
21904      * call layout on each of their children.</p>
21905      *
21906      * @param l Left position, relative to parent
21907      * @param t Top position, relative to parent
21908      * @param r Right position, relative to parent
21909      * @param b Bottom position, relative to parent
21910      */
21911     @SuppressWarnings({"unchecked"})
layout(int l, int t, int r, int b)21912     public void layout(int l, int t, int r, int b) {
21913         if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
21914             onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
21915             mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
21916         }
21917 
21918         int oldL = mLeft;
21919         int oldT = mTop;
21920         int oldB = mBottom;
21921         int oldR = mRight;
21922 
21923         boolean changed = isLayoutModeOptical(mParent) ?
21924                 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
21925 
21926         if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
21927             onLayout(changed, l, t, r, b);
21928 
21929             if (shouldDrawRoundScrollbar()) {
21930                 if(mRoundScrollbarRenderer == null) {
21931                     mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
21932                 }
21933             } else {
21934                 mRoundScrollbarRenderer = null;
21935             }
21936 
21937             mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
21938 
21939             ListenerInfo li = mListenerInfo;
21940             if (li != null && li.mOnLayoutChangeListeners != null) {
21941                 ArrayList<OnLayoutChangeListener> listenersCopy =
21942                         (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
21943                 int numListeners = listenersCopy.size();
21944                 for (int i = 0; i < numListeners; ++i) {
21945                     listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
21946                 }
21947             }
21948         }
21949 
21950         final boolean wasLayoutValid = isLayoutValid();
21951 
21952         mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
21953         mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
21954 
21955         if (!wasLayoutValid && isFocused()) {
21956             mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
21957             if (canTakeFocus()) {
21958                 // We have a robust focus, so parents should no longer be wanting focus.
21959                 clearParentsWantFocus();
21960             } else if (getViewRootImpl() == null || !getViewRootImpl().isInLayout()) {
21961                 // This is a weird case. Most-likely the user, rather than ViewRootImpl, called
21962                 // layout. In this case, there's no guarantee that parent layouts will be evaluated
21963                 // and thus the safest action is to clear focus here.
21964                 clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
21965                 clearParentsWantFocus();
21966             } else if (!hasParentWantsFocus()) {
21967                 // original requestFocus was likely on this view directly, so just clear focus
21968                 clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
21969             }
21970             // otherwise, we let parents handle re-assigning focus during their layout passes.
21971         } else if ((mPrivateFlags & PFLAG_WANTS_FOCUS) != 0) {
21972             mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
21973             View focused = findFocus();
21974             if (focused != null) {
21975                 // Try to restore focus as close as possible to our starting focus.
21976                 if (!restoreDefaultFocus() && !hasParentWantsFocus()) {
21977                     // Give up and clear focus once we've reached the top-most parent which wants
21978                     // focus.
21979                     focused.clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
21980                 }
21981             }
21982         }
21983 
21984         if ((mPrivateFlags3 & PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT) != 0) {
21985             mPrivateFlags3 &= ~PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
21986             notifyEnterOrExitForAutoFillIfNeeded(true);
21987         }
21988     }
21989 
hasParentWantsFocus()21990     private boolean hasParentWantsFocus() {
21991         ViewParent parent = mParent;
21992         while (parent instanceof ViewGroup) {
21993             ViewGroup pv = (ViewGroup) parent;
21994             if ((pv.mPrivateFlags & PFLAG_WANTS_FOCUS) != 0) {
21995                 return true;
21996             }
21997             parent = pv.mParent;
21998         }
21999         return false;
22000     }
22001 
22002     /**
22003      * Called from layout when this view should
22004      * assign a size and position to each of its children.
22005      *
22006      * Derived classes with children should override
22007      * this method and call layout on each of
22008      * their children.
22009      * @param changed This is a new size or position for this view
22010      * @param left Left position, relative to parent
22011      * @param top Top position, relative to parent
22012      * @param right Right position, relative to parent
22013      * @param bottom Bottom position, relative to parent
22014      */
onLayout(boolean changed, int left, int top, int right, int bottom)22015     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
22016     }
22017 
22018     /**
22019      * Assign a size and position to this view.
22020      *
22021      * This is called from layout.
22022      *
22023      * @param left Left position, relative to parent
22024      * @param top Top position, relative to parent
22025      * @param right Right position, relative to parent
22026      * @param bottom Bottom position, relative to parent
22027      * @return true if the new size and position are different than the
22028      *         previous ones
22029      * {@hide}
22030      */
22031     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
setFrame(int left, int top, int right, int bottom)22032     protected boolean setFrame(int left, int top, int right, int bottom) {
22033         boolean changed = false;
22034 
22035         if (DBG) {
22036             Log.d(VIEW_LOG_TAG, this + " View.setFrame(" + left + "," + top + ","
22037                     + right + "," + bottom + ")");
22038         }
22039 
22040         if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
22041             changed = true;
22042 
22043             // Remember our drawn bit
22044             int drawn = mPrivateFlags & PFLAG_DRAWN;
22045 
22046             int oldWidth = mRight - mLeft;
22047             int oldHeight = mBottom - mTop;
22048             int newWidth = right - left;
22049             int newHeight = bottom - top;
22050             boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
22051 
22052             // Invalidate our old position
22053             invalidate(sizeChanged);
22054 
22055             mLeft = left;
22056             mTop = top;
22057             mRight = right;
22058             mBottom = bottom;
22059             mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
22060 
22061             mPrivateFlags |= PFLAG_HAS_BOUNDS;
22062 
22063 
22064             if (sizeChanged) {
22065                 sizeChange(newWidth, newHeight, oldWidth, oldHeight);
22066             }
22067 
22068             if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
22069                 // If we are visible, force the DRAWN bit to on so that
22070                 // this invalidate will go through (at least to our parent).
22071                 // This is because someone may have invalidated this view
22072                 // before this call to setFrame came in, thereby clearing
22073                 // the DRAWN bit.
22074                 mPrivateFlags |= PFLAG_DRAWN;
22075                 invalidate(sizeChanged);
22076                 // parent display list may need to be recreated based on a change in the bounds
22077                 // of any child
22078                 invalidateParentCaches();
22079             }
22080 
22081             // Reset drawn bit to original value (invalidate turns it off)
22082             mPrivateFlags |= drawn;
22083 
22084             mBackgroundSizeChanged = true;
22085             mDefaultFocusHighlightSizeChanged = true;
22086             if (mForegroundInfo != null) {
22087                 mForegroundInfo.mBoundsChanged = true;
22088             }
22089 
22090             notifySubtreeAccessibilityStateChangedIfNeeded();
22091         }
22092         return changed;
22093     }
22094 
22095     /**
22096      * Assign a size and position to this view.
22097      *
22098      * This method is meant to be used in animations only as it applies this position and size
22099      * for the view only temporary and it can be changed back at any time by the layout.
22100      *
22101      * @param left Left position, relative to parent
22102      * @param top Top position, relative to parent
22103      * @param right Right position, relative to parent
22104      * @param bottom Bottom position, relative to parent
22105      *
22106      * @see #setLeft(int), #setRight(int), #setTop(int), #setBottom(int)
22107      */
setLeftTopRightBottom(int left, int top, int right, int bottom)22108     public final void setLeftTopRightBottom(int left, int top, int right, int bottom) {
22109         setFrame(left, top, right, bottom);
22110     }
22111 
sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight)22112     private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
22113         onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
22114         if (mOverlay != null) {
22115             mOverlay.getOverlayView().setRight(newWidth);
22116             mOverlay.getOverlayView().setBottom(newHeight);
22117         }
22118         // If this isn't laid out yet, focus assignment will be handled during the "deferment/
22119         // backtracking" of requestFocus during layout, so don't touch focus here.
22120         if (!sCanFocusZeroSized && isLayoutValid()
22121                 // Don't touch focus if animating
22122                 && !(mParent instanceof ViewGroup && ((ViewGroup) mParent).isLayoutSuppressed())) {
22123             if (newWidth <= 0 || newHeight <= 0) {
22124                 if (hasFocus()) {
22125                     clearFocus();
22126                     if (mParent instanceof ViewGroup) {
22127                         ((ViewGroup) mParent).clearFocusedInCluster();
22128                     }
22129                 }
22130                 clearAccessibilityFocus();
22131             } else if (oldWidth <= 0 || oldHeight <= 0) {
22132                 if (mParent != null && canTakeFocus()) {
22133                     mParent.focusableViewAvailable(this);
22134                 }
22135             }
22136         }
22137         rebuildOutline();
22138     }
22139 
22140     /**
22141      * Finalize inflating a view from XML.  This is called as the last phase
22142      * of inflation, after all child views have been added.
22143      *
22144      * <p>Even if the subclass overrides onFinishInflate, they should always be
22145      * sure to call the super method, so that we get called.
22146      */
22147     @CallSuper
onFinishInflate()22148     protected void onFinishInflate() {
22149     }
22150 
22151     /**
22152      * Returns the resources associated with this view.
22153      *
22154      * @return Resources object.
22155      */
getResources()22156     public Resources getResources() {
22157         return mResources;
22158     }
22159 
22160     /**
22161      * Invalidates the specified Drawable.
22162      *
22163      * @param drawable the drawable to invalidate
22164      */
22165     @Override
invalidateDrawable(@onNull Drawable drawable)22166     public void invalidateDrawable(@NonNull Drawable drawable) {
22167         if (verifyDrawable(drawable)) {
22168             final Rect dirty = drawable.getDirtyBounds();
22169             final int scrollX = mScrollX;
22170             final int scrollY = mScrollY;
22171 
22172             invalidate(dirty.left + scrollX, dirty.top + scrollY,
22173                     dirty.right + scrollX, dirty.bottom + scrollY);
22174             rebuildOutline();
22175         }
22176     }
22177 
22178     /**
22179      * Schedules an action on a drawable to occur at a specified time.
22180      *
22181      * @param who the recipient of the action
22182      * @param what the action to run on the drawable
22183      * @param when the time at which the action must occur. Uses the
22184      *        {@link SystemClock#uptimeMillis} timebase.
22185      */
22186     @Override
scheduleDrawable(@onNull Drawable who, @NonNull Runnable what, long when)22187     public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
22188         if (verifyDrawable(who) && what != null) {
22189             final long delay = when - SystemClock.uptimeMillis();
22190             if (mAttachInfo != null) {
22191                 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
22192                         Choreographer.CALLBACK_ANIMATION, what, who,
22193                         Choreographer.subtractFrameDelay(delay));
22194             } else {
22195                 // Postpone the runnable until we know
22196                 // on which thread it needs to run.
22197                 getRunQueue().postDelayed(what, delay);
22198             }
22199         }
22200     }
22201 
22202     /**
22203      * Cancels a scheduled action on a drawable.
22204      *
22205      * @param who the recipient of the action
22206      * @param what the action to cancel
22207      */
22208     @Override
unscheduleDrawable(@onNull Drawable who, @NonNull Runnable what)22209     public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
22210         if (verifyDrawable(who) && what != null) {
22211             if (mAttachInfo != null) {
22212                 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
22213                         Choreographer.CALLBACK_ANIMATION, what, who);
22214             }
22215             getRunQueue().removeCallbacks(what);
22216         }
22217     }
22218 
22219     /**
22220      * Unschedule any events associated with the given Drawable.  This can be
22221      * used when selecting a new Drawable into a view, so that the previous
22222      * one is completely unscheduled.
22223      *
22224      * @param who The Drawable to unschedule.
22225      *
22226      * @see #drawableStateChanged
22227      */
unscheduleDrawable(Drawable who)22228     public void unscheduleDrawable(Drawable who) {
22229         if (mAttachInfo != null && who != null) {
22230             mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
22231                     Choreographer.CALLBACK_ANIMATION, null, who);
22232         }
22233     }
22234 
22235     /**
22236      * Resolve the Drawables depending on the layout direction. This is implicitly supposing
22237      * that the View directionality can and will be resolved before its Drawables.
22238      *
22239      * Will call {@link View#onResolveDrawables} when resolution is done.
22240      *
22241      * @hide
22242      */
resolveDrawables()22243     protected void resolveDrawables() {
22244         // Drawables resolution may need to happen before resolving the layout direction (which is
22245         // done only during the measure() call).
22246         // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
22247         // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
22248         // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
22249         // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
22250         // direction to be resolved as its resolved value will be the same as its raw value.
22251         if (!isLayoutDirectionResolved() &&
22252                 getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
22253             return;
22254         }
22255 
22256         final int layoutDirection = isLayoutDirectionResolved() ?
22257                 getLayoutDirection() : getRawLayoutDirection();
22258 
22259         if (mBackground != null) {
22260             mBackground.setLayoutDirection(layoutDirection);
22261         }
22262         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
22263             mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
22264         }
22265         if (mDefaultFocusHighlight != null) {
22266             mDefaultFocusHighlight.setLayoutDirection(layoutDirection);
22267         }
22268         mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
22269         onResolveDrawables(layoutDirection);
22270     }
22271 
areDrawablesResolved()22272     boolean areDrawablesResolved() {
22273         return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
22274     }
22275 
22276     /**
22277      * Called when layout direction has been resolved.
22278      *
22279      * The default implementation does nothing.
22280      *
22281      * @param layoutDirection The resolved layout direction.
22282      *
22283      * @see #LAYOUT_DIRECTION_LTR
22284      * @see #LAYOUT_DIRECTION_RTL
22285      *
22286      * @hide
22287      */
onResolveDrawables(@esolvedLayoutDir int layoutDirection)22288     public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
22289     }
22290 
22291     /**
22292      * @hide
22293      */
22294     @TestApi
resetResolvedDrawables()22295     protected void resetResolvedDrawables() {
22296         resetResolvedDrawablesInternal();
22297     }
22298 
resetResolvedDrawablesInternal()22299     void resetResolvedDrawablesInternal() {
22300         mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
22301     }
22302 
22303     /**
22304      * If your view subclass is displaying its own Drawable objects, it should
22305      * override this function and return true for any Drawable it is
22306      * displaying.  This allows animations for those drawables to be
22307      * scheduled.
22308      *
22309      * <p>Be sure to call through to the super class when overriding this
22310      * function.
22311      *
22312      * @param who The Drawable to verify.  Return true if it is one you are
22313      *            displaying, else return the result of calling through to the
22314      *            super class.
22315      *
22316      * @return boolean If true than the Drawable is being displayed in the
22317      *         view; else false and it is not allowed to animate.
22318      *
22319      * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
22320      * @see #drawableStateChanged()
22321      */
22322     @CallSuper
verifyDrawable(@onNull Drawable who)22323     protected boolean verifyDrawable(@NonNull Drawable who) {
22324         // Avoid verifying the scroll bar drawable so that we don't end up in
22325         // an invalidation loop. This effectively prevents the scroll bar
22326         // drawable from triggering invalidations and scheduling runnables.
22327         return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who)
22328                 || (mDefaultFocusHighlight == who);
22329     }
22330 
22331     /**
22332      * This function is called whenever the state of the view changes in such
22333      * a way that it impacts the state of drawables being shown.
22334      * <p>
22335      * If the View has a StateListAnimator, it will also be called to run necessary state
22336      * change animations.
22337      * <p>
22338      * Be sure to call through to the superclass when overriding this function.
22339      *
22340      * @see Drawable#setState(int[])
22341      */
22342     @CallSuper
drawableStateChanged()22343     protected void drawableStateChanged() {
22344         final int[] state = getDrawableState();
22345         boolean changed = false;
22346 
22347         final Drawable bg = mBackground;
22348         if (bg != null && bg.isStateful()) {
22349             changed |= bg.setState(state);
22350         }
22351 
22352         final Drawable hl = mDefaultFocusHighlight;
22353         if (hl != null && hl.isStateful()) {
22354             changed |= hl.setState(state);
22355         }
22356 
22357         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
22358         if (fg != null && fg.isStateful()) {
22359             changed |= fg.setState(state);
22360         }
22361 
22362         if (mScrollCache != null) {
22363             final Drawable scrollBar = mScrollCache.scrollBar;
22364             if (scrollBar != null && scrollBar.isStateful()) {
22365                 changed |= scrollBar.setState(state)
22366                         && mScrollCache.state != ScrollabilityCache.OFF;
22367             }
22368         }
22369 
22370         if (mStateListAnimator != null) {
22371             mStateListAnimator.setState(state);
22372         }
22373 
22374         if (changed) {
22375             invalidate();
22376         }
22377     }
22378 
22379     /**
22380      * This function is called whenever the view hotspot changes and needs to
22381      * be propagated to drawables or child views managed by the view.
22382      * <p>
22383      * Dispatching to child views is handled by
22384      * {@link #dispatchDrawableHotspotChanged(float, float)}.
22385      * <p>
22386      * Be sure to call through to the superclass when overriding this function.
22387      *
22388      * @param x hotspot x coordinate
22389      * @param y hotspot y coordinate
22390      */
22391     @CallSuper
drawableHotspotChanged(float x, float y)22392     public void drawableHotspotChanged(float x, float y) {
22393         if (mBackground != null) {
22394             mBackground.setHotspot(x, y);
22395         }
22396         if (mDefaultFocusHighlight != null) {
22397             mDefaultFocusHighlight.setHotspot(x, y);
22398         }
22399         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
22400             mForegroundInfo.mDrawable.setHotspot(x, y);
22401         }
22402 
22403         dispatchDrawableHotspotChanged(x, y);
22404     }
22405 
22406     /**
22407      * Dispatches drawableHotspotChanged to all of this View's children.
22408      *
22409      * @param x hotspot x coordinate
22410      * @param y hotspot y coordinate
22411      * @see #drawableHotspotChanged(float, float)
22412      */
dispatchDrawableHotspotChanged(float x, float y)22413     public void dispatchDrawableHotspotChanged(float x, float y) {
22414     }
22415 
22416     /**
22417      * Call this to force a view to update its drawable state. This will cause
22418      * drawableStateChanged to be called on this view. Views that are interested
22419      * in the new state should call getDrawableState.
22420      *
22421      * @see #drawableStateChanged
22422      * @see #getDrawableState
22423      */
refreshDrawableState()22424     public void refreshDrawableState() {
22425         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
22426         drawableStateChanged();
22427 
22428         ViewParent parent = mParent;
22429         if (parent != null) {
22430             parent.childDrawableStateChanged(this);
22431         }
22432     }
22433 
22434     /**
22435      * Create a default focus highlight if it doesn't exist.
22436      * @return a default focus highlight.
22437      */
getDefaultFocusHighlightDrawable()22438     private Drawable getDefaultFocusHighlightDrawable() {
22439         if (mDefaultFocusHighlightCache == null) {
22440             if (mContext != null) {
22441                 final int[] attrs = new int[] { android.R.attr.selectableItemBackground };
22442                 final TypedArray ta = mContext.obtainStyledAttributes(attrs);
22443                 mDefaultFocusHighlightCache = ta.getDrawable(0);
22444                 ta.recycle();
22445             }
22446         }
22447         return mDefaultFocusHighlightCache;
22448     }
22449 
22450     /**
22451      * Set the current default focus highlight.
22452      * @param highlight the highlight drawable, or {@code null} if it's no longer needed.
22453      */
setDefaultFocusHighlight(Drawable highlight)22454     private void setDefaultFocusHighlight(Drawable highlight) {
22455         mDefaultFocusHighlight = highlight;
22456         mDefaultFocusHighlightSizeChanged = true;
22457         if (highlight != null) {
22458             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
22459                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
22460             }
22461             highlight.setLayoutDirection(getLayoutDirection());
22462             if (highlight.isStateful()) {
22463                 highlight.setState(getDrawableState());
22464             }
22465             if (isAttachedToWindow()) {
22466                 highlight.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
22467             }
22468             // Set callback last, since the view may still be initializing.
22469             highlight.setCallback(this);
22470         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
22471                 && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
22472             mPrivateFlags |= PFLAG_SKIP_DRAW;
22473         }
22474         invalidate();
22475     }
22476 
22477     /**
22478      * Check whether we need to draw a default focus highlight when this view gets focused,
22479      * which requires:
22480      * <ul>
22481      *     <li>In both background and foreground, {@link android.R.attr#state_focused}
22482      *         is not defined.</li>
22483      *     <li>This view is not in touch mode.</li>
22484      *     <li>This view doesn't opt out for a default focus highlight, via
22485      *         {@link #setDefaultFocusHighlightEnabled(boolean)}.</li>
22486      *     <li>This view is attached to window.</li>
22487      * </ul>
22488      * @return {@code true} if a default focus highlight is needed.
22489      * @hide
22490      */
22491     @TestApi
isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground)22492     public boolean isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground) {
22493         final boolean lackFocusState = (background == null || !background.isStateful()
22494                 || !background.hasFocusStateSpecified())
22495                 && (foreground == null || !foreground.isStateful()
22496                 || !foreground.hasFocusStateSpecified());
22497         return !isInTouchMode() && getDefaultFocusHighlightEnabled() && lackFocusState
22498                 && isAttachedToWindow() && sUseDefaultFocusHighlight;
22499     }
22500 
22501     /**
22502      * When this view is focused, switches on/off the default focused highlight.
22503      * <p>
22504      * This always happens when this view is focused, and only at this moment the default focus
22505      * highlight can be visible.
22506      */
switchDefaultFocusHighlight()22507     private void switchDefaultFocusHighlight() {
22508         if (isFocused()) {
22509             final boolean needed = isDefaultFocusHighlightNeeded(mBackground,
22510                     mForegroundInfo == null ? null : mForegroundInfo.mDrawable);
22511             final boolean active = mDefaultFocusHighlight != null;
22512             if (needed && !active) {
22513                 setDefaultFocusHighlight(getDefaultFocusHighlightDrawable());
22514             } else if (!needed && active) {
22515                 // The highlight is no longer needed, so tear it down.
22516                 setDefaultFocusHighlight(null);
22517             }
22518         }
22519     }
22520 
22521     /**
22522      * Draw the default focus highlight onto the canvas.
22523      * @param canvas the canvas where we're drawing the highlight.
22524      */
drawDefaultFocusHighlight(Canvas canvas)22525     private void drawDefaultFocusHighlight(Canvas canvas) {
22526         if (mDefaultFocusHighlight != null) {
22527             if (mDefaultFocusHighlightSizeChanged) {
22528                 mDefaultFocusHighlightSizeChanged = false;
22529                 final int l = mScrollX;
22530                 final int r = l + mRight - mLeft;
22531                 final int t = mScrollY;
22532                 final int b = t + mBottom - mTop;
22533                 mDefaultFocusHighlight.setBounds(l, t, r, b);
22534             }
22535             mDefaultFocusHighlight.draw(canvas);
22536         }
22537     }
22538 
22539     /**
22540      * Return an array of resource IDs of the drawable states representing the
22541      * current state of the view.
22542      *
22543      * @return The current drawable state
22544      *
22545      * @see Drawable#setState(int[])
22546      * @see #drawableStateChanged()
22547      * @see #onCreateDrawableState(int)
22548      */
getDrawableState()22549     public final int[] getDrawableState() {
22550         if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
22551             return mDrawableState;
22552         } else {
22553             mDrawableState = onCreateDrawableState(0);
22554             mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
22555             return mDrawableState;
22556         }
22557     }
22558 
22559     /**
22560      * Generate the new {@link android.graphics.drawable.Drawable} state for
22561      * this view. This is called by the view
22562      * system when the cached Drawable state is determined to be invalid.  To
22563      * retrieve the current state, you should use {@link #getDrawableState}.
22564      *
22565      * @param extraSpace if non-zero, this is the number of extra entries you
22566      * would like in the returned array in which you can place your own
22567      * states.
22568      *
22569      * @return Returns an array holding the current {@link Drawable} state of
22570      * the view.
22571      *
22572      * @see #mergeDrawableStates(int[], int[])
22573      */
onCreateDrawableState(int extraSpace)22574     protected int[] onCreateDrawableState(int extraSpace) {
22575         if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
22576                 mParent instanceof View) {
22577             return ((View) mParent).onCreateDrawableState(extraSpace);
22578         }
22579 
22580         int[] drawableState;
22581 
22582         int privateFlags = mPrivateFlags;
22583 
22584         int viewStateIndex = 0;
22585         if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
22586         if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
22587         if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
22588         if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
22589         if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
22590         if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
22591         if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
22592                 ThreadedRenderer.isAvailable()) {
22593             // This is set if HW acceleration is requested, even if the current
22594             // process doesn't allow it.  This is just to allow app preview
22595             // windows to better match their app.
22596             viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
22597         }
22598         if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
22599 
22600         final int privateFlags2 = mPrivateFlags2;
22601         if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
22602             viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
22603         }
22604         if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
22605             viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
22606         }
22607 
22608         drawableState = StateSet.get(viewStateIndex);
22609 
22610         //noinspection ConstantIfStatement
22611         if (false) {
22612             Log.i("View", "drawableStateIndex=" + viewStateIndex);
22613             Log.i("View", toString()
22614                     + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
22615                     + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
22616                     + " fo=" + hasFocus()
22617                     + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
22618                     + " wf=" + hasWindowFocus()
22619                     + ": " + Arrays.toString(drawableState));
22620         }
22621 
22622         if (extraSpace == 0) {
22623             return drawableState;
22624         }
22625 
22626         final int[] fullState;
22627         if (drawableState != null) {
22628             fullState = new int[drawableState.length + extraSpace];
22629             System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
22630         } else {
22631             fullState = new int[extraSpace];
22632         }
22633 
22634         return fullState;
22635     }
22636 
22637     /**
22638      * Merge your own state values in <var>additionalState</var> into the base
22639      * state values <var>baseState</var> that were returned by
22640      * {@link #onCreateDrawableState(int)}.
22641      *
22642      * @param baseState The base state values returned by
22643      * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
22644      * own additional state values.
22645      *
22646      * @param additionalState The additional state values you would like
22647      * added to <var>baseState</var>; this array is not modified.
22648      *
22649      * @return As a convenience, the <var>baseState</var> array you originally
22650      * passed into the function is returned.
22651      *
22652      * @see #onCreateDrawableState(int)
22653      */
mergeDrawableStates(int[] baseState, int[] additionalState)22654     protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
22655         final int N = baseState.length;
22656         int i = N - 1;
22657         while (i >= 0 && baseState[i] == 0) {
22658             i--;
22659         }
22660         System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
22661         return baseState;
22662     }
22663 
22664     /**
22665      * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
22666      * on all Drawable objects associated with this view.
22667      * <p>
22668      * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
22669      * attached to this view.
22670      */
22671     @CallSuper
jumpDrawablesToCurrentState()22672     public void jumpDrawablesToCurrentState() {
22673         if (mBackground != null) {
22674             mBackground.jumpToCurrentState();
22675         }
22676         if (mStateListAnimator != null) {
22677             mStateListAnimator.jumpToCurrentState();
22678         }
22679         if (mDefaultFocusHighlight != null) {
22680             mDefaultFocusHighlight.jumpToCurrentState();
22681         }
22682         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
22683             mForegroundInfo.mDrawable.jumpToCurrentState();
22684         }
22685     }
22686 
22687     /**
22688      * Sets the background color for this view.
22689      * @param color the color of the background
22690      */
22691     @RemotableViewMethod
setBackgroundColor(@olorInt int color)22692     public void setBackgroundColor(@ColorInt int color) {
22693         if (mBackground instanceof ColorDrawable) {
22694             ((ColorDrawable) mBackground.mutate()).setColor(color);
22695             computeOpaqueFlags();
22696             mBackgroundResource = 0;
22697         } else {
22698             setBackground(new ColorDrawable(color));
22699         }
22700     }
22701 
22702     /**
22703      * Set the background to a given resource. The resource should refer to
22704      * a Drawable object or 0 to remove the background.
22705      * @param resid The identifier of the resource.
22706      *
22707      * @attr ref android.R.styleable#View_background
22708      */
22709     @RemotableViewMethod
setBackgroundResource(@rawableRes int resid)22710     public void setBackgroundResource(@DrawableRes int resid) {
22711         if (resid != 0 && resid == mBackgroundResource) {
22712             return;
22713         }
22714 
22715         Drawable d = null;
22716         if (resid != 0) {
22717             d = mContext.getDrawable(resid);
22718         }
22719         setBackground(d);
22720 
22721         mBackgroundResource = resid;
22722     }
22723 
22724     /**
22725      * Set the background to a given Drawable, or remove the background. If the
22726      * background has padding, this View's padding is set to the background's
22727      * padding. However, when a background is removed, this View's padding isn't
22728      * touched. If setting the padding is desired, please use
22729      * {@link #setPadding(int, int, int, int)}.
22730      *
22731      * @param background The Drawable to use as the background, or null to remove the
22732      *        background
22733      */
setBackground(Drawable background)22734     public void setBackground(Drawable background) {
22735         //noinspection deprecation
22736         setBackgroundDrawable(background);
22737     }
22738 
22739     /**
22740      * @deprecated use {@link #setBackground(Drawable)} instead
22741      */
22742     @Deprecated
setBackgroundDrawable(Drawable background)22743     public void setBackgroundDrawable(Drawable background) {
22744         computeOpaqueFlags();
22745 
22746         if (background == mBackground) {
22747             return;
22748         }
22749 
22750         boolean requestLayout = false;
22751 
22752         mBackgroundResource = 0;
22753 
22754         /*
22755          * Regardless of whether we're setting a new background or not, we want
22756          * to clear the previous drawable. setVisible first while we still have the callback set.
22757          */
22758         if (mBackground != null) {
22759             if (isAttachedToWindow()) {
22760                 mBackground.setVisible(false, false);
22761             }
22762             mBackground.setCallback(null);
22763             unscheduleDrawable(mBackground);
22764         }
22765 
22766         if (background != null) {
22767             Rect padding = sThreadLocal.get();
22768             if (padding == null) {
22769                 padding = new Rect();
22770                 sThreadLocal.set(padding);
22771             }
22772             resetResolvedDrawablesInternal();
22773             background.setLayoutDirection(getLayoutDirection());
22774             if (background.getPadding(padding)) {
22775                 resetResolvedPaddingInternal();
22776                 switch (background.getLayoutDirection()) {
22777                     case LAYOUT_DIRECTION_RTL:
22778                         mUserPaddingLeftInitial = padding.right;
22779                         mUserPaddingRightInitial = padding.left;
22780                         internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
22781                         break;
22782                     case LAYOUT_DIRECTION_LTR:
22783                     default:
22784                         mUserPaddingLeftInitial = padding.left;
22785                         mUserPaddingRightInitial = padding.right;
22786                         internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
22787                 }
22788                 mLeftPaddingDefined = false;
22789                 mRightPaddingDefined = false;
22790             }
22791 
22792             // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
22793             // if it has a different minimum size, we should layout again
22794             if (mBackground == null
22795                     || mBackground.getMinimumHeight() != background.getMinimumHeight()
22796                     || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
22797                 requestLayout = true;
22798             }
22799 
22800             // Set mBackground before we set this as the callback and start making other
22801             // background drawable state change calls. In particular, the setVisible call below
22802             // can result in drawables attempting to start animations or otherwise invalidate,
22803             // which requires the view set as the callback (us) to recognize the drawable as
22804             // belonging to it as per verifyDrawable.
22805             mBackground = background;
22806             if (background.isStateful()) {
22807                 background.setState(getDrawableState());
22808             }
22809             if (isAttachedToWindow()) {
22810                 background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
22811             }
22812 
22813             applyBackgroundTint();
22814 
22815             // Set callback last, since the view may still be initializing.
22816             background.setCallback(this);
22817 
22818             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
22819                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
22820                 requestLayout = true;
22821             }
22822         } else {
22823             /* Remove the background */
22824             mBackground = null;
22825             if ((mViewFlags & WILL_NOT_DRAW) != 0
22826                     && (mDefaultFocusHighlight == null)
22827                     && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
22828                 mPrivateFlags |= PFLAG_SKIP_DRAW;
22829             }
22830 
22831             /*
22832              * When the background is set, we try to apply its padding to this
22833              * View. When the background is removed, we don't touch this View's
22834              * padding. This is noted in the Javadocs. Hence, we don't need to
22835              * requestLayout(), the invalidate() below is sufficient.
22836              */
22837 
22838             // The old background's minimum size could have affected this
22839             // View's layout, so let's requestLayout
22840             requestLayout = true;
22841         }
22842 
22843         computeOpaqueFlags();
22844 
22845         if (requestLayout) {
22846             requestLayout();
22847         }
22848 
22849         mBackgroundSizeChanged = true;
22850         invalidate(true);
22851         invalidateOutline();
22852     }
22853 
22854     /**
22855      * Gets the background drawable
22856      *
22857      * @return The drawable used as the background for this view, if any.
22858      *
22859      * @see #setBackground(Drawable)
22860      *
22861      * @attr ref android.R.styleable#View_background
22862      */
22863     @InspectableProperty
getBackground()22864     public Drawable getBackground() {
22865         return mBackground;
22866     }
22867 
22868     /**
22869      * Applies a tint to the background drawable. Does not modify the current tint
22870      * mode, which is {@link BlendMode#SRC_IN} by default.
22871      * <p>
22872      * Subsequent calls to {@link #setBackground(Drawable)} will automatically
22873      * mutate the drawable and apply the specified tint and tint mode using
22874      * {@link Drawable#setTintList(ColorStateList)}.
22875      *
22876      * @param tint the tint to apply, may be {@code null} to clear tint
22877      *
22878      * @attr ref android.R.styleable#View_backgroundTint
22879      * @see #getBackgroundTintList()
22880      * @see Drawable#setTintList(ColorStateList)
22881      */
setBackgroundTintList(@ullable ColorStateList tint)22882     public void setBackgroundTintList(@Nullable ColorStateList tint) {
22883         if (mBackgroundTint == null) {
22884             mBackgroundTint = new TintInfo();
22885         }
22886         mBackgroundTint.mTintList = tint;
22887         mBackgroundTint.mHasTintList = true;
22888 
22889         applyBackgroundTint();
22890     }
22891 
22892     /**
22893      * Return the tint applied to the background drawable, if specified.
22894      *
22895      * @return the tint applied to the background drawable
22896      * @attr ref android.R.styleable#View_backgroundTint
22897      * @see #setBackgroundTintList(ColorStateList)
22898      */
22899     @InspectableProperty(name = "backgroundTint")
22900     @Nullable
getBackgroundTintList()22901     public ColorStateList getBackgroundTintList() {
22902         return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
22903     }
22904 
22905     /**
22906      * Specifies the blending mode used to apply the tint specified by
22907      * {@link #setBackgroundTintList(ColorStateList)}} to the background
22908      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
22909      *
22910      * @param tintMode the blending mode used to apply the tint, may be
22911      *                 {@code null} to clear tint
22912      * @attr ref android.R.styleable#View_backgroundTintMode
22913      * @see #getBackgroundTintMode()
22914      * @see Drawable#setTintMode(PorterDuff.Mode)
22915      */
setBackgroundTintMode(@ullable PorterDuff.Mode tintMode)22916     public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
22917         BlendMode mode = null;
22918         if (tintMode != null) {
22919             mode = BlendMode.fromValue(tintMode.nativeInt);
22920         }
22921 
22922         setBackgroundTintBlendMode(mode);
22923     }
22924 
22925     /**
22926      * Specifies the blending mode used to apply the tint specified by
22927      * {@link #setBackgroundTintList(ColorStateList)}} to the background
22928      * drawable. The default mode is {@link BlendMode#SRC_IN}.
22929      *
22930      * @param blendMode the blending mode used to apply the tint, may be
22931      *                 {@code null} to clear tint
22932      * @attr ref android.R.styleable#View_backgroundTintMode
22933      * @see #getBackgroundTintMode()
22934      * @see Drawable#setTintBlendMode(BlendMode)
22935      */
setBackgroundTintBlendMode(@ullable BlendMode blendMode)22936     public void setBackgroundTintBlendMode(@Nullable BlendMode blendMode) {
22937         if (mBackgroundTint == null) {
22938             mBackgroundTint = new TintInfo();
22939         }
22940 
22941         mBackgroundTint.mBlendMode = blendMode;
22942         mBackgroundTint.mHasTintMode = true;
22943 
22944         applyBackgroundTint();
22945     }
22946 
22947     /**
22948      * Return the blending mode used to apply the tint to the background
22949      * drawable, if specified.
22950      *
22951      * @return the blending mode used to apply the tint to the background
22952      *         drawable
22953      * @attr ref android.R.styleable#View_backgroundTintMode
22954      * @see #setBackgroundTintBlendMode(BlendMode)
22955      *
22956      */
22957     @Nullable
22958     @InspectableProperty
getBackgroundTintMode()22959     public PorterDuff.Mode getBackgroundTintMode() {
22960         PorterDuff.Mode porterDuffMode;
22961         if (mBackgroundTint != null && mBackgroundTint.mBlendMode != null) {
22962             porterDuffMode = BlendMode.blendModeToPorterDuffMode(mBackgroundTint.mBlendMode);
22963         } else {
22964             porterDuffMode = null;
22965         }
22966         return porterDuffMode;
22967     }
22968 
22969     /**
22970      * Return the blending mode used to apply the tint to the background
22971      * drawable, if specified.
22972      *
22973      * @return the blending mode used to apply the tint to the background
22974      *         drawable, null if no blend has previously been configured
22975      * @attr ref android.R.styleable#View_backgroundTintMode
22976      * @see #setBackgroundTintBlendMode(BlendMode)
22977      */
getBackgroundTintBlendMode()22978     public @Nullable BlendMode getBackgroundTintBlendMode() {
22979         return mBackgroundTint != null ? mBackgroundTint.mBlendMode : null;
22980     }
22981 
applyBackgroundTint()22982     private void applyBackgroundTint() {
22983         if (mBackground != null && mBackgroundTint != null) {
22984             final TintInfo tintInfo = mBackgroundTint;
22985             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
22986                 mBackground = mBackground.mutate();
22987 
22988                 if (tintInfo.mHasTintList) {
22989                     mBackground.setTintList(tintInfo.mTintList);
22990                 }
22991 
22992                 if (tintInfo.mHasTintMode) {
22993                     mBackground.setTintBlendMode(tintInfo.mBlendMode);
22994                 }
22995 
22996                 // The drawable (or one of its children) may not have been
22997                 // stateful before applying the tint, so let's try again.
22998                 if (mBackground.isStateful()) {
22999                     mBackground.setState(getDrawableState());
23000                 }
23001             }
23002         }
23003     }
23004 
23005     /**
23006      * Returns the drawable used as the foreground of this View. The
23007      * foreground drawable, if non-null, is always drawn on top of the view's content.
23008      *
23009      * @return a Drawable or null if no foreground was set
23010      *
23011      * @see #onDrawForeground(Canvas)
23012      */
23013     @InspectableProperty
getForeground()23014     public Drawable getForeground() {
23015         return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
23016     }
23017 
23018     /**
23019      * Supply a Drawable that is to be rendered on top of all of the content in the view.
23020      *
23021      * @param foreground the Drawable to be drawn on top of the children
23022      *
23023      * @attr ref android.R.styleable#View_foreground
23024      */
setForeground(Drawable foreground)23025     public void setForeground(Drawable foreground) {
23026         if (mForegroundInfo == null) {
23027             if (foreground == null) {
23028                 // Nothing to do.
23029                 return;
23030             }
23031             mForegroundInfo = new ForegroundInfo();
23032         }
23033 
23034         if (foreground == mForegroundInfo.mDrawable) {
23035             // Nothing to do
23036             return;
23037         }
23038 
23039         if (mForegroundInfo.mDrawable != null) {
23040             if (isAttachedToWindow()) {
23041                 mForegroundInfo.mDrawable.setVisible(false, false);
23042             }
23043             mForegroundInfo.mDrawable.setCallback(null);
23044             unscheduleDrawable(mForegroundInfo.mDrawable);
23045         }
23046 
23047         mForegroundInfo.mDrawable = foreground;
23048         mForegroundInfo.mBoundsChanged = true;
23049         if (foreground != null) {
23050             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
23051                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
23052             }
23053             foreground.setLayoutDirection(getLayoutDirection());
23054             if (foreground.isStateful()) {
23055                 foreground.setState(getDrawableState());
23056             }
23057             applyForegroundTint();
23058             if (isAttachedToWindow()) {
23059                 foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
23060             }
23061             // Set callback last, since the view may still be initializing.
23062             foreground.setCallback(this);
23063         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
23064                 && (mDefaultFocusHighlight == null)) {
23065             mPrivateFlags |= PFLAG_SKIP_DRAW;
23066         }
23067         requestLayout();
23068         invalidate();
23069     }
23070 
23071     /**
23072      * Magic bit used to support features of framework-internal window decor implementation details.
23073      * This used to live exclusively in FrameLayout.
23074      *
23075      * @return true if the foreground should draw inside the padding region or false
23076      *         if it should draw inset by the view's padding
23077      * @hide internal use only; only used by FrameLayout and internal screen layouts.
23078      */
isForegroundInsidePadding()23079     public boolean isForegroundInsidePadding() {
23080         return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
23081     }
23082 
23083     /**
23084      * Describes how the foreground is positioned.
23085      *
23086      * @return foreground gravity.
23087      *
23088      * @see #setForegroundGravity(int)
23089      *
23090      * @attr ref android.R.styleable#View_foregroundGravity
23091      */
23092     @InspectableProperty(valueType = InspectableProperty.ValueType.GRAVITY)
getForegroundGravity()23093     public int getForegroundGravity() {
23094         return mForegroundInfo != null ? mForegroundInfo.mGravity
23095                 : Gravity.START | Gravity.TOP;
23096     }
23097 
23098     /**
23099      * Describes how the foreground is positioned. Defaults to START and TOP.
23100      *
23101      * @param gravity see {@link android.view.Gravity}
23102      *
23103      * @see #getForegroundGravity()
23104      *
23105      * @attr ref android.R.styleable#View_foregroundGravity
23106      */
setForegroundGravity(int gravity)23107     public void setForegroundGravity(int gravity) {
23108         if (mForegroundInfo == null) {
23109             mForegroundInfo = new ForegroundInfo();
23110         }
23111 
23112         if (mForegroundInfo.mGravity != gravity) {
23113             if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
23114                 gravity |= Gravity.START;
23115             }
23116 
23117             if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
23118                 gravity |= Gravity.TOP;
23119             }
23120 
23121             mForegroundInfo.mGravity = gravity;
23122             requestLayout();
23123         }
23124     }
23125 
23126     /**
23127      * Applies a tint to the foreground drawable. Does not modify the current tint
23128      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
23129      * <p>
23130      * Subsequent calls to {@link #setForeground(Drawable)} will automatically
23131      * mutate the drawable and apply the specified tint and tint mode using
23132      * {@link Drawable#setTintList(ColorStateList)}.
23133      *
23134      * @param tint the tint to apply, may be {@code null} to clear tint
23135      *
23136      * @attr ref android.R.styleable#View_foregroundTint
23137      * @see #getForegroundTintList()
23138      * @see Drawable#setTintList(ColorStateList)
23139      */
setForegroundTintList(@ullable ColorStateList tint)23140     public void setForegroundTintList(@Nullable ColorStateList tint) {
23141         if (mForegroundInfo == null) {
23142             mForegroundInfo = new ForegroundInfo();
23143         }
23144         if (mForegroundInfo.mTintInfo == null) {
23145             mForegroundInfo.mTintInfo = new TintInfo();
23146         }
23147         mForegroundInfo.mTintInfo.mTintList = tint;
23148         mForegroundInfo.mTintInfo.mHasTintList = true;
23149 
23150         applyForegroundTint();
23151     }
23152 
23153     /**
23154      * Return the tint applied to the foreground drawable, if specified.
23155      *
23156      * @return the tint applied to the foreground drawable
23157      * @attr ref android.R.styleable#View_foregroundTint
23158      * @see #setForegroundTintList(ColorStateList)
23159      */
23160     @InspectableProperty(name = "foregroundTint")
23161     @Nullable
getForegroundTintList()23162     public ColorStateList getForegroundTintList() {
23163         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
23164                 ? mForegroundInfo.mTintInfo.mTintList : null;
23165     }
23166 
23167     /**
23168      * Specifies the blending mode used to apply the tint specified by
23169      * {@link #setForegroundTintList(ColorStateList)}} to the background
23170      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
23171      *
23172      * @param tintMode the blending mode used to apply the tint, may be
23173      *                 {@code null} to clear tint
23174      * @attr ref android.R.styleable#View_foregroundTintMode
23175      * @see #getForegroundTintMode()
23176      * @see Drawable#setTintMode(PorterDuff.Mode)
23177      *
23178      */
setForegroundTintMode(@ullable PorterDuff.Mode tintMode)23179     public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
23180         BlendMode mode = null;
23181         if (tintMode != null) {
23182             mode = BlendMode.fromValue(tintMode.nativeInt);
23183         }
23184         setForegroundTintBlendMode(mode);
23185     }
23186 
23187     /**
23188      * Specifies the blending mode used to apply the tint specified by
23189      * {@link #setForegroundTintList(ColorStateList)}} to the background
23190      * drawable. The default mode is {@link BlendMode#SRC_IN}.
23191      *
23192      * @param blendMode the blending mode used to apply the tint, may be
23193      *                 {@code null} to clear tint
23194      * @attr ref android.R.styleable#View_foregroundTintMode
23195      * @see #getForegroundTintMode()
23196      * @see Drawable#setTintBlendMode(BlendMode)
23197      */
setForegroundTintBlendMode(@ullable BlendMode blendMode)23198     public void setForegroundTintBlendMode(@Nullable BlendMode blendMode) {
23199         if (mForegroundInfo == null) {
23200             mForegroundInfo = new ForegroundInfo();
23201         }
23202         if (mForegroundInfo.mTintInfo == null) {
23203             mForegroundInfo.mTintInfo = new TintInfo();
23204         }
23205         mForegroundInfo.mTintInfo.mBlendMode = blendMode;
23206         mForegroundInfo.mTintInfo.mHasTintMode = true;
23207 
23208         applyForegroundTint();
23209     }
23210 
23211     /**
23212      * Return the blending mode used to apply the tint to the foreground
23213      * drawable, if specified.
23214      *
23215      * @return the blending mode used to apply the tint to the foreground
23216      *         drawable
23217      * @attr ref android.R.styleable#View_foregroundTintMode
23218      * @see #setForegroundTintMode(PorterDuff.Mode)
23219      */
23220     @InspectableProperty
23221     @Nullable
getForegroundTintMode()23222     public PorterDuff.Mode getForegroundTintMode() {
23223         BlendMode blendMode = mForegroundInfo != null && mForegroundInfo.mTintInfo != null
23224                 ? mForegroundInfo.mTintInfo.mBlendMode : null;
23225         if (blendMode != null) {
23226             return BlendMode.blendModeToPorterDuffMode(blendMode);
23227         } else {
23228             return null;
23229         }
23230     }
23231 
23232     /**
23233      * Return the blending mode used to apply the tint to the foreground
23234      * drawable, if specified.
23235      *
23236      * @return the blending mode used to apply the tint to the foreground
23237      *         drawable
23238      * @attr ref android.R.styleable#View_foregroundTintMode
23239      * @see #setForegroundTintBlendMode(BlendMode)
23240      *
23241      */
getForegroundTintBlendMode()23242     public @Nullable BlendMode getForegroundTintBlendMode() {
23243         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
23244                 ? mForegroundInfo.mTintInfo.mBlendMode : null;
23245     }
23246 
applyForegroundTint()23247     private void applyForegroundTint() {
23248         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
23249                 && mForegroundInfo.mTintInfo != null) {
23250             final TintInfo tintInfo = mForegroundInfo.mTintInfo;
23251             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
23252                 mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
23253 
23254                 if (tintInfo.mHasTintList) {
23255                     mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
23256                 }
23257 
23258                 if (tintInfo.mHasTintMode) {
23259                     mForegroundInfo.mDrawable.setTintBlendMode(tintInfo.mBlendMode);
23260                 }
23261 
23262                 // The drawable (or one of its children) may not have been
23263                 // stateful before applying the tint, so let's try again.
23264                 if (mForegroundInfo.mDrawable.isStateful()) {
23265                     mForegroundInfo.mDrawable.setState(getDrawableState());
23266                 }
23267             }
23268         }
23269     }
23270 
23271     /**
23272      * Get the drawable to be overlayed when a view is autofilled
23273      *
23274      * @return The drawable
23275      *
23276      * @throws IllegalStateException if the drawable could not be found.
23277      */
getAutofilledDrawable()23278     @Nullable private Drawable getAutofilledDrawable() {
23279         if (mAttachInfo == null) {
23280             return null;
23281         }
23282         // Lazily load the isAutofilled drawable.
23283         if (mAttachInfo.mAutofilledDrawable == null) {
23284             Context rootContext = getRootView().getContext();
23285             TypedArray a = rootContext.getTheme().obtainStyledAttributes(AUTOFILL_HIGHLIGHT_ATTR);
23286             int attributeResourceId = a.getResourceId(0, 0);
23287             mAttachInfo.mAutofilledDrawable = rootContext.getDrawable(attributeResourceId);
23288             a.recycle();
23289         }
23290 
23291         return mAttachInfo.mAutofilledDrawable;
23292     }
23293 
23294     /**
23295      * Draw {@link View#isAutofilled()} highlight over view if the view is autofilled.
23296      *
23297      * @param canvas The canvas to draw on
23298      */
drawAutofilledHighlight(@onNull Canvas canvas)23299     private void drawAutofilledHighlight(@NonNull Canvas canvas) {
23300         if (isAutofilled()) {
23301             Drawable autofilledHighlight = getAutofilledDrawable();
23302 
23303             if (autofilledHighlight != null) {
23304                 autofilledHighlight.setBounds(0, 0, getWidth(), getHeight());
23305                 autofilledHighlight.draw(canvas);
23306             }
23307         }
23308     }
23309 
23310     /**
23311      * Draw any foreground content for this view.
23312      *
23313      * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
23314      * drawable or other view-specific decorations. The foreground is drawn on top of the
23315      * primary view content.</p>
23316      *
23317      * @param canvas canvas to draw into
23318      */
onDrawForeground(Canvas canvas)23319     public void onDrawForeground(Canvas canvas) {
23320         onDrawScrollIndicators(canvas);
23321         onDrawScrollBars(canvas);
23322 
23323         final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
23324         if (foreground != null) {
23325             if (mForegroundInfo.mBoundsChanged) {
23326                 mForegroundInfo.mBoundsChanged = false;
23327                 final Rect selfBounds = mForegroundInfo.mSelfBounds;
23328                 final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
23329 
23330                 if (mForegroundInfo.mInsidePadding) {
23331                     selfBounds.set(0, 0, getWidth(), getHeight());
23332                 } else {
23333                     selfBounds.set(getPaddingLeft(), getPaddingTop(),
23334                             getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
23335                 }
23336 
23337                 final int ld = getLayoutDirection();
23338                 Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
23339                         foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
23340                 foreground.setBounds(overlayBounds);
23341             }
23342 
23343             foreground.draw(canvas);
23344         }
23345     }
23346 
23347     /**
23348      * Sets the padding. The view may add on the space required to display
23349      * the scrollbars, depending on the style and visibility of the scrollbars.
23350      * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
23351      * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
23352      * from the values set in this call.
23353      *
23354      * @attr ref android.R.styleable#View_padding
23355      * @attr ref android.R.styleable#View_paddingBottom
23356      * @attr ref android.R.styleable#View_paddingLeft
23357      * @attr ref android.R.styleable#View_paddingRight
23358      * @attr ref android.R.styleable#View_paddingTop
23359      * @param left the left padding in pixels
23360      * @param top the top padding in pixels
23361      * @param right the right padding in pixels
23362      * @param bottom the bottom padding in pixels
23363      */
setPadding(int left, int top, int right, int bottom)23364     public void setPadding(int left, int top, int right, int bottom) {
23365         resetResolvedPaddingInternal();
23366 
23367         mUserPaddingStart = UNDEFINED_PADDING;
23368         mUserPaddingEnd = UNDEFINED_PADDING;
23369 
23370         mUserPaddingLeftInitial = left;
23371         mUserPaddingRightInitial = right;
23372 
23373         mLeftPaddingDefined = true;
23374         mRightPaddingDefined = true;
23375 
23376         internalSetPadding(left, top, right, bottom);
23377     }
23378 
23379     /**
23380      * @hide
23381      */
23382     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768420)
internalSetPadding(int left, int top, int right, int bottom)23383     protected void internalSetPadding(int left, int top, int right, int bottom) {
23384         mUserPaddingLeft = left;
23385         mUserPaddingRight = right;
23386         mUserPaddingBottom = bottom;
23387 
23388         final int viewFlags = mViewFlags;
23389         boolean changed = false;
23390 
23391         // Common case is there are no scroll bars.
23392         if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
23393             if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
23394                 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
23395                         ? 0 : getVerticalScrollbarWidth();
23396                 switch (mVerticalScrollbarPosition) {
23397                     case SCROLLBAR_POSITION_DEFAULT:
23398                         if (isLayoutRtl()) {
23399                             left += offset;
23400                         } else {
23401                             right += offset;
23402                         }
23403                         break;
23404                     case SCROLLBAR_POSITION_RIGHT:
23405                         right += offset;
23406                         break;
23407                     case SCROLLBAR_POSITION_LEFT:
23408                         left += offset;
23409                         break;
23410                 }
23411             }
23412             if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
23413                 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
23414                         ? 0 : getHorizontalScrollbarHeight();
23415             }
23416         }
23417 
23418         if (mPaddingLeft != left) {
23419             changed = true;
23420             mPaddingLeft = left;
23421         }
23422         if (mPaddingTop != top) {
23423             changed = true;
23424             mPaddingTop = top;
23425         }
23426         if (mPaddingRight != right) {
23427             changed = true;
23428             mPaddingRight = right;
23429         }
23430         if (mPaddingBottom != bottom) {
23431             changed = true;
23432             mPaddingBottom = bottom;
23433         }
23434 
23435         if (changed) {
23436             requestLayout();
23437             invalidateOutline();
23438         }
23439     }
23440 
23441     /**
23442      * Sets the relative padding. The view may add on the space required to display
23443      * the scrollbars, depending on the style and visibility of the scrollbars.
23444      * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
23445      * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
23446      * from the values set in this call.
23447      *
23448      * @attr ref android.R.styleable#View_padding
23449      * @attr ref android.R.styleable#View_paddingBottom
23450      * @attr ref android.R.styleable#View_paddingStart
23451      * @attr ref android.R.styleable#View_paddingEnd
23452      * @attr ref android.R.styleable#View_paddingTop
23453      * @param start the start padding in pixels
23454      * @param top the top padding in pixels
23455      * @param end the end padding in pixels
23456      * @param bottom the bottom padding in pixels
23457      */
setPaddingRelative(int start, int top, int end, int bottom)23458     public void setPaddingRelative(int start, int top, int end, int bottom) {
23459         resetResolvedPaddingInternal();
23460 
23461         mUserPaddingStart = start;
23462         mUserPaddingEnd = end;
23463         mLeftPaddingDefined = true;
23464         mRightPaddingDefined = true;
23465 
23466         switch(getLayoutDirection()) {
23467             case LAYOUT_DIRECTION_RTL:
23468                 mUserPaddingLeftInitial = end;
23469                 mUserPaddingRightInitial = start;
23470                 internalSetPadding(end, top, start, bottom);
23471                 break;
23472             case LAYOUT_DIRECTION_LTR:
23473             default:
23474                 mUserPaddingLeftInitial = start;
23475                 mUserPaddingRightInitial = end;
23476                 internalSetPadding(start, top, end, bottom);
23477         }
23478     }
23479 
23480     /**
23481      * A {@link View} can be inflated from an XML layout. For such Views this method returns the
23482      * resource ID of the source layout.
23483      *
23484      * @return The layout resource id if this view was inflated from XML, otherwise
23485      * {@link Resources#ID_NULL}.
23486      */
23487     @LayoutRes
getSourceLayoutResId()23488     public int getSourceLayoutResId() {
23489         return mSourceLayoutId;
23490     }
23491 
23492     /**
23493      * Returns the top padding of this view.
23494      *
23495      * @return the top padding in pixels
23496      */
23497     @InspectableProperty
getPaddingTop()23498     public int getPaddingTop() {
23499         return mPaddingTop;
23500     }
23501 
23502     /**
23503      * Returns the bottom padding of this view. If there are inset and enabled
23504      * scrollbars, this value may include the space required to display the
23505      * scrollbars as well.
23506      *
23507      * @return the bottom padding in pixels
23508      */
23509     @InspectableProperty
getPaddingBottom()23510     public int getPaddingBottom() {
23511         return mPaddingBottom;
23512     }
23513 
23514     /**
23515      * Returns the left padding of this view. If there are inset and enabled
23516      * scrollbars, this value may include the space required to display the
23517      * scrollbars as well.
23518      *
23519      * @return the left padding in pixels
23520      */
23521     @InspectableProperty
getPaddingLeft()23522     public int getPaddingLeft() {
23523         if (!isPaddingResolved()) {
23524             resolvePadding();
23525         }
23526         return mPaddingLeft;
23527     }
23528 
23529     /**
23530      * Returns the start padding of this view depending on its resolved layout direction.
23531      * If there are inset and enabled scrollbars, this value may include the space
23532      * required to display the scrollbars as well.
23533      *
23534      * @return the start padding in pixels
23535      */
getPaddingStart()23536     public int getPaddingStart() {
23537         if (!isPaddingResolved()) {
23538             resolvePadding();
23539         }
23540         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
23541                 mPaddingRight : mPaddingLeft;
23542     }
23543 
23544     /**
23545      * Returns the right padding of this view. If there are inset and enabled
23546      * scrollbars, this value may include the space required to display the
23547      * scrollbars as well.
23548      *
23549      * @return the right padding in pixels
23550      */
23551     @InspectableProperty
getPaddingRight()23552     public int getPaddingRight() {
23553         if (!isPaddingResolved()) {
23554             resolvePadding();
23555         }
23556         return mPaddingRight;
23557     }
23558 
23559     /**
23560      * Returns the end padding of this view depending on its resolved layout direction.
23561      * If there are inset and enabled scrollbars, this value may include the space
23562      * required to display the scrollbars as well.
23563      *
23564      * @return the end padding in pixels
23565      */
getPaddingEnd()23566     public int getPaddingEnd() {
23567         if (!isPaddingResolved()) {
23568             resolvePadding();
23569         }
23570         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
23571                 mPaddingLeft : mPaddingRight;
23572     }
23573 
23574     /**
23575      * Return if the padding has been set through relative values
23576      * {@link #setPaddingRelative(int, int, int, int)} or through
23577      * @attr ref android.R.styleable#View_paddingStart or
23578      * @attr ref android.R.styleable#View_paddingEnd
23579      *
23580      * @return true if the padding is relative or false if it is not.
23581      */
isPaddingRelative()23582     public boolean isPaddingRelative() {
23583         return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
23584     }
23585 
computeOpticalInsets()23586     Insets computeOpticalInsets() {
23587         return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
23588     }
23589 
23590     /**
23591      * @hide
23592      */
23593     @UnsupportedAppUsage
resetPaddingToInitialValues()23594     public void resetPaddingToInitialValues() {
23595         if (isRtlCompatibilityMode()) {
23596             mPaddingLeft = mUserPaddingLeftInitial;
23597             mPaddingRight = mUserPaddingRightInitial;
23598             return;
23599         }
23600         if (isLayoutRtl()) {
23601             mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
23602             mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
23603         } else {
23604             mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
23605             mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
23606         }
23607     }
23608 
23609     /**
23610      * @hide
23611      */
getOpticalInsets()23612     public Insets getOpticalInsets() {
23613         if (mLayoutInsets == null) {
23614             mLayoutInsets = computeOpticalInsets();
23615         }
23616         return mLayoutInsets;
23617     }
23618 
23619     /**
23620      * Set this view's optical insets.
23621      *
23622      * <p>This method should be treated similarly to setMeasuredDimension and not as a general
23623      * property. Views that compute their own optical insets should call it as part of measurement.
23624      * This method does not request layout. If you are setting optical insets outside of
23625      * measure/layout itself you will want to call requestLayout() yourself.
23626      * </p>
23627      * @hide
23628      */
setOpticalInsets(Insets insets)23629     public void setOpticalInsets(Insets insets) {
23630         mLayoutInsets = insets;
23631     }
23632 
23633     /**
23634      * Changes the selection state of this view. A view can be selected or not.
23635      * Note that selection is not the same as focus. Views are typically
23636      * selected in the context of an AdapterView like ListView or GridView;
23637      * the selected view is the view that is highlighted.
23638      *
23639      * @param selected true if the view must be selected, false otherwise
23640      */
setSelected(boolean selected)23641     public void setSelected(boolean selected) {
23642         //noinspection DoubleNegation
23643         if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
23644             mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
23645             if (!selected) resetPressedState();
23646             invalidate(true);
23647             refreshDrawableState();
23648             dispatchSetSelected(selected);
23649             if (selected) {
23650                 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
23651             } else {
23652                 notifyViewAccessibilityStateChangedIfNeeded(
23653                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
23654             }
23655         }
23656     }
23657 
23658     /**
23659      * Dispatch setSelected to all of this View's children.
23660      *
23661      * @see #setSelected(boolean)
23662      *
23663      * @param selected The new selected state
23664      */
dispatchSetSelected(boolean selected)23665     protected void dispatchSetSelected(boolean selected) {
23666     }
23667 
23668     /**
23669      * Indicates the selection state of this view.
23670      *
23671      * @return true if the view is selected, false otherwise
23672      */
23673     @ViewDebug.ExportedProperty
23674     @InspectableProperty(hasAttributeId = false)
isSelected()23675     public boolean isSelected() {
23676         return (mPrivateFlags & PFLAG_SELECTED) != 0;
23677     }
23678 
23679     /**
23680      * Changes the activated state of this view. A view can be activated or not.
23681      * Note that activation is not the same as selection.  Selection is
23682      * a transient property, representing the view (hierarchy) the user is
23683      * currently interacting with.  Activation is a longer-term state that the
23684      * user can move views in and out of.  For example, in a list view with
23685      * single or multiple selection enabled, the views in the current selection
23686      * set are activated.  (Um, yeah, we are deeply sorry about the terminology
23687      * here.)  The activated state is propagated down to children of the view it
23688      * is set on.
23689      *
23690      * @param activated true if the view must be activated, false otherwise
23691      */
setActivated(boolean activated)23692     public void setActivated(boolean activated) {
23693         //noinspection DoubleNegation
23694         if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
23695             mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
23696             invalidate(true);
23697             refreshDrawableState();
23698             dispatchSetActivated(activated);
23699         }
23700     }
23701 
23702     /**
23703      * Dispatch setActivated to all of this View's children.
23704      *
23705      * @see #setActivated(boolean)
23706      *
23707      * @param activated The new activated state
23708      */
dispatchSetActivated(boolean activated)23709     protected void dispatchSetActivated(boolean activated) {
23710     }
23711 
23712     /**
23713      * Indicates the activation state of this view.
23714      *
23715      * @return true if the view is activated, false otherwise
23716      */
23717     @ViewDebug.ExportedProperty
23718     @InspectableProperty(hasAttributeId = false)
isActivated()23719     public boolean isActivated() {
23720         return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
23721     }
23722 
23723     /**
23724      * Returns the ViewTreeObserver for this view's hierarchy. The view tree
23725      * observer can be used to get notifications when global events, like
23726      * layout, happen.
23727      *
23728      * The returned ViewTreeObserver observer is not guaranteed to remain
23729      * valid for the lifetime of this View. If the caller of this method keeps
23730      * a long-lived reference to ViewTreeObserver, it should always check for
23731      * the return value of {@link ViewTreeObserver#isAlive()}.
23732      *
23733      * @return The ViewTreeObserver for this view's hierarchy.
23734      */
getViewTreeObserver()23735     public ViewTreeObserver getViewTreeObserver() {
23736         if (mAttachInfo != null) {
23737             return mAttachInfo.mTreeObserver;
23738         }
23739         if (mFloatingTreeObserver == null) {
23740             mFloatingTreeObserver = new ViewTreeObserver(mContext);
23741         }
23742         return mFloatingTreeObserver;
23743     }
23744 
23745     /**
23746      * <p>Finds the topmost view in the current view hierarchy.</p>
23747      *
23748      * @return the topmost view containing this view
23749      */
getRootView()23750     public View getRootView() {
23751         if (mAttachInfo != null) {
23752             final View v = mAttachInfo.mRootView;
23753             if (v != null) {
23754                 return v;
23755             }
23756         }
23757 
23758         View parent = this;
23759 
23760         while (parent.mParent != null && parent.mParent instanceof View) {
23761             parent = (View) parent.mParent;
23762         }
23763 
23764         return parent;
23765     }
23766 
23767     /**
23768      * Transforms a motion event from view-local coordinates to on-screen
23769      * coordinates.
23770      *
23771      * @param ev the view-local motion event
23772      * @return false if the transformation could not be applied
23773      * @hide
23774      */
23775     @UnsupportedAppUsage
toGlobalMotionEvent(MotionEvent ev)23776     public boolean toGlobalMotionEvent(MotionEvent ev) {
23777         final AttachInfo info = mAttachInfo;
23778         if (info == null) {
23779             return false;
23780         }
23781 
23782         final Matrix m = info.mTmpMatrix;
23783         m.set(Matrix.IDENTITY_MATRIX);
23784         transformMatrixToGlobal(m);
23785         ev.transform(m);
23786         return true;
23787     }
23788 
23789     /**
23790      * Transforms a motion event from on-screen coordinates to view-local
23791      * coordinates.
23792      *
23793      * @param ev the on-screen motion event
23794      * @return false if the transformation could not be applied
23795      * @hide
23796      */
23797     @UnsupportedAppUsage
toLocalMotionEvent(MotionEvent ev)23798     public boolean toLocalMotionEvent(MotionEvent ev) {
23799         final AttachInfo info = mAttachInfo;
23800         if (info == null) {
23801             return false;
23802         }
23803 
23804         final Matrix m = info.mTmpMatrix;
23805         m.set(Matrix.IDENTITY_MATRIX);
23806         transformMatrixToLocal(m);
23807         ev.transform(m);
23808         return true;
23809     }
23810 
23811     /**
23812      * Modifies the input matrix such that it maps view-local coordinates to
23813      * on-screen coordinates.
23814      *
23815      * @param matrix input matrix to modify
23816      */
transformMatrixToGlobal(@onNull Matrix matrix)23817     public void transformMatrixToGlobal(@NonNull Matrix matrix) {
23818         final ViewParent parent = mParent;
23819         if (parent instanceof View) {
23820             final View vp = (View) parent;
23821             vp.transformMatrixToGlobal(matrix);
23822             matrix.preTranslate(-vp.mScrollX, -vp.mScrollY);
23823         } else if (parent instanceof ViewRootImpl) {
23824             final ViewRootImpl vr = (ViewRootImpl) parent;
23825             vr.transformMatrixToGlobal(matrix);
23826             matrix.preTranslate(0, -vr.mCurScrollY);
23827         }
23828 
23829         matrix.preTranslate(mLeft, mTop);
23830 
23831         if (!hasIdentityMatrix()) {
23832             matrix.preConcat(getMatrix());
23833         }
23834     }
23835 
23836     /**
23837      * Modifies the input matrix such that it maps on-screen coordinates to
23838      * view-local coordinates.
23839      *
23840      * @param matrix input matrix to modify
23841      */
transformMatrixToLocal(@onNull Matrix matrix)23842     public void transformMatrixToLocal(@NonNull Matrix matrix) {
23843         final ViewParent parent = mParent;
23844         if (parent instanceof View) {
23845             final View vp = (View) parent;
23846             vp.transformMatrixToLocal(matrix);
23847             matrix.postTranslate(vp.mScrollX, vp.mScrollY);
23848         } else if (parent instanceof ViewRootImpl) {
23849             final ViewRootImpl vr = (ViewRootImpl) parent;
23850             vr.transformMatrixToLocal(matrix);
23851             matrix.postTranslate(0, vr.mCurScrollY);
23852         }
23853 
23854         matrix.postTranslate(-mLeft, -mTop);
23855 
23856         if (!hasIdentityMatrix()) {
23857             matrix.postConcat(getInverseMatrix());
23858         }
23859     }
23860 
23861     /**
23862      * @hide
23863      */
23864     @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
23865             @ViewDebug.IntToString(from = 0, to = "x"),
23866             @ViewDebug.IntToString(from = 1, to = "y")
23867     })
23868     @UnsupportedAppUsage
getLocationOnScreen()23869     public int[] getLocationOnScreen() {
23870         int[] location = new int[2];
23871         getLocationOnScreen(location);
23872         return location;
23873     }
23874 
23875     /**
23876      * <p>Computes the coordinates of this view on the screen. The argument
23877      * must be an array of two integers. After the method returns, the array
23878      * contains the x and y location in that order.</p>
23879      *
23880      * @param outLocation an array of two integers in which to hold the coordinates
23881      */
getLocationOnScreen(@ize2) int[] outLocation)23882     public void getLocationOnScreen(@Size(2) int[] outLocation) {
23883         getLocationInWindow(outLocation);
23884 
23885         final AttachInfo info = mAttachInfo;
23886         if (info != null) {
23887             outLocation[0] += info.mWindowLeft;
23888             outLocation[1] += info.mWindowTop;
23889         }
23890     }
23891 
23892     /**
23893      * <p>Computes the coordinates of this view in its window. The argument
23894      * must be an array of two integers. After the method returns, the array
23895      * contains the x and y location in that order.</p>
23896      *
23897      * @param outLocation an array of two integers in which to hold the coordinates
23898      */
getLocationInWindow(@ize2) int[] outLocation)23899     public void getLocationInWindow(@Size(2) int[] outLocation) {
23900         if (outLocation == null || outLocation.length < 2) {
23901             throw new IllegalArgumentException("outLocation must be an array of two integers");
23902         }
23903 
23904         outLocation[0] = 0;
23905         outLocation[1] = 0;
23906 
23907         transformFromViewToWindowSpace(outLocation);
23908     }
23909 
23910     /** @hide */
transformFromViewToWindowSpace(@ize2) int[] inOutLocation)23911     public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
23912         if (inOutLocation == null || inOutLocation.length < 2) {
23913             throw new IllegalArgumentException("inOutLocation must be an array of two integers");
23914         }
23915 
23916         if (mAttachInfo == null) {
23917             // When the view is not attached to a window, this method does not make sense
23918             inOutLocation[0] = inOutLocation[1] = 0;
23919             return;
23920         }
23921 
23922         float position[] = mAttachInfo.mTmpTransformLocation;
23923         position[0] = inOutLocation[0];
23924         position[1] = inOutLocation[1];
23925 
23926         if (!hasIdentityMatrix()) {
23927             getMatrix().mapPoints(position);
23928         }
23929 
23930         position[0] += mLeft;
23931         position[1] += mTop;
23932 
23933         ViewParent viewParent = mParent;
23934         while (viewParent instanceof View) {
23935             final View view = (View) viewParent;
23936 
23937             position[0] -= view.mScrollX;
23938             position[1] -= view.mScrollY;
23939 
23940             if (!view.hasIdentityMatrix()) {
23941                 view.getMatrix().mapPoints(position);
23942             }
23943 
23944             position[0] += view.mLeft;
23945             position[1] += view.mTop;
23946 
23947             viewParent = view.mParent;
23948          }
23949 
23950         if (viewParent instanceof ViewRootImpl) {
23951             // *cough*
23952             final ViewRootImpl vr = (ViewRootImpl) viewParent;
23953             position[1] -= vr.mCurScrollY;
23954         }
23955 
23956         inOutLocation[0] = Math.round(position[0]);
23957         inOutLocation[1] = Math.round(position[1]);
23958     }
23959 
23960     /**
23961      * @param id the id of the view to be found
23962      * @return the view of the specified id, null if cannot be found
23963      * @hide
23964      */
findViewTraversal(@dRes int id)23965     protected <T extends View> T findViewTraversal(@IdRes int id) {
23966         if (id == mID) {
23967             return (T) this;
23968         }
23969         return null;
23970     }
23971 
23972     /**
23973      * @param tag the tag of the view to be found
23974      * @return the view of specified tag, null if cannot be found
23975      * @hide
23976      */
findViewWithTagTraversal(Object tag)23977     protected <T extends View> T findViewWithTagTraversal(Object tag) {
23978         if (tag != null && tag.equals(mTag)) {
23979             return (T) this;
23980         }
23981         return null;
23982     }
23983 
23984     /**
23985      * @param predicate The predicate to evaluate.
23986      * @param childToSkip If not null, ignores this child during the recursive traversal.
23987      * @return The first view that matches the predicate or null.
23988      * @hide
23989      */
findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip)23990     protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
23991             View childToSkip) {
23992         if (predicate.test(this)) {
23993             return (T) this;
23994         }
23995         return null;
23996     }
23997 
23998     /**
23999      * Finds the first descendant view with the given ID, the view itself if
24000      * the ID matches {@link #getId()}, or {@code null} if the ID is invalid
24001      * (< 0) or there is no matching view in the hierarchy.
24002      * <p>
24003      * <strong>Note:</strong> In most cases -- depending on compiler support --
24004      * the resulting view is automatically cast to the target class type. If
24005      * the target class type is unconstrained, an explicit cast may be
24006      * necessary.
24007      *
24008      * @param id the ID to search for
24009      * @return a view with given ID if found, or {@code null} otherwise
24010      * @see View#requireViewById(int)
24011      */
24012     @Nullable
findViewById(@dRes int id)24013     public final <T extends View> T findViewById(@IdRes int id) {
24014         if (id == NO_ID) {
24015             return null;
24016         }
24017         return findViewTraversal(id);
24018     }
24019 
24020     /**
24021      * Finds the first descendant view with the given ID, the view itself if the ID matches
24022      * {@link #getId()}, or throws an IllegalArgumentException if the ID is invalid or there is no
24023      * matching view in the hierarchy.
24024      * <p>
24025      * <strong>Note:</strong> In most cases -- depending on compiler support --
24026      * the resulting view is automatically cast to the target class type. If
24027      * the target class type is unconstrained, an explicit cast may be
24028      * necessary.
24029      *
24030      * @param id the ID to search for
24031      * @return a view with given ID
24032      * @see View#findViewById(int)
24033      */
24034     @NonNull
requireViewById(@dRes int id)24035     public final <T extends View> T requireViewById(@IdRes int id) {
24036         T view = findViewById(id);
24037         if (view == null) {
24038             throw new IllegalArgumentException("ID does not reference a View inside this View");
24039         }
24040         return view;
24041     }
24042 
24043     /**
24044      * Performs the traversal to find a view by its unique and stable accessibility id.
24045      *
24046      * <strong>Note:</strong>This method does not stop at the root namespace
24047      * boundary since the user can touch the screen at an arbitrary location
24048      * potentially crossing the root namespace boundary which will send an
24049      * accessibility event to accessibility services and they should be able
24050      * to obtain the event source. Also accessibility ids are guaranteed to be
24051      * unique in the window.
24052      *
24053      * @param accessibilityId The accessibility id.
24054      * @return The found view.
24055      * @hide
24056      */
findViewByAccessibilityIdTraversal(int accessibilityId)24057     public <T extends View> T findViewByAccessibilityIdTraversal(int accessibilityId) {
24058         if (getAccessibilityViewId() == accessibilityId) {
24059             return (T) this;
24060         }
24061         return null;
24062     }
24063 
24064     /**
24065      * Performs the traversal to find a view by its autofill id.
24066      *
24067      * <strong>Note:</strong>This method does not stop at the root namespace
24068      * boundary.
24069      *
24070      * @param autofillId The autofill id.
24071      * @return The found view.
24072      * @hide
24073      */
findViewByAutofillIdTraversal(int autofillId)24074     public <T extends View> T findViewByAutofillIdTraversal(int autofillId) {
24075         if (getAutofillViewId() == autofillId) {
24076             return (T) this;
24077         }
24078         return null;
24079     }
24080 
24081     /**
24082      * Look for a child view with the given tag.  If this view has the given
24083      * tag, return this view.
24084      *
24085      * @param tag The tag to search for, using "tag.equals(getTag())".
24086      * @return The View that has the given tag in the hierarchy or null
24087      */
findViewWithTag(Object tag)24088     public final <T extends View> T findViewWithTag(Object tag) {
24089         if (tag == null) {
24090             return null;
24091         }
24092         return findViewWithTagTraversal(tag);
24093     }
24094 
24095     /**
24096      * Look for a child view that matches the specified predicate.
24097      * If this view matches the predicate, return this view.
24098      *
24099      * @param predicate The predicate to evaluate.
24100      * @return The first view that matches the predicate or null.
24101      * @hide
24102      */
findViewByPredicate(Predicate<View> predicate)24103     public final <T extends View> T findViewByPredicate(Predicate<View> predicate) {
24104         return findViewByPredicateTraversal(predicate, null);
24105     }
24106 
24107     /**
24108      * Look for a child view that matches the specified predicate,
24109      * starting with the specified view and its descendents and then
24110      * recusively searching the ancestors and siblings of that view
24111      * until this view is reached.
24112      *
24113      * This method is useful in cases where the predicate does not match
24114      * a single unique view (perhaps multiple views use the same id)
24115      * and we are trying to find the view that is "closest" in scope to the
24116      * starting view.
24117      *
24118      * @param start The view to start from.
24119      * @param predicate The predicate to evaluate.
24120      * @return The first view that matches the predicate or null.
24121      * @hide
24122      */
findViewByPredicateInsideOut( View start, Predicate<View> predicate)24123     public final <T extends View> T findViewByPredicateInsideOut(
24124             View start, Predicate<View> predicate) {
24125         View childToSkip = null;
24126         for (;;) {
24127             T view = start.findViewByPredicateTraversal(predicate, childToSkip);
24128             if (view != null || start == this) {
24129                 return view;
24130             }
24131 
24132             ViewParent parent = start.getParent();
24133             if (parent == null || !(parent instanceof View)) {
24134                 return null;
24135             }
24136 
24137             childToSkip = start;
24138             start = (View) parent;
24139         }
24140     }
24141 
24142     /**
24143      * Sets the identifier for this view. The identifier does not have to be
24144      * unique in this view's hierarchy. The identifier should be a positive
24145      * number.
24146      *
24147      * @see #NO_ID
24148      * @see #getId()
24149      * @see #findViewById(int)
24150      *
24151      * @param id a number used to identify the view
24152      *
24153      * @attr ref android.R.styleable#View_id
24154      */
setId(@dRes int id)24155     public void setId(@IdRes int id) {
24156         mID = id;
24157         if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
24158             mID = generateViewId();
24159         }
24160     }
24161 
24162     /**
24163      * {@hide}
24164      *
24165      * @param isRoot true if the view belongs to the root namespace, false
24166      *        otherwise
24167      */
24168     @TestApi
setIsRootNamespace(boolean isRoot)24169     public void setIsRootNamespace(boolean isRoot) {
24170         if (isRoot) {
24171             mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
24172         } else {
24173             mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
24174         }
24175     }
24176 
24177     /**
24178      * {@hide}
24179      *
24180      * @return true if the view belongs to the root namespace, false otherwise
24181      */
24182     @UnsupportedAppUsage
isRootNamespace()24183     public boolean isRootNamespace() {
24184         return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
24185     }
24186 
24187     /**
24188      * Returns this view's identifier.
24189      *
24190      * @return a positive integer used to identify the view or {@link #NO_ID}
24191      *         if the view has no ID
24192      *
24193      * @see #setId(int)
24194      * @see #findViewById(int)
24195      * @attr ref android.R.styleable#View_id
24196      */
24197     @IdRes
24198     @ViewDebug.CapturedViewProperty
24199     @InspectableProperty
getId()24200     public int getId() {
24201         return mID;
24202     }
24203 
24204     /**
24205      * Get the identifier used for this view by the drawing system.
24206      *
24207      * @see RenderNode#getUniqueId()
24208      * @return A long that uniquely identifies this view's drawing component
24209      */
getUniqueDrawingId()24210     public long getUniqueDrawingId() {
24211         return mRenderNode.getUniqueId();
24212     }
24213 
24214     /**
24215      * Returns this view's tag.
24216      *
24217      * @return the Object stored in this view as a tag, or {@code null} if not
24218      *         set
24219      *
24220      * @see #setTag(Object)
24221      * @see #getTag(int)
24222      */
24223     @ViewDebug.ExportedProperty
24224     @InspectableProperty
getTag()24225     public Object getTag() {
24226         return mTag;
24227     }
24228 
24229     /**
24230      * Sets the tag associated with this view. A tag can be used to mark
24231      * a view in its hierarchy and does not have to be unique within the
24232      * hierarchy. Tags can also be used to store data within a view without
24233      * resorting to another data structure.
24234      *
24235      * @param tag an Object to tag the view with
24236      *
24237      * @see #getTag()
24238      * @see #setTag(int, Object)
24239      */
setTag(final Object tag)24240     public void setTag(final Object tag) {
24241         mTag = tag;
24242     }
24243 
24244     /**
24245      * Returns the tag associated with this view and the specified key.
24246      *
24247      * @param key The key identifying the tag
24248      *
24249      * @return the Object stored in this view as a tag, or {@code null} if not
24250      *         set
24251      *
24252      * @see #setTag(int, Object)
24253      * @see #getTag()
24254      */
getTag(int key)24255     public Object getTag(int key) {
24256         if (mKeyedTags != null) return mKeyedTags.get(key);
24257         return null;
24258     }
24259 
24260     /**
24261      * Sets a tag associated with this view and a key. A tag can be used
24262      * to mark a view in its hierarchy and does not have to be unique within
24263      * the hierarchy. Tags can also be used to store data within a view
24264      * without resorting to another data structure.
24265      *
24266      * The specified key should be an id declared in the resources of the
24267      * application to ensure it is unique (see the <a
24268      * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
24269      * Keys identified as belonging to
24270      * the Android framework or not associated with any package will cause
24271      * an {@link IllegalArgumentException} to be thrown.
24272      *
24273      * @param key The key identifying the tag
24274      * @param tag An Object to tag the view with
24275      *
24276      * @throws IllegalArgumentException If they specified key is not valid
24277      *
24278      * @see #setTag(Object)
24279      * @see #getTag(int)
24280      */
setTag(int key, final Object tag)24281     public void setTag(int key, final Object tag) {
24282         // If the package id is 0x00 or 0x01, it's either an undefined package
24283         // or a framework id
24284         if ((key >>> 24) < 2) {
24285             throw new IllegalArgumentException("The key must be an application-specific "
24286                     + "resource id.");
24287         }
24288 
24289         setKeyedTag(key, tag);
24290     }
24291 
24292     /**
24293      * Variation of {@link #setTag(int, Object)} that enforces the key to be a
24294      * framework id.
24295      *
24296      * @hide
24297      */
24298     @UnsupportedAppUsage
setTagInternal(int key, Object tag)24299     public void setTagInternal(int key, Object tag) {
24300         if ((key >>> 24) != 0x1) {
24301             throw new IllegalArgumentException("The key must be a framework-specific "
24302                     + "resource id.");
24303         }
24304 
24305         setKeyedTag(key, tag);
24306     }
24307 
setKeyedTag(int key, Object tag)24308     private void setKeyedTag(int key, Object tag) {
24309         if (mKeyedTags == null) {
24310             mKeyedTags = new SparseArray<Object>(2);
24311         }
24312 
24313         mKeyedTags.put(key, tag);
24314     }
24315 
24316     /**
24317      * Prints information about this view in the log output, with the tag
24318      * {@link #VIEW_LOG_TAG}.
24319      *
24320      * @hide
24321      */
24322     @UnsupportedAppUsage
debug()24323     public void debug() {
24324         debug(0);
24325     }
24326 
24327     /**
24328      * Prints information about this view in the log output, with the tag
24329      * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
24330      * indentation defined by the <code>depth</code>.
24331      *
24332      * @param depth the indentation level
24333      *
24334      * @hide
24335      */
24336     @UnsupportedAppUsage
debug(int depth)24337     protected void debug(int depth) {
24338         String output = debugIndent(depth - 1);
24339 
24340         output += "+ " + this;
24341         int id = getId();
24342         if (id != -1) {
24343             output += " (id=" + id + ")";
24344         }
24345         Object tag = getTag();
24346         if (tag != null) {
24347             output += " (tag=" + tag + ")";
24348         }
24349         Log.d(VIEW_LOG_TAG, output);
24350 
24351         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
24352             output = debugIndent(depth) + " FOCUSED";
24353             Log.d(VIEW_LOG_TAG, output);
24354         }
24355 
24356         output = debugIndent(depth);
24357         output += "frame={" + mLeft + ", " + mTop + ", " + mRight
24358                 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
24359                 + "} ";
24360         Log.d(VIEW_LOG_TAG, output);
24361 
24362         if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
24363                 || mPaddingBottom != 0) {
24364             output = debugIndent(depth);
24365             output += "padding={" + mPaddingLeft + ", " + mPaddingTop
24366                     + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
24367             Log.d(VIEW_LOG_TAG, output);
24368         }
24369 
24370         output = debugIndent(depth);
24371         output += "mMeasureWidth=" + mMeasuredWidth +
24372                 " mMeasureHeight=" + mMeasuredHeight;
24373         Log.d(VIEW_LOG_TAG, output);
24374 
24375         output = debugIndent(depth);
24376         if (mLayoutParams == null) {
24377             output += "BAD! no layout params";
24378         } else {
24379             output = mLayoutParams.debug(output);
24380         }
24381         Log.d(VIEW_LOG_TAG, output);
24382 
24383         output = debugIndent(depth);
24384         output += "flags={";
24385         output += View.printFlags(mViewFlags);
24386         output += "}";
24387         Log.d(VIEW_LOG_TAG, output);
24388 
24389         output = debugIndent(depth);
24390         output += "privateFlags={";
24391         output += View.printPrivateFlags(mPrivateFlags);
24392         output += "}";
24393         Log.d(VIEW_LOG_TAG, output);
24394     }
24395 
24396     /**
24397      * Creates a string of whitespaces used for indentation.
24398      *
24399      * @param depth the indentation level
24400      * @return a String containing (depth * 2 + 3) * 2 white spaces
24401      *
24402      * @hide
24403      */
debugIndent(int depth)24404     protected static String debugIndent(int depth) {
24405         StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
24406         for (int i = 0; i < (depth * 2) + 3; i++) {
24407             spaces.append(' ').append(' ');
24408         }
24409         return spaces.toString();
24410     }
24411 
24412     /**
24413      * <p>Return the offset of the widget's text baseline from the widget's top
24414      * boundary. If this widget does not support baseline alignment, this
24415      * method returns -1. </p>
24416      *
24417      * @return the offset of the baseline within the widget's bounds or -1
24418      *         if baseline alignment is not supported
24419      */
24420     @ViewDebug.ExportedProperty(category = "layout")
24421     @InspectableProperty
getBaseline()24422     public int getBaseline() {
24423         return -1;
24424     }
24425 
24426     /**
24427      * Returns whether the view hierarchy is currently undergoing a layout pass. This
24428      * information is useful to avoid situations such as calling {@link #requestLayout()} during
24429      * a layout pass.
24430      *
24431      * @return whether the view hierarchy is currently undergoing a layout pass
24432      */
isInLayout()24433     public boolean isInLayout() {
24434         ViewRootImpl viewRoot = getViewRootImpl();
24435         return (viewRoot != null && viewRoot.isInLayout());
24436     }
24437 
24438     /**
24439      * Call this when something has changed which has invalidated the
24440      * layout of this view. This will schedule a layout pass of the view
24441      * tree. This should not be called while the view hierarchy is currently in a layout
24442      * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
24443      * end of the current layout pass (and then layout will run again) or after the current
24444      * frame is drawn and the next layout occurs.
24445      *
24446      * <p>Subclasses which override this method should call the superclass method to
24447      * handle possible request-during-layout errors correctly.</p>
24448      */
24449     @CallSuper
requestLayout()24450     public void requestLayout() {
24451         if (mMeasureCache != null) mMeasureCache.clear();
24452 
24453         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
24454             // Only trigger request-during-layout logic if this is the view requesting it,
24455             // not the views in its parent hierarchy
24456             ViewRootImpl viewRoot = getViewRootImpl();
24457             if (viewRoot != null && viewRoot.isInLayout()) {
24458                 if (!viewRoot.requestLayoutDuringLayout(this)) {
24459                     return;
24460                 }
24461             }
24462             mAttachInfo.mViewRequestingLayout = this;
24463         }
24464 
24465         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
24466         mPrivateFlags |= PFLAG_INVALIDATED;
24467 
24468         if (mParent != null && !mParent.isLayoutRequested()) {
24469             mParent.requestLayout();
24470         }
24471         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
24472             mAttachInfo.mViewRequestingLayout = null;
24473         }
24474     }
24475 
24476     /**
24477      * Forces this view to be laid out during the next layout pass.
24478      * This method does not call requestLayout() or forceLayout()
24479      * on the parent.
24480      */
forceLayout()24481     public void forceLayout() {
24482         if (mMeasureCache != null) mMeasureCache.clear();
24483 
24484         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
24485         mPrivateFlags |= PFLAG_INVALIDATED;
24486     }
24487 
24488     /**
24489      * <p>
24490      * This is called to find out how big a view should be. The parent
24491      * supplies constraint information in the width and height parameters.
24492      * </p>
24493      *
24494      * <p>
24495      * The actual measurement work of a view is performed in
24496      * {@link #onMeasure(int, int)}, called by this method. Therefore, only
24497      * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
24498      * </p>
24499      *
24500      *
24501      * @param widthMeasureSpec Horizontal space requirements as imposed by the
24502      *        parent
24503      * @param heightMeasureSpec Vertical space requirements as imposed by the
24504      *        parent
24505      *
24506      * @see #onMeasure(int, int)
24507      */
measure(int widthMeasureSpec, int heightMeasureSpec)24508     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
24509         boolean optical = isLayoutModeOptical(this);
24510         if (optical != isLayoutModeOptical(mParent)) {
24511             Insets insets = getOpticalInsets();
24512             int oWidth  = insets.left + insets.right;
24513             int oHeight = insets.top  + insets.bottom;
24514             widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
24515             heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
24516         }
24517 
24518         // Suppress sign extension for the low bytes
24519         long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
24520         if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
24521 
24522         final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
24523 
24524         // Optimize layout by avoiding an extra EXACTLY pass when the view is
24525         // already measured as the correct size. In API 23 and below, this
24526         // extra pass is required to make LinearLayout re-distribute weight.
24527         final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
24528                 || heightMeasureSpec != mOldHeightMeasureSpec;
24529         final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
24530                 && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
24531         final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
24532                 && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
24533         final boolean needsLayout = specChanged
24534                 && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
24535 
24536         if (forceLayout || needsLayout) {
24537             // first clears the measured dimension flag
24538             mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
24539 
24540             resolveRtlPropertiesIfNeeded();
24541 
24542             int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
24543             if (cacheIndex < 0 || sIgnoreMeasureCache) {
24544                 // measure ourselves, this should set the measured dimension flag back
24545                 onMeasure(widthMeasureSpec, heightMeasureSpec);
24546                 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
24547             } else {
24548                 long value = mMeasureCache.valueAt(cacheIndex);
24549                 // Casting a long to int drops the high 32 bits, no mask needed
24550                 setMeasuredDimensionRaw((int) (value >> 32), (int) value);
24551                 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
24552             }
24553 
24554             // flag not set, setMeasuredDimension() was not invoked, we raise
24555             // an exception to warn the developer
24556             if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
24557                 throw new IllegalStateException("View with id " + getId() + ": "
24558                         + getClass().getName() + "#onMeasure() did not set the"
24559                         + " measured dimension by calling"
24560                         + " setMeasuredDimension()");
24561             }
24562 
24563             mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
24564         }
24565 
24566         mOldWidthMeasureSpec = widthMeasureSpec;
24567         mOldHeightMeasureSpec = heightMeasureSpec;
24568 
24569         mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
24570                 (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
24571     }
24572 
24573     /**
24574      * <p>
24575      * Measure the view and its content to determine the measured width and the
24576      * measured height. This method is invoked by {@link #measure(int, int)} and
24577      * should be overridden by subclasses to provide accurate and efficient
24578      * measurement of their contents.
24579      * </p>
24580      *
24581      * <p>
24582      * <strong>CONTRACT:</strong> When overriding this method, you
24583      * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
24584      * measured width and height of this view. Failure to do so will trigger an
24585      * <code>IllegalStateException</code>, thrown by
24586      * {@link #measure(int, int)}. Calling the superclass'
24587      * {@link #onMeasure(int, int)} is a valid use.
24588      * </p>
24589      *
24590      * <p>
24591      * The base class implementation of measure defaults to the background size,
24592      * unless a larger size is allowed by the MeasureSpec. Subclasses should
24593      * override {@link #onMeasure(int, int)} to provide better measurements of
24594      * their content.
24595      * </p>
24596      *
24597      * <p>
24598      * If this method is overridden, it is the subclass's responsibility to make
24599      * sure the measured height and width are at least the view's minimum height
24600      * and width ({@link #getSuggestedMinimumHeight()} and
24601      * {@link #getSuggestedMinimumWidth()}).
24602      * </p>
24603      *
24604      * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
24605      *                         The requirements are encoded with
24606      *                         {@link android.view.View.MeasureSpec}.
24607      * @param heightMeasureSpec vertical space requirements as imposed by the parent.
24608      *                         The requirements are encoded with
24609      *                         {@link android.view.View.MeasureSpec}.
24610      *
24611      * @see #getMeasuredWidth()
24612      * @see #getMeasuredHeight()
24613      * @see #setMeasuredDimension(int, int)
24614      * @see #getSuggestedMinimumHeight()
24615      * @see #getSuggestedMinimumWidth()
24616      * @see android.view.View.MeasureSpec#getMode(int)
24617      * @see android.view.View.MeasureSpec#getSize(int)
24618      */
onMeasure(int widthMeasureSpec, int heightMeasureSpec)24619     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
24620         setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
24621                 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
24622     }
24623 
24624     /**
24625      * <p>This method must be called by {@link #onMeasure(int, int)} to store the
24626      * measured width and measured height. Failing to do so will trigger an
24627      * exception at measurement time.</p>
24628      *
24629      * @param measuredWidth The measured width of this view.  May be a complex
24630      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
24631      * {@link #MEASURED_STATE_TOO_SMALL}.
24632      * @param measuredHeight The measured height of this view.  May be a complex
24633      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
24634      * {@link #MEASURED_STATE_TOO_SMALL}.
24635      */
setMeasuredDimension(int measuredWidth, int measuredHeight)24636     protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
24637         boolean optical = isLayoutModeOptical(this);
24638         if (optical != isLayoutModeOptical(mParent)) {
24639             Insets insets = getOpticalInsets();
24640             int opticalWidth  = insets.left + insets.right;
24641             int opticalHeight = insets.top  + insets.bottom;
24642 
24643             measuredWidth  += optical ? opticalWidth  : -opticalWidth;
24644             measuredHeight += optical ? opticalHeight : -opticalHeight;
24645         }
24646         setMeasuredDimensionRaw(measuredWidth, measuredHeight);
24647     }
24648 
24649     /**
24650      * Sets the measured dimension without extra processing for things like optical bounds.
24651      * Useful for reapplying consistent values that have already been cooked with adjustments
24652      * for optical bounds, etc. such as those from the measurement cache.
24653      *
24654      * @param measuredWidth The measured width of this view.  May be a complex
24655      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
24656      * {@link #MEASURED_STATE_TOO_SMALL}.
24657      * @param measuredHeight The measured height of this view.  May be a complex
24658      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
24659      * {@link #MEASURED_STATE_TOO_SMALL}.
24660      */
setMeasuredDimensionRaw(int measuredWidth, int measuredHeight)24661     private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
24662         mMeasuredWidth = measuredWidth;
24663         mMeasuredHeight = measuredHeight;
24664 
24665         mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
24666     }
24667 
24668     /**
24669      * Merge two states as returned by {@link #getMeasuredState()}.
24670      * @param curState The current state as returned from a view or the result
24671      * of combining multiple views.
24672      * @param newState The new view state to combine.
24673      * @return Returns a new integer reflecting the combination of the two
24674      * states.
24675      */
combineMeasuredStates(int curState, int newState)24676     public static int combineMeasuredStates(int curState, int newState) {
24677         return curState | newState;
24678     }
24679 
24680     /**
24681      * Version of {@link #resolveSizeAndState(int, int, int)}
24682      * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
24683      */
resolveSize(int size, int measureSpec)24684     public static int resolveSize(int size, int measureSpec) {
24685         return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
24686     }
24687 
24688     /**
24689      * Utility to reconcile a desired size and state, with constraints imposed
24690      * by a MeasureSpec. Will take the desired size, unless a different size
24691      * is imposed by the constraints. The returned value is a compound integer,
24692      * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
24693      * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
24694      * resulting size is smaller than the size the view wants to be.
24695      *
24696      * @param size How big the view wants to be.
24697      * @param measureSpec Constraints imposed by the parent.
24698      * @param childMeasuredState Size information bit mask for the view's
24699      *                           children.
24700      * @return Size information bit mask as defined by
24701      *         {@link #MEASURED_SIZE_MASK} and
24702      *         {@link #MEASURED_STATE_TOO_SMALL}.
24703      */
resolveSizeAndState(int size, int measureSpec, int childMeasuredState)24704     public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
24705         final int specMode = MeasureSpec.getMode(measureSpec);
24706         final int specSize = MeasureSpec.getSize(measureSpec);
24707         final int result;
24708         switch (specMode) {
24709             case MeasureSpec.AT_MOST:
24710                 if (specSize < size) {
24711                     result = specSize | MEASURED_STATE_TOO_SMALL;
24712                 } else {
24713                     result = size;
24714                 }
24715                 break;
24716             case MeasureSpec.EXACTLY:
24717                 result = specSize;
24718                 break;
24719             case MeasureSpec.UNSPECIFIED:
24720             default:
24721                 result = size;
24722         }
24723         return result | (childMeasuredState & MEASURED_STATE_MASK);
24724     }
24725 
24726     /**
24727      * Utility to return a default size. Uses the supplied size if the
24728      * MeasureSpec imposed no constraints. Will get larger if allowed
24729      * by the MeasureSpec.
24730      *
24731      * @param size Default size for this view
24732      * @param measureSpec Constraints imposed by the parent
24733      * @return The size this view should be.
24734      */
getDefaultSize(int size, int measureSpec)24735     public static int getDefaultSize(int size, int measureSpec) {
24736         int result = size;
24737         int specMode = MeasureSpec.getMode(measureSpec);
24738         int specSize = MeasureSpec.getSize(measureSpec);
24739 
24740         switch (specMode) {
24741         case MeasureSpec.UNSPECIFIED:
24742             result = size;
24743             break;
24744         case MeasureSpec.AT_MOST:
24745         case MeasureSpec.EXACTLY:
24746             result = specSize;
24747             break;
24748         }
24749         return result;
24750     }
24751 
24752     /**
24753      * Returns the suggested minimum height that the view should use. This
24754      * returns the maximum of the view's minimum height
24755      * and the background's minimum height
24756      * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
24757      * <p>
24758      * When being used in {@link #onMeasure(int, int)}, the caller should still
24759      * ensure the returned height is within the requirements of the parent.
24760      *
24761      * @return The suggested minimum height of the view.
24762      */
getSuggestedMinimumHeight()24763     protected int getSuggestedMinimumHeight() {
24764         return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
24765 
24766     }
24767 
24768     /**
24769      * Returns the suggested minimum width that the view should use. This
24770      * returns the maximum of the view's minimum width
24771      * and the background's minimum width
24772      *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
24773      * <p>
24774      * When being used in {@link #onMeasure(int, int)}, the caller should still
24775      * ensure the returned width is within the requirements of the parent.
24776      *
24777      * @return The suggested minimum width of the view.
24778      */
getSuggestedMinimumWidth()24779     protected int getSuggestedMinimumWidth() {
24780         return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
24781     }
24782 
24783     /**
24784      * Returns the minimum height of the view.
24785      *
24786      * @return the minimum height the view will try to be, in pixels
24787      *
24788      * @see #setMinimumHeight(int)
24789      *
24790      * @attr ref android.R.styleable#View_minHeight
24791      */
24792     @InspectableProperty(name = "minHeight")
getMinimumHeight()24793     public int getMinimumHeight() {
24794         return mMinHeight;
24795     }
24796 
24797     /**
24798      * Sets the minimum height of the view. It is not guaranteed the view will
24799      * be able to achieve this minimum height (for example, if its parent layout
24800      * constrains it with less available height).
24801      *
24802      * @param minHeight The minimum height the view will try to be, in pixels
24803      *
24804      * @see #getMinimumHeight()
24805      *
24806      * @attr ref android.R.styleable#View_minHeight
24807      */
24808     @RemotableViewMethod
setMinimumHeight(int minHeight)24809     public void setMinimumHeight(int minHeight) {
24810         mMinHeight = minHeight;
24811         requestLayout();
24812     }
24813 
24814     /**
24815      * Returns the minimum width of the view.
24816      *
24817      * @return the minimum width the view will try to be, in pixels
24818      *
24819      * @see #setMinimumWidth(int)
24820      *
24821      * @attr ref android.R.styleable#View_minWidth
24822      */
24823     @InspectableProperty(name = "minWidth")
getMinimumWidth()24824     public int getMinimumWidth() {
24825         return mMinWidth;
24826     }
24827 
24828     /**
24829      * Sets the minimum width of the view. It is not guaranteed the view will
24830      * be able to achieve this minimum width (for example, if its parent layout
24831      * constrains it with less available width).
24832      *
24833      * @param minWidth The minimum width the view will try to be, in pixels
24834      *
24835      * @see #getMinimumWidth()
24836      *
24837      * @attr ref android.R.styleable#View_minWidth
24838      */
setMinimumWidth(int minWidth)24839     public void setMinimumWidth(int minWidth) {
24840         mMinWidth = minWidth;
24841         requestLayout();
24842 
24843     }
24844 
24845     /**
24846      * Get the animation currently associated with this view.
24847      *
24848      * @return The animation that is currently playing or
24849      *         scheduled to play for this view.
24850      */
getAnimation()24851     public Animation getAnimation() {
24852         return mCurrentAnimation;
24853     }
24854 
24855     /**
24856      * Start the specified animation now.
24857      *
24858      * @param animation the animation to start now
24859      */
startAnimation(Animation animation)24860     public void startAnimation(Animation animation) {
24861         animation.setStartTime(Animation.START_ON_FIRST_FRAME);
24862         setAnimation(animation);
24863         invalidateParentCaches();
24864         invalidate(true);
24865     }
24866 
24867     /**
24868      * Cancels any animations for this view.
24869      */
clearAnimation()24870     public void clearAnimation() {
24871         if (mCurrentAnimation != null) {
24872             mCurrentAnimation.detach();
24873         }
24874         mCurrentAnimation = null;
24875         invalidateParentIfNeeded();
24876     }
24877 
24878     /**
24879      * Sets the next animation to play for this view.
24880      * If you want the animation to play immediately, use
24881      * {@link #startAnimation(android.view.animation.Animation)} instead.
24882      * This method provides allows fine-grained
24883      * control over the start time and invalidation, but you
24884      * must make sure that 1) the animation has a start time set, and
24885      * 2) the view's parent (which controls animations on its children)
24886      * will be invalidated when the animation is supposed to
24887      * start.
24888      *
24889      * @param animation The next animation, or null.
24890      */
setAnimation(Animation animation)24891     public void setAnimation(Animation animation) {
24892         mCurrentAnimation = animation;
24893 
24894         if (animation != null) {
24895             // If the screen is off assume the animation start time is now instead of
24896             // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
24897             // would cause the animation to start when the screen turns back on
24898             if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
24899                     && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
24900                 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
24901             }
24902             animation.reset();
24903         }
24904     }
24905 
24906     /**
24907      * Invoked by a parent ViewGroup to notify the start of the animation
24908      * currently associated with this view. If you override this method,
24909      * always call super.onAnimationStart();
24910      *
24911      * @see #setAnimation(android.view.animation.Animation)
24912      * @see #getAnimation()
24913      */
24914     @CallSuper
onAnimationStart()24915     protected void onAnimationStart() {
24916         mPrivateFlags |= PFLAG_ANIMATION_STARTED;
24917     }
24918 
24919     /**
24920      * Invoked by a parent ViewGroup to notify the end of the animation
24921      * currently associated with this view. If you override this method,
24922      * always call super.onAnimationEnd();
24923      *
24924      * @see #setAnimation(android.view.animation.Animation)
24925      * @see #getAnimation()
24926      */
24927     @CallSuper
onAnimationEnd()24928     protected void onAnimationEnd() {
24929         mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
24930     }
24931 
24932     /**
24933      * Invoked if there is a Transform that involves alpha. Subclass that can
24934      * draw themselves with the specified alpha should return true, and then
24935      * respect that alpha when their onDraw() is called. If this returns false
24936      * then the view may be redirected to draw into an offscreen buffer to
24937      * fulfill the request, which will look fine, but may be slower than if the
24938      * subclass handles it internally. The default implementation returns false.
24939      *
24940      * @param alpha The alpha (0..255) to apply to the view's drawing
24941      * @return true if the view can draw with the specified alpha.
24942      */
onSetAlpha(int alpha)24943     protected boolean onSetAlpha(int alpha) {
24944         return false;
24945     }
24946 
24947     /**
24948      * This is used by the RootView to perform an optimization when
24949      * the view hierarchy contains one or several SurfaceView.
24950      * SurfaceView is always considered transparent, but its children are not,
24951      * therefore all View objects remove themselves from the global transparent
24952      * region (passed as a parameter to this function).
24953      *
24954      * @param region The transparent region for this ViewAncestor (window).
24955      *
24956      * @return Returns true if the effective visibility of the view at this
24957      * point is opaque, regardless of the transparent region; returns false
24958      * if it is possible for underlying windows to be seen behind the view.
24959      *
24960      * {@hide}
24961      */
24962     @UnsupportedAppUsage
gatherTransparentRegion(Region region)24963     public boolean gatherTransparentRegion(Region region) {
24964         final AttachInfo attachInfo = mAttachInfo;
24965         if (region != null && attachInfo != null) {
24966             final int pflags = mPrivateFlags;
24967             if ((pflags & PFLAG_SKIP_DRAW) == 0) {
24968                 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
24969                 // remove it from the transparent region.
24970                 final int[] location = attachInfo.mTransparentLocation;
24971                 getLocationInWindow(location);
24972                 // When a view has Z value, then it will be better to leave some area below the view
24973                 // for drawing shadow. The shadow outset is proportional to the Z value. Note that
24974                 // the bottom part needs more offset than the left, top and right parts due to the
24975                 // spot light effects.
24976                 int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
24977                 region.op(location[0] - shadowOffset, location[1] - shadowOffset,
24978                         location[0] + mRight - mLeft + shadowOffset,
24979                         location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
24980             } else {
24981                 if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
24982                     // The SKIP_DRAW flag IS set and the background drawable exists, we remove
24983                     // the background drawable's non-transparent parts from this transparent region.
24984                     applyDrawableToTransparentRegion(mBackground, region);
24985                 }
24986                 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
24987                         && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
24988                     // Similarly, we remove the foreground drawable's non-transparent parts.
24989                     applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
24990                 }
24991                 if (mDefaultFocusHighlight != null
24992                         && mDefaultFocusHighlight.getOpacity() != PixelFormat.TRANSPARENT) {
24993                     // Similarly, we remove the default focus highlight's non-transparent parts.
24994                     applyDrawableToTransparentRegion(mDefaultFocusHighlight, region);
24995                 }
24996             }
24997         }
24998         return true;
24999     }
25000 
25001     /**
25002      * Play a sound effect for this view.
25003      *
25004      * <p>The framework will play sound effects for some built in actions, such as
25005      * clicking, but you may wish to play these effects in your widget,
25006      * for instance, for internal navigation.
25007      *
25008      * <p>The sound effect will only be played if sound effects are enabled by the user, and
25009      * {@link #isSoundEffectsEnabled()} is true.
25010      *
25011      * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
25012      */
playSoundEffect(int soundConstant)25013     public void playSoundEffect(int soundConstant) {
25014         if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
25015             return;
25016         }
25017         mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
25018     }
25019 
25020     /**
25021      * BZZZTT!!1!
25022      *
25023      * <p>Provide haptic feedback to the user for this view.
25024      *
25025      * <p>The framework will provide haptic feedback for some built in actions,
25026      * such as long presses, but you may wish to provide feedback for your
25027      * own widget.
25028      *
25029      * <p>The feedback will only be performed if
25030      * {@link #isHapticFeedbackEnabled()} is true.
25031      *
25032      * @param feedbackConstant One of the constants defined in
25033      * {@link HapticFeedbackConstants}
25034      */
performHapticFeedback(int feedbackConstant)25035     public boolean performHapticFeedback(int feedbackConstant) {
25036         return performHapticFeedback(feedbackConstant, 0);
25037     }
25038 
25039     /**
25040      * BZZZTT!!1!
25041      *
25042      * <p>Like {@link #performHapticFeedback(int)}, with additional options.
25043      *
25044      * @param feedbackConstant One of the constants defined in
25045      * {@link HapticFeedbackConstants}
25046      * @param flags Additional flags as per {@link HapticFeedbackConstants}.
25047      */
performHapticFeedback(int feedbackConstant, int flags)25048     public boolean performHapticFeedback(int feedbackConstant, int flags) {
25049         if (mAttachInfo == null) {
25050             return false;
25051         }
25052         //noinspection SimplifiableIfStatement
25053         if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
25054                 && !isHapticFeedbackEnabled()) {
25055             return false;
25056         }
25057         return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
25058                 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
25059     }
25060 
25061     /**
25062      * Request that the visibility of the status bar or other screen/window
25063      * decorations be changed.
25064      *
25065      * <p>This method is used to put the over device UI into temporary modes
25066      * where the user's attention is focused more on the application content,
25067      * by dimming or hiding surrounding system affordances.  This is typically
25068      * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
25069      * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
25070      * to be placed behind the action bar (and with these flags other system
25071      * affordances) so that smooth transitions between hiding and showing them
25072      * can be done.
25073      *
25074      * <p>Two representative examples of the use of system UI visibility is
25075      * implementing a content browsing application (like a magazine reader)
25076      * and a video playing application.
25077      *
25078      * <p>The first code shows a typical implementation of a View in a content
25079      * browsing application.  In this implementation, the application goes
25080      * into a content-oriented mode by hiding the status bar and action bar,
25081      * and putting the navigation elements into lights out mode.  The user can
25082      * then interact with content while in this mode.  Such an application should
25083      * provide an easy way for the user to toggle out of the mode (such as to
25084      * check information in the status bar or access notifications).  In the
25085      * implementation here, this is done simply by tapping on the content.
25086      *
25087      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
25088      *      content}
25089      *
25090      * <p>This second code sample shows a typical implementation of a View
25091      * in a video playing application.  In this situation, while the video is
25092      * playing the application would like to go into a complete full-screen mode,
25093      * to use as much of the display as possible for the video.  When in this state
25094      * the user can not interact with the application; the system intercepts
25095      * touching on the screen to pop the UI out of full screen mode.  See
25096      * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
25097      *
25098      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
25099      *      content}
25100      *
25101      * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
25102      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
25103      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
25104      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
25105      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
25106      */
setSystemUiVisibility(int visibility)25107     public void setSystemUiVisibility(int visibility) {
25108         if (visibility != mSystemUiVisibility) {
25109             mSystemUiVisibility = visibility;
25110             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
25111                 mParent.recomputeViewAttributes(this);
25112             }
25113         }
25114     }
25115 
25116     /**
25117      * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
25118      * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
25119      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
25120      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
25121      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
25122      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
25123      */
getSystemUiVisibility()25124     public int getSystemUiVisibility() {
25125         return mSystemUiVisibility;
25126     }
25127 
25128     /**
25129      * Returns the current system UI visibility that is currently set for
25130      * the entire window.  This is the combination of the
25131      * {@link #setSystemUiVisibility(int)} values supplied by all of the
25132      * views in the window.
25133      */
getWindowSystemUiVisibility()25134     public int getWindowSystemUiVisibility() {
25135         return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
25136     }
25137 
25138     /**
25139      * Override to find out when the window's requested system UI visibility
25140      * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
25141      * This is different from the callbacks received through
25142      * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
25143      * in that this is only telling you about the local request of the window,
25144      * not the actual values applied by the system.
25145      */
onWindowSystemUiVisibilityChanged(int visible)25146     public void onWindowSystemUiVisibilityChanged(int visible) {
25147     }
25148 
25149     /**
25150      * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
25151      * the view hierarchy.
25152      */
dispatchWindowSystemUiVisiblityChanged(int visible)25153     public void dispatchWindowSystemUiVisiblityChanged(int visible) {
25154         onWindowSystemUiVisibilityChanged(visible);
25155     }
25156 
25157     /**
25158      * Set a listener to receive callbacks when the visibility of the system bar changes.
25159      * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
25160      */
setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l)25161     public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
25162         getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
25163         if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
25164             mParent.recomputeViewAttributes(this);
25165         }
25166     }
25167 
25168     /**
25169      * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
25170      * the view hierarchy.
25171      */
dispatchSystemUiVisibilityChanged(int visibility)25172     public void dispatchSystemUiVisibilityChanged(int visibility) {
25173         ListenerInfo li = mListenerInfo;
25174         if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
25175             li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
25176                     visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
25177         }
25178     }
25179 
updateLocalSystemUiVisibility(int localValue, int localChanges)25180     boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
25181         int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
25182         if (val != mSystemUiVisibility) {
25183             setSystemUiVisibility(val);
25184             return true;
25185         }
25186         return false;
25187     }
25188 
25189     /** @hide */
25190     @UnsupportedAppUsage
setDisabledSystemUiVisibility(int flags)25191     public void setDisabledSystemUiVisibility(int flags) {
25192         if (mAttachInfo != null) {
25193             if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
25194                 mAttachInfo.mDisabledSystemUiVisibility = flags;
25195                 if (mParent != null) {
25196                     mParent.recomputeViewAttributes(this);
25197                 }
25198             }
25199         }
25200     }
25201 
25202     /**
25203      * Creates an image that the system displays during the drag and drop
25204      * operation. This is called a &quot;drag shadow&quot;. The default implementation
25205      * for a DragShadowBuilder based on a View returns an image that has exactly the same
25206      * appearance as the given View. The default also positions the center of the drag shadow
25207      * directly under the touch point. If no View is provided (the constructor with no parameters
25208      * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
25209      * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
25210      * default is an invisible drag shadow.
25211      * <p>
25212      * You are not required to use the View you provide to the constructor as the basis of the
25213      * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
25214      * anything you want as the drag shadow.
25215      * </p>
25216      * <p>
25217      *  You pass a DragShadowBuilder object to the system when you start the drag. The system
25218      *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
25219      *  size and position of the drag shadow. It uses this data to construct a
25220      *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
25221      *  so that your application can draw the shadow image in the Canvas.
25222      * </p>
25223      *
25224      * <div class="special reference">
25225      * <h3>Developer Guides</h3>
25226      * <p>For a guide to implementing drag and drop features, read the
25227      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
25228      * </div>
25229      */
25230     public static class DragShadowBuilder {
25231         @UnsupportedAppUsage
25232         private final WeakReference<View> mView;
25233 
25234         /**
25235          * Constructs a shadow image builder based on a View. By default, the resulting drag
25236          * shadow will have the same appearance and dimensions as the View, with the touch point
25237          * over the center of the View.
25238          * @param view A View. Any View in scope can be used.
25239          */
DragShadowBuilder(View view)25240         public DragShadowBuilder(View view) {
25241             mView = new WeakReference<View>(view);
25242         }
25243 
25244         /**
25245          * Construct a shadow builder object with no associated View.  This
25246          * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
25247          * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
25248          * to supply the drag shadow's dimensions and appearance without
25249          * reference to any View object.
25250          */
DragShadowBuilder()25251         public DragShadowBuilder() {
25252             mView = new WeakReference<View>(null);
25253         }
25254 
25255         /**
25256          * Returns the View object that had been passed to the
25257          * {@link #View.DragShadowBuilder(View)}
25258          * constructor.  If that View parameter was {@code null} or if the
25259          * {@link #View.DragShadowBuilder()}
25260          * constructor was used to instantiate the builder object, this method will return
25261          * null.
25262          *
25263          * @return The View object associate with this builder object.
25264          */
25265         @SuppressWarnings({"JavadocReference"})
getView()25266         final public View getView() {
25267             return mView.get();
25268         }
25269 
25270         /**
25271          * Provides the metrics for the shadow image. These include the dimensions of
25272          * the shadow image, and the point within that shadow that should
25273          * be centered under the touch location while dragging.
25274          * <p>
25275          * The default implementation sets the dimensions of the shadow to be the
25276          * same as the dimensions of the View itself and centers the shadow under
25277          * the touch point.
25278          * </p>
25279          *
25280          * @param outShadowSize A {@link android.graphics.Point} containing the width and height
25281          * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
25282          * desired width and must set {@link android.graphics.Point#y} to the desired height of the
25283          * image. Since Android P, the width and height must be positive values.
25284          *
25285          * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
25286          * shadow image that should be underneath the touch point during the drag and drop
25287          * operation. Your application must set {@link android.graphics.Point#x} to the
25288          * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
25289          */
onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint)25290         public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
25291             final View view = mView.get();
25292             if (view != null) {
25293                 outShadowSize.set(view.getWidth(), view.getHeight());
25294                 outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
25295             } else {
25296                 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
25297             }
25298         }
25299 
25300         /**
25301          * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
25302          * based on the dimensions it received from the
25303          * {@link #onProvideShadowMetrics(Point, Point)} callback.
25304          *
25305          * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
25306          */
onDrawShadow(Canvas canvas)25307         public void onDrawShadow(Canvas canvas) {
25308             final View view = mView.get();
25309             if (view != null) {
25310                 view.draw(canvas);
25311             } else {
25312                 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
25313             }
25314         }
25315     }
25316 
25317     /**
25318      * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
25319      * startDragAndDrop()} for newer platform versions.
25320      */
25321     @Deprecated
startDrag(ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flags)25322     public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
25323                                    Object myLocalState, int flags) {
25324         return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
25325     }
25326 
25327     /**
25328      * Starts a drag and drop operation. When your application calls this method, it passes a
25329      * {@link android.view.View.DragShadowBuilder} object to the system. The
25330      * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
25331      * to get metrics for the drag shadow, and then calls the object's
25332      * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
25333      * <p>
25334      *  Once the system has the drag shadow, it begins the drag and drop operation by sending
25335      *  drag events to all the View objects in your application that are currently visible. It does
25336      *  this either by calling the View object's drag listener (an implementation of
25337      *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
25338      *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
25339      *  Both are passed a {@link android.view.DragEvent} object that has a
25340      *  {@link android.view.DragEvent#getAction()} value of
25341      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
25342      * </p>
25343      * <p>
25344      * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
25345      * int) startDragAndDrop()} on any attached View object. The View object does not need to be
25346      * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
25347      * to the View the user selected for dragging.
25348      * </p>
25349      * @param data A {@link android.content.ClipData} object pointing to the data to be
25350      * transferred by the drag and drop operation.
25351      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
25352      * drag shadow.
25353      * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
25354      * drop operation. When dispatching drag events to views in the same activity this object
25355      * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other
25356      * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()}
25357      * will return null).
25358      * <p>
25359      * myLocalState is a lightweight mechanism for the sending information from the dragged View
25360      * to the target Views. For example, it can contain flags that differentiate between a
25361      * a copy operation and a move operation.
25362      * </p>
25363      * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
25364      * flags, or any combination of the following:
25365      *     <ul>
25366      *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
25367      *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
25368      *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
25369      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
25370      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
25371      *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
25372      *     </ul>
25373      * @return {@code true} if the method completes successfully, or
25374      * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
25375      * do a drag because of another ongoing operation or some other reasons.
25376      */
startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flags)25377     public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
25378             Object myLocalState, int flags) {
25379         if (ViewDebug.DEBUG_DRAG) {
25380             Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
25381         }
25382         if (mAttachInfo == null) {
25383             Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
25384             return false;
25385         }
25386         if (!mAttachInfo.mViewRootImpl.mSurface.isValid()) {
25387             Log.w(VIEW_LOG_TAG, "startDragAndDrop called with an invalid surface.");
25388             return false;
25389         }
25390 
25391         if (data != null) {
25392             data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0);
25393         }
25394 
25395         Point shadowSize = new Point();
25396         Point shadowTouchPoint = new Point();
25397         shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
25398 
25399         if ((shadowSize.x < 0) || (shadowSize.y < 0)
25400                 || (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
25401             throw new IllegalStateException("Drag shadow dimensions must not be negative");
25402         }
25403 
25404         // Create 1x1 surface when zero surface size is specified because SurfaceControl.Builder
25405         // does not accept zero size surface.
25406         if (shadowSize.x == 0  || shadowSize.y == 0) {
25407             if (!sAcceptZeroSizeDragShadow) {
25408                 throw new IllegalStateException("Drag shadow dimensions must be positive");
25409             }
25410             shadowSize.x = 1;
25411             shadowSize.y = 1;
25412         }
25413 
25414         if (ViewDebug.DEBUG_DRAG) {
25415             Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
25416                     + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
25417         }
25418 
25419         final ViewRootImpl root = mAttachInfo.mViewRootImpl;
25420         final SurfaceSession session = new SurfaceSession();
25421         final SurfaceControl surfaceControl = new SurfaceControl.Builder(session)
25422                 .setName("drag surface")
25423                 .setParent(root.getSurfaceControl())
25424                 .setBufferSize(shadowSize.x, shadowSize.y)
25425                 .setFormat(PixelFormat.TRANSLUCENT)
25426                 .build();
25427         final Surface surface = new Surface();
25428         surface.copyFrom(surfaceControl);
25429         IBinder token = null;
25430         try {
25431             final Canvas canvas = surface.lockCanvas(null);
25432             try {
25433                 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
25434                 shadowBuilder.onDrawShadow(canvas);
25435             } finally {
25436                 surface.unlockCanvasAndPost(canvas);
25437             }
25438 
25439             // repurpose 'shadowSize' for the last touch point
25440             root.getLastTouchPoint(shadowSize);
25441 
25442             token = mAttachInfo.mSession.performDrag(
25443                     mAttachInfo.mWindow, flags, surfaceControl, root.getLastTouchSource(),
25444                     shadowSize.x, shadowSize.y, shadowTouchPoint.x, shadowTouchPoint.y, data);
25445             if (ViewDebug.DEBUG_DRAG) {
25446                 Log.d(VIEW_LOG_TAG, "performDrag returned " + token);
25447             }
25448             if (token != null) {
25449                 if (mAttachInfo.mDragSurface != null) {
25450                     mAttachInfo.mDragSurface.release();
25451                 }
25452                 mAttachInfo.mDragSurface = surface;
25453                 mAttachInfo.mDragToken = token;
25454                 // Cache the local state object for delivery with DragEvents
25455                 root.setLocalDragState(myLocalState);
25456             }
25457             return token != null;
25458         } catch (Exception e) {
25459             Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
25460             return false;
25461         } finally {
25462             if (token == null) {
25463                 surface.destroy();
25464             }
25465             session.kill();
25466         }
25467     }
25468 
25469     /**
25470      * Cancels an ongoing drag and drop operation.
25471      * <p>
25472      * A {@link android.view.DragEvent} object with
25473      * {@link android.view.DragEvent#getAction()} value of
25474      * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
25475      * {@link android.view.DragEvent#getResult()} value of {@code false}
25476      * will be sent to every
25477      * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
25478      * even if they are not currently visible.
25479      * </p>
25480      * <p>
25481      * This method can be called on any View in the same window as the View on which
25482      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
25483      * was called.
25484      * </p>
25485      */
cancelDragAndDrop()25486     public final void cancelDragAndDrop() {
25487         if (ViewDebug.DEBUG_DRAG) {
25488             Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
25489         }
25490         if (mAttachInfo == null) {
25491             Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
25492             return;
25493         }
25494         if (mAttachInfo.mDragToken != null) {
25495             try {
25496                 mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken, false);
25497             } catch (Exception e) {
25498                 Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
25499             }
25500             mAttachInfo.mDragToken = null;
25501         } else {
25502             Log.e(VIEW_LOG_TAG, "No active drag to cancel");
25503         }
25504     }
25505 
25506     /**
25507      * Updates the drag shadow for the ongoing drag and drop operation.
25508      *
25509      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
25510      * new drag shadow.
25511      */
updateDragShadow(DragShadowBuilder shadowBuilder)25512     public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
25513         if (ViewDebug.DEBUG_DRAG) {
25514             Log.d(VIEW_LOG_TAG, "updateDragShadow");
25515         }
25516         if (mAttachInfo == null) {
25517             Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
25518             return;
25519         }
25520         if (mAttachInfo.mDragToken != null) {
25521             try {
25522                 Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
25523                 try {
25524                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
25525                     shadowBuilder.onDrawShadow(canvas);
25526                 } finally {
25527                     mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
25528                 }
25529             } catch (Exception e) {
25530                 Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
25531             }
25532         } else {
25533             Log.e(VIEW_LOG_TAG, "No active drag");
25534         }
25535     }
25536 
25537     /**
25538      * Starts a move from {startX, startY}, the amount of the movement will be the offset
25539      * between {startX, startY} and the new cursor positon.
25540      * @param startX horizontal coordinate where the move started.
25541      * @param startY vertical coordinate where the move started.
25542      * @return whether moving was started successfully.
25543      * @hide
25544      */
startMovingTask(float startX, float startY)25545     public final boolean startMovingTask(float startX, float startY) {
25546         if (ViewDebug.DEBUG_POSITIONING) {
25547             Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
25548         }
25549         try {
25550             return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
25551         } catch (RemoteException e) {
25552             Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
25553         }
25554         return false;
25555     }
25556 
25557     /**
25558      * Finish a window move task.
25559      * @hide
25560      */
finishMovingTask()25561     public void finishMovingTask() {
25562         if (ViewDebug.DEBUG_POSITIONING) {
25563             Log.d(VIEW_LOG_TAG, "finishMovingTask");
25564         }
25565         try {
25566             mAttachInfo.mSession.finishMovingTask(mAttachInfo.mWindow);
25567         } catch (RemoteException e) {
25568             Log.e(VIEW_LOG_TAG, "Unable to finish moving", e);
25569         }
25570     }
25571 
25572     /**
25573      * Handles drag events sent by the system following a call to
25574      * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
25575      * startDragAndDrop()}.
25576      *<p>
25577      * When the system calls this method, it passes a
25578      * {@link android.view.DragEvent} object. A call to
25579      * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
25580      * in DragEvent. The method uses these to determine what is happening in the drag and drop
25581      * operation.
25582      * @param event The {@link android.view.DragEvent} sent by the system.
25583      * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
25584      * in DragEvent, indicating the type of drag event represented by this object.
25585      * @return {@code true} if the method was successful, otherwise {@code false}.
25586      * <p>
25587      *  The method should return {@code true} in response to an action type of
25588      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
25589      *  operation.
25590      * </p>
25591      * <p>
25592      *  The method should also return {@code true} in response to an action type of
25593      *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
25594      *  {@code false} if it didn't.
25595      * </p>
25596      * <p>
25597      *  For all other events, the return value is ignored.
25598      * </p>
25599      */
onDragEvent(DragEvent event)25600     public boolean onDragEvent(DragEvent event) {
25601         return false;
25602     }
25603 
25604     // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps.
dispatchDragEnterExitInPreN(DragEvent event)25605     boolean dispatchDragEnterExitInPreN(DragEvent event) {
25606         return callDragEventHandler(event);
25607     }
25608 
25609     /**
25610      * Detects if this View is enabled and has a drag event listener.
25611      * If both are true, then it calls the drag event listener with the
25612      * {@link android.view.DragEvent} it received. If the drag event listener returns
25613      * {@code true}, then dispatchDragEvent() returns {@code true}.
25614      * <p>
25615      * For all other cases, the method calls the
25616      * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
25617      * method and returns its result.
25618      * </p>
25619      * <p>
25620      * This ensures that a drag event is always consumed, even if the View does not have a drag
25621      * event listener. However, if the View has a listener and the listener returns true, then
25622      * onDragEvent() is not called.
25623      * </p>
25624      */
dispatchDragEvent(DragEvent event)25625     public boolean dispatchDragEvent(DragEvent event) {
25626         event.mEventHandlerWasCalled = true;
25627         if (event.mAction == DragEvent.ACTION_DRAG_LOCATION ||
25628             event.mAction == DragEvent.ACTION_DROP) {
25629             // About to deliver an event with coordinates to this view. Notify that now this view
25630             // has drag focus. This will send exit/enter events as needed.
25631             getViewRootImpl().setDragFocus(this, event);
25632         }
25633         return callDragEventHandler(event);
25634     }
25635 
callDragEventHandler(DragEvent event)25636     final boolean callDragEventHandler(DragEvent event) {
25637         final boolean result;
25638 
25639         ListenerInfo li = mListenerInfo;
25640         //noinspection SimplifiableIfStatement
25641         if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
25642                 && li.mOnDragListener.onDrag(this, event)) {
25643             result = true;
25644         } else {
25645             result = onDragEvent(event);
25646         }
25647 
25648         switch (event.mAction) {
25649             case DragEvent.ACTION_DRAG_ENTERED: {
25650                 mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
25651                 refreshDrawableState();
25652             } break;
25653             case DragEvent.ACTION_DRAG_EXITED: {
25654                 mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
25655                 refreshDrawableState();
25656             } break;
25657             case DragEvent.ACTION_DRAG_ENDED: {
25658                 mPrivateFlags2 &= ~View.DRAG_MASK;
25659                 refreshDrawableState();
25660             } break;
25661         }
25662 
25663         return result;
25664     }
25665 
canAcceptDrag()25666     boolean canAcceptDrag() {
25667         return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
25668     }
25669 
25670     /**
25671      * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
25672      * it is ever exposed at all.
25673      * @hide
25674      */
25675     @UnsupportedAppUsage
onCloseSystemDialogs(String reason)25676     public void onCloseSystemDialogs(String reason) {
25677     }
25678 
25679     /**
25680      * Given a Drawable whose bounds have been set to draw into this view,
25681      * update a Region being computed for
25682      * {@link #gatherTransparentRegion(android.graphics.Region)} so
25683      * that any non-transparent parts of the Drawable are removed from the
25684      * given transparent region.
25685      *
25686      * @param dr The Drawable whose transparency is to be applied to the region.
25687      * @param region A Region holding the current transparency information,
25688      * where any parts of the region that are set are considered to be
25689      * transparent.  On return, this region will be modified to have the
25690      * transparency information reduced by the corresponding parts of the
25691      * Drawable that are not transparent.
25692      * {@hide}
25693      */
25694     @UnsupportedAppUsage
applyDrawableToTransparentRegion(Drawable dr, Region region)25695     public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
25696         if (DBG) {
25697             Log.i("View", "Getting transparent region for: " + this);
25698         }
25699         final Region r = dr.getTransparentRegion();
25700         final Rect db = dr.getBounds();
25701         final AttachInfo attachInfo = mAttachInfo;
25702         if (r != null && attachInfo != null) {
25703             final int w = getRight()-getLeft();
25704             final int h = getBottom()-getTop();
25705             if (db.left > 0) {
25706                 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
25707                 r.op(0, 0, db.left, h, Region.Op.UNION);
25708             }
25709             if (db.right < w) {
25710                 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
25711                 r.op(db.right, 0, w, h, Region.Op.UNION);
25712             }
25713             if (db.top > 0) {
25714                 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
25715                 r.op(0, 0, w, db.top, Region.Op.UNION);
25716             }
25717             if (db.bottom < h) {
25718                 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
25719                 r.op(0, db.bottom, w, h, Region.Op.UNION);
25720             }
25721             final int[] location = attachInfo.mTransparentLocation;
25722             getLocationInWindow(location);
25723             r.translate(location[0], location[1]);
25724             region.op(r, Region.Op.INTERSECT);
25725         } else {
25726             region.op(db, Region.Op.DIFFERENCE);
25727         }
25728     }
25729 
checkForLongClick(long delay, float x, float y, int classification)25730     private void checkForLongClick(long delay, float x, float y, int classification) {
25731         if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
25732             mHasPerformedLongPress = false;
25733 
25734             if (mPendingCheckForLongPress == null) {
25735                 mPendingCheckForLongPress = new CheckForLongPress();
25736             }
25737             mPendingCheckForLongPress.setAnchor(x, y);
25738             mPendingCheckForLongPress.rememberWindowAttachCount();
25739             mPendingCheckForLongPress.rememberPressedState();
25740             mPendingCheckForLongPress.setClassification(classification);
25741             postDelayed(mPendingCheckForLongPress, delay);
25742         }
25743     }
25744 
25745     /**
25746      * Inflate a view from an XML resource.  This convenience method wraps the {@link
25747      * LayoutInflater} class, which provides a full range of options for view inflation.
25748      *
25749      * @param context The Context object for your activity or application.
25750      * @param resource The resource ID to inflate
25751      * @param root A view group that will be the parent.  Used to properly inflate the
25752      * layout_* parameters.
25753      * @see LayoutInflater
25754      */
inflate(Context context, @LayoutRes int resource, ViewGroup root)25755     public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
25756         LayoutInflater factory = LayoutInflater.from(context);
25757         return factory.inflate(resource, root);
25758     }
25759 
25760     /**
25761      * Scroll the view with standard behavior for scrolling beyond the normal
25762      * content boundaries. Views that call this method should override
25763      * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
25764      * results of an over-scroll operation.
25765      *
25766      * Views can use this method to handle any touch or fling-based scrolling.
25767      *
25768      * @param deltaX Change in X in pixels
25769      * @param deltaY Change in Y in pixels
25770      * @param scrollX Current X scroll value in pixels before applying deltaX
25771      * @param scrollY Current Y scroll value in pixels before applying deltaY
25772      * @param scrollRangeX Maximum content scroll range along the X axis
25773      * @param scrollRangeY Maximum content scroll range along the Y axis
25774      * @param maxOverScrollX Number of pixels to overscroll by in either direction
25775      *          along the X axis.
25776      * @param maxOverScrollY Number of pixels to overscroll by in either direction
25777      *          along the Y axis.
25778      * @param isTouchEvent true if this scroll operation is the result of a touch event.
25779      * @return true if scrolling was clamped to an over-scroll boundary along either
25780      *          axis, false otherwise.
25781      */
25782     @SuppressWarnings({"UnusedParameters"})
overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent)25783     protected boolean overScrollBy(int deltaX, int deltaY,
25784             int scrollX, int scrollY,
25785             int scrollRangeX, int scrollRangeY,
25786             int maxOverScrollX, int maxOverScrollY,
25787             boolean isTouchEvent) {
25788         final int overScrollMode = mOverScrollMode;
25789         final boolean canScrollHorizontal =
25790                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
25791         final boolean canScrollVertical =
25792                 computeVerticalScrollRange() > computeVerticalScrollExtent();
25793         final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
25794                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
25795         final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
25796                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
25797 
25798         int newScrollX = scrollX + deltaX;
25799         if (!overScrollHorizontal) {
25800             maxOverScrollX = 0;
25801         }
25802 
25803         int newScrollY = scrollY + deltaY;
25804         if (!overScrollVertical) {
25805             maxOverScrollY = 0;
25806         }
25807 
25808         // Clamp values if at the limits and record
25809         final int left = -maxOverScrollX;
25810         final int right = maxOverScrollX + scrollRangeX;
25811         final int top = -maxOverScrollY;
25812         final int bottom = maxOverScrollY + scrollRangeY;
25813 
25814         boolean clampedX = false;
25815         if (newScrollX > right) {
25816             newScrollX = right;
25817             clampedX = true;
25818         } else if (newScrollX < left) {
25819             newScrollX = left;
25820             clampedX = true;
25821         }
25822 
25823         boolean clampedY = false;
25824         if (newScrollY > bottom) {
25825             newScrollY = bottom;
25826             clampedY = true;
25827         } else if (newScrollY < top) {
25828             newScrollY = top;
25829             clampedY = true;
25830         }
25831 
25832         onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
25833 
25834         return clampedX || clampedY;
25835     }
25836 
25837     /**
25838      * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
25839      * respond to the results of an over-scroll operation.
25840      *
25841      * @param scrollX New X scroll value in pixels
25842      * @param scrollY New Y scroll value in pixels
25843      * @param clampedX True if scrollX was clamped to an over-scroll boundary
25844      * @param clampedY True if scrollY was clamped to an over-scroll boundary
25845      */
onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY)25846     protected void onOverScrolled(int scrollX, int scrollY,
25847             boolean clampedX, boolean clampedY) {
25848         // Intentionally empty.
25849     }
25850 
25851     /**
25852      * Returns the over-scroll mode for this view. The result will be
25853      * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
25854      * (allow over-scrolling only if the view content is larger than the container),
25855      * or {@link #OVER_SCROLL_NEVER}.
25856      *
25857      * @return This view's over-scroll mode.
25858      */
25859     @InspectableProperty(enumMapping = {
25860             @EnumEntry(value = OVER_SCROLL_ALWAYS, name = "always"),
25861             @EnumEntry(value = OVER_SCROLL_IF_CONTENT_SCROLLS, name = "ifContentScrolls"),
25862             @EnumEntry(value = OVER_SCROLL_NEVER, name = "never")
25863     })
getOverScrollMode()25864     public int getOverScrollMode() {
25865         return mOverScrollMode;
25866     }
25867 
25868     /**
25869      * Set the over-scroll mode for this view. Valid over-scroll modes are
25870      * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
25871      * (allow over-scrolling only if the view content is larger than the container),
25872      * or {@link #OVER_SCROLL_NEVER}.
25873      *
25874      * Setting the over-scroll mode of a view will have an effect only if the
25875      * view is capable of scrolling.
25876      *
25877      * @param overScrollMode The new over-scroll mode for this view.
25878      */
setOverScrollMode(int overScrollMode)25879     public void setOverScrollMode(int overScrollMode) {
25880         if (overScrollMode != OVER_SCROLL_ALWAYS &&
25881                 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
25882                 overScrollMode != OVER_SCROLL_NEVER) {
25883             throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
25884         }
25885         mOverScrollMode = overScrollMode;
25886     }
25887 
25888     /**
25889      * Enable or disable nested scrolling for this view.
25890      *
25891      * <p>If this property is set to true the view will be permitted to initiate nested
25892      * scrolling operations with a compatible parent view in the current hierarchy. If this
25893      * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
25894      * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
25895      * the nested scroll.</p>
25896      *
25897      * @param enabled true to enable nested scrolling, false to disable
25898      *
25899      * @see #isNestedScrollingEnabled()
25900      */
setNestedScrollingEnabled(boolean enabled)25901     public void setNestedScrollingEnabled(boolean enabled) {
25902         if (enabled) {
25903             mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
25904         } else {
25905             stopNestedScroll();
25906             mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
25907         }
25908     }
25909 
25910     /**
25911      * Returns true if nested scrolling is enabled for this view.
25912      *
25913      * <p>If nested scrolling is enabled and this View class implementation supports it,
25914      * this view will act as a nested scrolling child view when applicable, forwarding data
25915      * about the scroll operation in progress to a compatible and cooperating nested scrolling
25916      * parent.</p>
25917      *
25918      * @return true if nested scrolling is enabled
25919      *
25920      * @see #setNestedScrollingEnabled(boolean)
25921      */
25922     @InspectableProperty
isNestedScrollingEnabled()25923     public boolean isNestedScrollingEnabled() {
25924         return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
25925                 PFLAG3_NESTED_SCROLLING_ENABLED;
25926     }
25927 
25928     /**
25929      * Begin a nestable scroll operation along the given axes.
25930      *
25931      * <p>A view starting a nested scroll promises to abide by the following contract:</p>
25932      *
25933      * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
25934      * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
25935      * In the case of touch scrolling the nested scroll will be terminated automatically in
25936      * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
25937      * In the event of programmatic scrolling the caller must explicitly call
25938      * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
25939      *
25940      * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
25941      * If it returns false the caller may ignore the rest of this contract until the next scroll.
25942      * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
25943      *
25944      * <p>At each incremental step of the scroll the caller should invoke
25945      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
25946      * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
25947      * parent at least partially consumed the scroll and the caller should adjust the amount it
25948      * scrolls by.</p>
25949      *
25950      * <p>After applying the remainder of the scroll delta the caller should invoke
25951      * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
25952      * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
25953      * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
25954      * </p>
25955      *
25956      * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
25957      *             {@link #SCROLL_AXIS_VERTICAL}.
25958      * @return true if a cooperative parent was found and nested scrolling has been enabled for
25959      *         the current gesture.
25960      *
25961      * @see #stopNestedScroll()
25962      * @see #dispatchNestedPreScroll(int, int, int[], int[])
25963      * @see #dispatchNestedScroll(int, int, int, int, int[])
25964      */
startNestedScroll(int axes)25965     public boolean startNestedScroll(int axes) {
25966         if (hasNestedScrollingParent()) {
25967             // Already in progress
25968             return true;
25969         }
25970         if (isNestedScrollingEnabled()) {
25971             ViewParent p = getParent();
25972             View child = this;
25973             while (p != null) {
25974                 try {
25975                     if (p.onStartNestedScroll(child, this, axes)) {
25976                         mNestedScrollingParent = p;
25977                         p.onNestedScrollAccepted(child, this, axes);
25978                         return true;
25979                     }
25980                 } catch (AbstractMethodError e) {
25981                     Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
25982                             "method onStartNestedScroll", e);
25983                     // Allow the search upward to continue
25984                 }
25985                 if (p instanceof View) {
25986                     child = (View) p;
25987                 }
25988                 p = p.getParent();
25989             }
25990         }
25991         return false;
25992     }
25993 
25994     /**
25995      * Stop a nested scroll in progress.
25996      *
25997      * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
25998      *
25999      * @see #startNestedScroll(int)
26000      */
stopNestedScroll()26001     public void stopNestedScroll() {
26002         if (mNestedScrollingParent != null) {
26003             mNestedScrollingParent.onStopNestedScroll(this);
26004             mNestedScrollingParent = null;
26005         }
26006     }
26007 
26008     /**
26009      * Returns true if this view has a nested scrolling parent.
26010      *
26011      * <p>The presence of a nested scrolling parent indicates that this view has initiated
26012      * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
26013      *
26014      * @return whether this view has a nested scrolling parent
26015      */
hasNestedScrollingParent()26016     public boolean hasNestedScrollingParent() {
26017         return mNestedScrollingParent != null;
26018     }
26019 
26020     /**
26021      * Dispatch one step of a nested scroll in progress.
26022      *
26023      * <p>Implementations of views that support nested scrolling should call this to report
26024      * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
26025      * is not currently in progress or nested scrolling is not
26026      * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
26027      *
26028      * <p>Compatible View implementations should also call
26029      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
26030      * consuming a component of the scroll event themselves.</p>
26031      *
26032      * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
26033      * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
26034      * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
26035      * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
26036      * @param offsetInWindow Optional. If not null, on return this will contain the offset
26037      *                       in local view coordinates of this view from before this operation
26038      *                       to after it completes. View implementations may use this to adjust
26039      *                       expected input coordinate tracking.
26040      * @return true if the event was dispatched, false if it could not be dispatched.
26041      * @see #dispatchNestedPreScroll(int, int, int[], int[])
26042      */
dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow)26043     public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
26044             int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
26045         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
26046             if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
26047                 int startX = 0;
26048                 int startY = 0;
26049                 if (offsetInWindow != null) {
26050                     getLocationInWindow(offsetInWindow);
26051                     startX = offsetInWindow[0];
26052                     startY = offsetInWindow[1];
26053                 }
26054 
26055                 mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
26056                         dxUnconsumed, dyUnconsumed);
26057 
26058                 if (offsetInWindow != null) {
26059                     getLocationInWindow(offsetInWindow);
26060                     offsetInWindow[0] -= startX;
26061                     offsetInWindow[1] -= startY;
26062                 }
26063                 return true;
26064             } else if (offsetInWindow != null) {
26065                 // No motion, no dispatch. Keep offsetInWindow up to date.
26066                 offsetInWindow[0] = 0;
26067                 offsetInWindow[1] = 0;
26068             }
26069         }
26070         return false;
26071     }
26072 
26073     /**
26074      * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
26075      *
26076      * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
26077      * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
26078      * scrolling operation to consume some or all of the scroll operation before the child view
26079      * consumes it.</p>
26080      *
26081      * @param dx Horizontal scroll distance in pixels
26082      * @param dy Vertical scroll distance in pixels
26083      * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
26084      *                 and consumed[1] the consumed dy.
26085      * @param offsetInWindow Optional. If not null, on return this will contain the offset
26086      *                       in local view coordinates of this view from before this operation
26087      *                       to after it completes. View implementations may use this to adjust
26088      *                       expected input coordinate tracking.
26089      * @return true if the parent consumed some or all of the scroll delta
26090      * @see #dispatchNestedScroll(int, int, int, int, int[])
26091      */
dispatchNestedPreScroll(int dx, int dy, @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow)26092     public boolean dispatchNestedPreScroll(int dx, int dy,
26093             @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
26094         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
26095             if (dx != 0 || dy != 0) {
26096                 int startX = 0;
26097                 int startY = 0;
26098                 if (offsetInWindow != null) {
26099                     getLocationInWindow(offsetInWindow);
26100                     startX = offsetInWindow[0];
26101                     startY = offsetInWindow[1];
26102                 }
26103 
26104                 if (consumed == null) {
26105                     if (mTempNestedScrollConsumed == null) {
26106                         mTempNestedScrollConsumed = new int[2];
26107                     }
26108                     consumed = mTempNestedScrollConsumed;
26109                 }
26110                 consumed[0] = 0;
26111                 consumed[1] = 0;
26112                 mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
26113 
26114                 if (offsetInWindow != null) {
26115                     getLocationInWindow(offsetInWindow);
26116                     offsetInWindow[0] -= startX;
26117                     offsetInWindow[1] -= startY;
26118                 }
26119                 return consumed[0] != 0 || consumed[1] != 0;
26120             } else if (offsetInWindow != null) {
26121                 offsetInWindow[0] = 0;
26122                 offsetInWindow[1] = 0;
26123             }
26124         }
26125         return false;
26126     }
26127 
26128     /**
26129      * Dispatch a fling to a nested scrolling parent.
26130      *
26131      * <p>This method should be used to indicate that a nested scrolling child has detected
26132      * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
26133      * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
26134      * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
26135      * along a scrollable axis.</p>
26136      *
26137      * <p>If a nested scrolling child view would normally fling but it is at the edge of
26138      * its own content, it can use this method to delegate the fling to its nested scrolling
26139      * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
26140      *
26141      * @param velocityX Horizontal fling velocity in pixels per second
26142      * @param velocityY Vertical fling velocity in pixels per second
26143      * @param consumed true if the child consumed the fling, false otherwise
26144      * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
26145      */
dispatchNestedFling(float velocityX, float velocityY, boolean consumed)26146     public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
26147         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
26148             return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
26149         }
26150         return false;
26151     }
26152 
26153     /**
26154      * Dispatch a fling to a nested scrolling parent before it is processed by this view.
26155      *
26156      * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
26157      * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
26158      * offsets an opportunity for the parent view in a nested fling to fully consume the fling
26159      * before the child view consumes it. If this method returns <code>true</code>, a nested
26160      * parent view consumed the fling and this view should not scroll as a result.</p>
26161      *
26162      * <p>For a better user experience, only one view in a nested scrolling chain should consume
26163      * the fling at a time. If a parent view consumed the fling this method will return false.
26164      * Custom view implementations should account for this in two ways:</p>
26165      *
26166      * <ul>
26167      *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
26168      *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
26169      *     position regardless.</li>
26170      *     <li>If a nested parent does consume the fling, this view should not scroll at all,
26171      *     even to settle back to a valid idle position.</li>
26172      * </ul>
26173      *
26174      * <p>Views should also not offer fling velocities to nested parent views along an axis
26175      * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
26176      * should not offer a horizontal fling velocity to its parents since scrolling along that
26177      * axis is not permitted and carrying velocity along that motion does not make sense.</p>
26178      *
26179      * @param velocityX Horizontal fling velocity in pixels per second
26180      * @param velocityY Vertical fling velocity in pixels per second
26181      * @return true if a nested scrolling parent consumed the fling
26182      */
dispatchNestedPreFling(float velocityX, float velocityY)26183     public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
26184         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
26185             return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
26186         }
26187         return false;
26188     }
26189 
26190     /**
26191      * Gets a scale factor that determines the distance the view should scroll
26192      * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
26193      * @return The vertical scroll scale factor.
26194      * @hide
26195      */
26196     @UnsupportedAppUsage
getVerticalScrollFactor()26197     protected float getVerticalScrollFactor() {
26198         if (mVerticalScrollFactor == 0) {
26199             TypedValue outValue = new TypedValue();
26200             if (!mContext.getTheme().resolveAttribute(
26201                     com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
26202                 throw new IllegalStateException(
26203                         "Expected theme to define listPreferredItemHeight.");
26204             }
26205             mVerticalScrollFactor = outValue.getDimension(
26206                     mContext.getResources().getDisplayMetrics());
26207         }
26208         return mVerticalScrollFactor;
26209     }
26210 
26211     /**
26212      * Gets a scale factor that determines the distance the view should scroll
26213      * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
26214      * @return The horizontal scroll scale factor.
26215      * @hide
26216      */
26217     @UnsupportedAppUsage
getHorizontalScrollFactor()26218     protected float getHorizontalScrollFactor() {
26219         // TODO: Should use something else.
26220         return getVerticalScrollFactor();
26221     }
26222 
26223     /**
26224      * Return the value specifying the text direction or policy that was set with
26225      * {@link #setTextDirection(int)}.
26226      *
26227      * @return the defined text direction. It can be one of:
26228      *
26229      * {@link #TEXT_DIRECTION_INHERIT},
26230      * {@link #TEXT_DIRECTION_FIRST_STRONG},
26231      * {@link #TEXT_DIRECTION_ANY_RTL},
26232      * {@link #TEXT_DIRECTION_LTR},
26233      * {@link #TEXT_DIRECTION_RTL},
26234      * {@link #TEXT_DIRECTION_LOCALE},
26235      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
26236      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
26237      *
26238      * @attr ref android.R.styleable#View_textDirection
26239      *
26240      * @hide
26241      */
26242     @ViewDebug.ExportedProperty(category = "text", mapping = {
26243             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
26244             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
26245             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
26246             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
26247             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
26248             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
26249             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
26250             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
26251     })
26252     @InspectableProperty(hasAttributeId = false, enumMapping = {
26253             @EnumEntry(value = TEXT_DIRECTION_INHERIT, name = "inherit"),
26254             @EnumEntry(value = TEXT_DIRECTION_LOCALE, name = "locale"),
26255             @EnumEntry(value = TEXT_DIRECTION_ANY_RTL, name = "anyRtl"),
26256             @EnumEntry(value = TEXT_DIRECTION_LTR, name = "ltr"),
26257             @EnumEntry(value = TEXT_DIRECTION_RTL, name = "rtl"),
26258             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG, name = "firstStrong"),
26259             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_LTR, name = "firstStrongLtr"),
26260             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_RTL, name = "firstStrongRtl"),
26261     })
26262     @UnsupportedAppUsage
getRawTextDirection()26263     public int getRawTextDirection() {
26264         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
26265     }
26266 
26267     /**
26268      * Set the text direction.
26269      *
26270      * @param textDirection the direction to set. Should be one of:
26271      *
26272      * {@link #TEXT_DIRECTION_INHERIT},
26273      * {@link #TEXT_DIRECTION_FIRST_STRONG},
26274      * {@link #TEXT_DIRECTION_ANY_RTL},
26275      * {@link #TEXT_DIRECTION_LTR},
26276      * {@link #TEXT_DIRECTION_RTL},
26277      * {@link #TEXT_DIRECTION_LOCALE}
26278      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
26279      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
26280      *
26281      * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
26282      * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
26283      * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
26284      *
26285      * @attr ref android.R.styleable#View_textDirection
26286      */
setTextDirection(int textDirection)26287     public void setTextDirection(int textDirection) {
26288         if (getRawTextDirection() != textDirection) {
26289             // Reset the current text direction and the resolved one
26290             mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
26291             resetResolvedTextDirection();
26292             // Set the new text direction
26293             mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
26294             // Do resolution
26295             resolveTextDirection();
26296             // Notify change
26297             onRtlPropertiesChanged(getLayoutDirection());
26298             // Refresh
26299             requestLayout();
26300             invalidate(true);
26301         }
26302     }
26303 
26304     /**
26305      * Return the resolved text direction.
26306      *
26307      * @return the resolved text direction. Returns one of:
26308      *
26309      * {@link #TEXT_DIRECTION_FIRST_STRONG},
26310      * {@link #TEXT_DIRECTION_ANY_RTL},
26311      * {@link #TEXT_DIRECTION_LTR},
26312      * {@link #TEXT_DIRECTION_RTL},
26313      * {@link #TEXT_DIRECTION_LOCALE},
26314      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
26315      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
26316      *
26317      * @attr ref android.R.styleable#View_textDirection
26318      */
26319     @ViewDebug.ExportedProperty(category = "text", mapping = {
26320             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
26321             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
26322             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
26323             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
26324             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
26325             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
26326             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
26327             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
26328     })
26329     @InspectableProperty(hasAttributeId = false, enumMapping = {
26330             @EnumEntry(value = TEXT_DIRECTION_LOCALE, name = "locale"),
26331             @EnumEntry(value = TEXT_DIRECTION_ANY_RTL, name = "anyRtl"),
26332             @EnumEntry(value = TEXT_DIRECTION_LTR, name = "ltr"),
26333             @EnumEntry(value = TEXT_DIRECTION_RTL, name = "rtl"),
26334             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG, name = "firstStrong"),
26335             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_LTR, name = "firstStrongLtr"),
26336             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_RTL, name = "firstStrongRtl"),
26337     })
getTextDirection()26338     public int getTextDirection() {
26339         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
26340     }
26341 
26342     /**
26343      * Resolve the text direction.
26344      *
26345      * @return true if resolution has been done, false otherwise.
26346      *
26347      * @hide
26348      */
resolveTextDirection()26349     public boolean resolveTextDirection() {
26350         // Reset any previous text direction resolution
26351         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
26352 
26353         if (hasRtlSupport()) {
26354             // Set resolved text direction flag depending on text direction flag
26355             final int textDirection = getRawTextDirection();
26356             switch(textDirection) {
26357                 case TEXT_DIRECTION_INHERIT:
26358                     if (!canResolveTextDirection()) {
26359                         // We cannot do the resolution if there is no parent, so use the default one
26360                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
26361                         // Resolution will need to happen again later
26362                         return false;
26363                     }
26364 
26365                     // Parent has not yet resolved, so we still return the default
26366                     try {
26367                         if (!mParent.isTextDirectionResolved()) {
26368                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
26369                             // Resolution will need to happen again later
26370                             return false;
26371                         }
26372                     } catch (AbstractMethodError e) {
26373                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
26374                                 " does not fully implement ViewParent", e);
26375                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
26376                                 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
26377                         return true;
26378                     }
26379 
26380                     // Set current resolved direction to the same value as the parent's one
26381                     int parentResolvedDirection;
26382                     try {
26383                         parentResolvedDirection = mParent.getTextDirection();
26384                     } catch (AbstractMethodError e) {
26385                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
26386                                 " does not fully implement ViewParent", e);
26387                         parentResolvedDirection = TEXT_DIRECTION_LTR;
26388                     }
26389                     switch (parentResolvedDirection) {
26390                         case TEXT_DIRECTION_FIRST_STRONG:
26391                         case TEXT_DIRECTION_ANY_RTL:
26392                         case TEXT_DIRECTION_LTR:
26393                         case TEXT_DIRECTION_RTL:
26394                         case TEXT_DIRECTION_LOCALE:
26395                         case TEXT_DIRECTION_FIRST_STRONG_LTR:
26396                         case TEXT_DIRECTION_FIRST_STRONG_RTL:
26397                             mPrivateFlags2 |=
26398                                     (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
26399                             break;
26400                         default:
26401                             // Default resolved direction is "first strong" heuristic
26402                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
26403                     }
26404                     break;
26405                 case TEXT_DIRECTION_FIRST_STRONG:
26406                 case TEXT_DIRECTION_ANY_RTL:
26407                 case TEXT_DIRECTION_LTR:
26408                 case TEXT_DIRECTION_RTL:
26409                 case TEXT_DIRECTION_LOCALE:
26410                 case TEXT_DIRECTION_FIRST_STRONG_LTR:
26411                 case TEXT_DIRECTION_FIRST_STRONG_RTL:
26412                     // Resolved direction is the same as text direction
26413                     mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
26414                     break;
26415                 default:
26416                     // Default resolved direction is "first strong" heuristic
26417                     mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
26418             }
26419         } else {
26420             // Default resolved direction is "first strong" heuristic
26421             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
26422         }
26423 
26424         // Set to resolved
26425         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
26426         return true;
26427     }
26428 
26429     /**
26430      * Check if text direction resolution can be done.
26431      *
26432      * @return true if text direction resolution can be done otherwise return false.
26433      */
canResolveTextDirection()26434     public boolean canResolveTextDirection() {
26435         switch (getRawTextDirection()) {
26436             case TEXT_DIRECTION_INHERIT:
26437                 if (mParent != null) {
26438                     try {
26439                         return mParent.canResolveTextDirection();
26440                     } catch (AbstractMethodError e) {
26441                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
26442                                 " does not fully implement ViewParent", e);
26443                     }
26444                 }
26445                 return false;
26446 
26447             default:
26448                 return true;
26449         }
26450     }
26451 
26452     /**
26453      * Reset resolved text direction. Text direction will be resolved during a call to
26454      * {@link #onMeasure(int, int)}.
26455      *
26456      * @hide
26457      */
26458     @TestApi
resetResolvedTextDirection()26459     public void resetResolvedTextDirection() {
26460         // Reset any previous text direction resolution
26461         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
26462         // Set to default value
26463         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
26464     }
26465 
26466     /**
26467      * @return true if text direction is inherited.
26468      *
26469      * @hide
26470      */
isTextDirectionInherited()26471     public boolean isTextDirectionInherited() {
26472         return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
26473     }
26474 
26475     /**
26476      * @return true if text direction is resolved.
26477      */
isTextDirectionResolved()26478     public boolean isTextDirectionResolved() {
26479         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
26480     }
26481 
26482     /**
26483      * Return the value specifying the text alignment or policy that was set with
26484      * {@link #setTextAlignment(int)}.
26485      *
26486      * @return the defined text alignment. It can be one of:
26487      *
26488      * {@link #TEXT_ALIGNMENT_INHERIT},
26489      * {@link #TEXT_ALIGNMENT_GRAVITY},
26490      * {@link #TEXT_ALIGNMENT_CENTER},
26491      * {@link #TEXT_ALIGNMENT_TEXT_START},
26492      * {@link #TEXT_ALIGNMENT_TEXT_END},
26493      * {@link #TEXT_ALIGNMENT_VIEW_START},
26494      * {@link #TEXT_ALIGNMENT_VIEW_END}
26495      *
26496      * @attr ref android.R.styleable#View_textAlignment
26497      *
26498      * @hide
26499      */
26500     @ViewDebug.ExportedProperty(category = "text", mapping = {
26501             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
26502             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
26503             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
26504             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
26505             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
26506             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
26507             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
26508     })
26509     @InspectableProperty(hasAttributeId = false, enumMapping = {
26510             @EnumEntry(value = TEXT_ALIGNMENT_INHERIT, name = "inherit"),
26511             @EnumEntry(value = TEXT_ALIGNMENT_GRAVITY, name = "gravity"),
26512             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_START, name = "textStart"),
26513             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_END, name = "textEnd"),
26514             @EnumEntry(value = TEXT_ALIGNMENT_CENTER, name = "center"),
26515             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_START, name = "viewStart"),
26516             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_END, name = "viewEnd")
26517     })
26518     @TextAlignment
26519     @UnsupportedAppUsage
getRawTextAlignment()26520     public int getRawTextAlignment() {
26521         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
26522     }
26523 
26524     /**
26525      * Set the text alignment.
26526      *
26527      * @param textAlignment The text alignment to set. Should be one of
26528      *
26529      * {@link #TEXT_ALIGNMENT_INHERIT},
26530      * {@link #TEXT_ALIGNMENT_GRAVITY},
26531      * {@link #TEXT_ALIGNMENT_CENTER},
26532      * {@link #TEXT_ALIGNMENT_TEXT_START},
26533      * {@link #TEXT_ALIGNMENT_TEXT_END},
26534      * {@link #TEXT_ALIGNMENT_VIEW_START},
26535      * {@link #TEXT_ALIGNMENT_VIEW_END}
26536      *
26537      * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
26538      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
26539      * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
26540      *
26541      * @attr ref android.R.styleable#View_textAlignment
26542      */
setTextAlignment(@extAlignment int textAlignment)26543     public void setTextAlignment(@TextAlignment int textAlignment) {
26544         if (textAlignment != getRawTextAlignment()) {
26545             // Reset the current and resolved text alignment
26546             mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
26547             resetResolvedTextAlignment();
26548             // Set the new text alignment
26549             mPrivateFlags2 |=
26550                     ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
26551             // Do resolution
26552             resolveTextAlignment();
26553             // Notify change
26554             onRtlPropertiesChanged(getLayoutDirection());
26555             // Refresh
26556             requestLayout();
26557             invalidate(true);
26558         }
26559     }
26560 
26561     /**
26562      * Return the resolved text alignment.
26563      *
26564      * @return the resolved text alignment. Returns one of:
26565      *
26566      * {@link #TEXT_ALIGNMENT_GRAVITY},
26567      * {@link #TEXT_ALIGNMENT_CENTER},
26568      * {@link #TEXT_ALIGNMENT_TEXT_START},
26569      * {@link #TEXT_ALIGNMENT_TEXT_END},
26570      * {@link #TEXT_ALIGNMENT_VIEW_START},
26571      * {@link #TEXT_ALIGNMENT_VIEW_END}
26572      *
26573      * @attr ref android.R.styleable#View_textAlignment
26574      */
26575     @ViewDebug.ExportedProperty(category = "text", mapping = {
26576             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
26577             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
26578             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
26579             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
26580             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
26581             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
26582             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
26583     })
26584     @InspectableProperty(enumMapping = {
26585             @EnumEntry(value = TEXT_ALIGNMENT_GRAVITY, name = "gravity"),
26586             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_START, name = "textStart"),
26587             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_END, name = "textEnd"),
26588             @EnumEntry(value = TEXT_ALIGNMENT_CENTER, name = "center"),
26589             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_START, name = "viewStart"),
26590             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_END, name = "viewEnd")
26591     })
26592     @TextAlignment
getTextAlignment()26593     public int getTextAlignment() {
26594         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
26595                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
26596     }
26597 
26598     /**
26599      * Resolve the text alignment.
26600      *
26601      * @return true if resolution has been done, false otherwise.
26602      *
26603      * @hide
26604      */
resolveTextAlignment()26605     public boolean resolveTextAlignment() {
26606         // Reset any previous text alignment resolution
26607         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
26608 
26609         if (hasRtlSupport()) {
26610             // Set resolved text alignment flag depending on text alignment flag
26611             final int textAlignment = getRawTextAlignment();
26612             switch (textAlignment) {
26613                 case TEXT_ALIGNMENT_INHERIT:
26614                     // Check if we can resolve the text alignment
26615                     if (!canResolveTextAlignment()) {
26616                         // We cannot do the resolution if there is no parent so use the default
26617                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
26618                         // Resolution will need to happen again later
26619                         return false;
26620                     }
26621 
26622                     // Parent has not yet resolved, so we still return the default
26623                     try {
26624                         if (!mParent.isTextAlignmentResolved()) {
26625                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
26626                             // Resolution will need to happen again later
26627                             return false;
26628                         }
26629                     } catch (AbstractMethodError e) {
26630                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
26631                                 " does not fully implement ViewParent", e);
26632                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
26633                                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
26634                         return true;
26635                     }
26636 
26637                     int parentResolvedTextAlignment;
26638                     try {
26639                         parentResolvedTextAlignment = mParent.getTextAlignment();
26640                     } catch (AbstractMethodError e) {
26641                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
26642                                 " does not fully implement ViewParent", e);
26643                         parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
26644                     }
26645                     switch (parentResolvedTextAlignment) {
26646                         case TEXT_ALIGNMENT_GRAVITY:
26647                         case TEXT_ALIGNMENT_TEXT_START:
26648                         case TEXT_ALIGNMENT_TEXT_END:
26649                         case TEXT_ALIGNMENT_CENTER:
26650                         case TEXT_ALIGNMENT_VIEW_START:
26651                         case TEXT_ALIGNMENT_VIEW_END:
26652                             // Resolved text alignment is the same as the parent resolved
26653                             // text alignment
26654                             mPrivateFlags2 |=
26655                                     (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
26656                             break;
26657                         default:
26658                             // Use default resolved text alignment
26659                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
26660                     }
26661                     break;
26662                 case TEXT_ALIGNMENT_GRAVITY:
26663                 case TEXT_ALIGNMENT_TEXT_START:
26664                 case TEXT_ALIGNMENT_TEXT_END:
26665                 case TEXT_ALIGNMENT_CENTER:
26666                 case TEXT_ALIGNMENT_VIEW_START:
26667                 case TEXT_ALIGNMENT_VIEW_END:
26668                     // Resolved text alignment is the same as text alignment
26669                     mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
26670                     break;
26671                 default:
26672                     // Use default resolved text alignment
26673                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
26674             }
26675         } else {
26676             // Use default resolved text alignment
26677             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
26678         }
26679 
26680         // Set the resolved
26681         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
26682         return true;
26683     }
26684 
26685     /**
26686      * Check if text alignment resolution can be done.
26687      *
26688      * @return true if text alignment resolution can be done otherwise return false.
26689      */
canResolveTextAlignment()26690     public boolean canResolveTextAlignment() {
26691         switch (getRawTextAlignment()) {
26692             case TEXT_DIRECTION_INHERIT:
26693                 if (mParent != null) {
26694                     try {
26695                         return mParent.canResolveTextAlignment();
26696                     } catch (AbstractMethodError e) {
26697                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
26698                                 " does not fully implement ViewParent", e);
26699                     }
26700                 }
26701                 return false;
26702 
26703             default:
26704                 return true;
26705         }
26706     }
26707 
26708     /**
26709      * Reset resolved text alignment. Text alignment will be resolved during a call to
26710      * {@link #onMeasure(int, int)}.
26711      *
26712      * @hide
26713      */
26714     @TestApi
resetResolvedTextAlignment()26715     public void resetResolvedTextAlignment() {
26716         // Reset any previous text alignment resolution
26717         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
26718         // Set to default
26719         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
26720     }
26721 
26722     /**
26723      * @return true if text alignment is inherited.
26724      *
26725      * @hide
26726      */
isTextAlignmentInherited()26727     public boolean isTextAlignmentInherited() {
26728         return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
26729     }
26730 
26731     /**
26732      * @return true if text alignment is resolved.
26733      */
isTextAlignmentResolved()26734     public boolean isTextAlignmentResolved() {
26735         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
26736     }
26737 
26738     /**
26739      * Generate a value suitable for use in {@link #setId(int)}.
26740      * This value will not collide with ID values generated at build time by aapt for R.id.
26741      *
26742      * @return a generated ID value
26743      */
generateViewId()26744     public static int generateViewId() {
26745         for (;;) {
26746             final int result = sNextGeneratedId.get();
26747             // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
26748             int newValue = result + 1;
26749             if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
26750             if (sNextGeneratedId.compareAndSet(result, newValue)) {
26751                 return result;
26752             }
26753         }
26754     }
26755 
isViewIdGenerated(int id)26756     private static boolean isViewIdGenerated(int id) {
26757         return (id & 0xFF000000) == 0 && (id & 0x00FFFFFF) != 0;
26758     }
26759 
26760     /**
26761      * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
26762      * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
26763      *                           a normal View or a ViewGroup with
26764      *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
26765      * @hide
26766      */
captureTransitioningViews(List<View> transitioningViews)26767     public void captureTransitioningViews(List<View> transitioningViews) {
26768         if (getVisibility() == View.VISIBLE) {
26769             transitioningViews.add(this);
26770         }
26771     }
26772 
26773     /**
26774      * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
26775      * @param namedElements Will contain all Views in the hierarchy having a transitionName.
26776      * @hide
26777      */
findNamedViews(Map<String, View> namedElements)26778     public void findNamedViews(Map<String, View> namedElements) {
26779         if (getVisibility() == VISIBLE || mGhostView != null) {
26780             String transitionName = getTransitionName();
26781             if (transitionName != null) {
26782                 namedElements.put(transitionName, this);
26783             }
26784         }
26785     }
26786 
26787     /**
26788      * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
26789      * The default implementation does not care the location or event types, but some subclasses
26790      * may use it (such as WebViews).
26791      * @param event The MotionEvent from a mouse
26792      * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
26793      *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
26794      * @see PointerIcon
26795      */
onResolvePointerIcon(MotionEvent event, int pointerIndex)26796     public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
26797         final float x = event.getX(pointerIndex);
26798         final float y = event.getY(pointerIndex);
26799         if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
26800             return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
26801         }
26802         return mPointerIcon;
26803     }
26804 
26805     /**
26806      * Set the pointer icon for the current view.
26807      * Passing {@code null} will restore the pointer icon to its default value.
26808      * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
26809      */
setPointerIcon(PointerIcon pointerIcon)26810     public void setPointerIcon(PointerIcon pointerIcon) {
26811         mPointerIcon = pointerIcon;
26812         if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
26813             return;
26814         }
26815         try {
26816             mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
26817         } catch (RemoteException e) {
26818         }
26819     }
26820 
26821     /**
26822      * Gets the pointer icon for the current view.
26823      */
26824     @InspectableProperty
getPointerIcon()26825     public PointerIcon getPointerIcon() {
26826         return mPointerIcon;
26827     }
26828 
26829     /**
26830      * Checks pointer capture status.
26831      *
26832      * @return true if the view has pointer capture.
26833      * @see #requestPointerCapture()
26834      * @see #hasPointerCapture()
26835      */
hasPointerCapture()26836     public boolean hasPointerCapture() {
26837         final ViewRootImpl viewRootImpl = getViewRootImpl();
26838         if (viewRootImpl == null) {
26839             return false;
26840         }
26841         return viewRootImpl.hasPointerCapture();
26842     }
26843 
26844     /**
26845      * Requests pointer capture mode.
26846      * <p>
26847      * When the window has pointer capture, the mouse pointer icon will disappear and will not
26848      * change its position. Further mouse will be dispatched with the source
26849      * {@link InputDevice#SOURCE_MOUSE_RELATIVE}, and relative position changes will be available
26850      * through {@link MotionEvent#getX} and {@link MotionEvent#getY}. Non-mouse events
26851      * (touchscreens, or stylus) will not be affected.
26852      * <p>
26853      * If the window already has pointer capture, this call does nothing.
26854      * <p>
26855      * The capture may be released through {@link #releasePointerCapture()}, or will be lost
26856      * automatically when the window loses focus.
26857      *
26858      * @see #releasePointerCapture()
26859      * @see #hasPointerCapture()
26860      */
requestPointerCapture()26861     public void requestPointerCapture() {
26862         final ViewRootImpl viewRootImpl = getViewRootImpl();
26863         if (viewRootImpl != null) {
26864             viewRootImpl.requestPointerCapture(true);
26865         }
26866     }
26867 
26868 
26869     /**
26870      * Releases the pointer capture.
26871      * <p>
26872      * If the window does not have pointer capture, this call will do nothing.
26873      * @see #requestPointerCapture()
26874      * @see #hasPointerCapture()
26875      */
releasePointerCapture()26876     public void releasePointerCapture() {
26877         final ViewRootImpl viewRootImpl = getViewRootImpl();
26878         if (viewRootImpl != null) {
26879             viewRootImpl.requestPointerCapture(false);
26880         }
26881     }
26882 
26883     /**
26884      * Called when the window has just acquired or lost pointer capture.
26885      *
26886      * @param hasCapture True if the view now has pointerCapture, false otherwise.
26887      */
26888     @CallSuper
onPointerCaptureChange(boolean hasCapture)26889     public void onPointerCaptureChange(boolean hasCapture) {
26890     }
26891 
26892     /**
26893      * @see #onPointerCaptureChange
26894      */
dispatchPointerCaptureChanged(boolean hasCapture)26895     public void dispatchPointerCaptureChanged(boolean hasCapture) {
26896         onPointerCaptureChange(hasCapture);
26897     }
26898 
26899     /**
26900      * Implement this method to handle captured pointer events
26901      *
26902      * @param event The captured pointer event.
26903      * @return True if the event was handled, false otherwise.
26904      * @see #requestPointerCapture()
26905      */
onCapturedPointerEvent(MotionEvent event)26906     public boolean onCapturedPointerEvent(MotionEvent event) {
26907         return false;
26908     }
26909 
26910     /**
26911      * Interface definition for a callback to be invoked when a captured pointer event
26912      * is being dispatched this view. The callback will be invoked before the event is
26913      * given to the view.
26914      */
26915     public interface OnCapturedPointerListener {
26916         /**
26917          * Called when a captured pointer event is dispatched to a view.
26918          * @param view The view this event has been dispatched to.
26919          * @param event The captured event.
26920          * @return True if the listener has consumed the event, false otherwise.
26921          */
onCapturedPointer(View view, MotionEvent event)26922         boolean onCapturedPointer(View view, MotionEvent event);
26923     }
26924 
26925     /**
26926      * Set a listener to receive callbacks when the pointer capture state of a view changes.
26927      * @param l  The {@link OnCapturedPointerListener} to receive callbacks.
26928      */
setOnCapturedPointerListener(OnCapturedPointerListener l)26929     public void setOnCapturedPointerListener(OnCapturedPointerListener l) {
26930         getListenerInfo().mOnCapturedPointerListener = l;
26931     }
26932 
26933     // Properties
26934     //
26935     /**
26936      * A Property wrapper around the <code>alpha</code> functionality handled by the
26937      * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
26938      */
26939     public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
26940         @Override
26941         public void setValue(View object, float value) {
26942             object.setAlpha(value);
26943         }
26944 
26945         @Override
26946         public Float get(View object) {
26947             return object.getAlpha();
26948         }
26949     };
26950 
26951     /**
26952      * A Property wrapper around the <code>translationX</code> functionality handled by the
26953      * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
26954      */
26955     public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
26956         @Override
26957         public void setValue(View object, float value) {
26958             object.setTranslationX(value);
26959         }
26960 
26961                 @Override
26962         public Float get(View object) {
26963             return object.getTranslationX();
26964         }
26965     };
26966 
26967     /**
26968      * A Property wrapper around the <code>translationY</code> functionality handled by the
26969      * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
26970      */
26971     public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
26972         @Override
26973         public void setValue(View object, float value) {
26974             object.setTranslationY(value);
26975         }
26976 
26977         @Override
26978         public Float get(View object) {
26979             return object.getTranslationY();
26980         }
26981     };
26982 
26983     /**
26984      * A Property wrapper around the <code>translationZ</code> functionality handled by the
26985      * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
26986      */
26987     public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
26988         @Override
26989         public void setValue(View object, float value) {
26990             object.setTranslationZ(value);
26991         }
26992 
26993         @Override
26994         public Float get(View object) {
26995             return object.getTranslationZ();
26996         }
26997     };
26998 
26999     /**
27000      * A Property wrapper around the <code>x</code> functionality handled by the
27001      * {@link View#setX(float)} and {@link View#getX()} methods.
27002      */
27003     public static final Property<View, Float> X = new FloatProperty<View>("x") {
27004         @Override
27005         public void setValue(View object, float value) {
27006             object.setX(value);
27007         }
27008 
27009         @Override
27010         public Float get(View object) {
27011             return object.getX();
27012         }
27013     };
27014 
27015     /**
27016      * A Property wrapper around the <code>y</code> functionality handled by the
27017      * {@link View#setY(float)} and {@link View#getY()} methods.
27018      */
27019     public static final Property<View, Float> Y = new FloatProperty<View>("y") {
27020         @Override
27021         public void setValue(View object, float value) {
27022             object.setY(value);
27023         }
27024 
27025         @Override
27026         public Float get(View object) {
27027             return object.getY();
27028         }
27029     };
27030 
27031     /**
27032      * A Property wrapper around the <code>z</code> functionality handled by the
27033      * {@link View#setZ(float)} and {@link View#getZ()} methods.
27034      */
27035     public static final Property<View, Float> Z = new FloatProperty<View>("z") {
27036         @Override
27037         public void setValue(View object, float value) {
27038             object.setZ(value);
27039         }
27040 
27041         @Override
27042         public Float get(View object) {
27043             return object.getZ();
27044         }
27045     };
27046 
27047     /**
27048      * A Property wrapper around the <code>rotation</code> functionality handled by the
27049      * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
27050      */
27051     public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
27052         @Override
27053         public void setValue(View object, float value) {
27054             object.setRotation(value);
27055         }
27056 
27057         @Override
27058         public Float get(View object) {
27059             return object.getRotation();
27060         }
27061     };
27062 
27063     /**
27064      * A Property wrapper around the <code>rotationX</code> functionality handled by the
27065      * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
27066      */
27067     public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
27068         @Override
27069         public void setValue(View object, float value) {
27070             object.setRotationX(value);
27071         }
27072 
27073         @Override
27074         public Float get(View object) {
27075             return object.getRotationX();
27076         }
27077     };
27078 
27079     /**
27080      * A Property wrapper around the <code>rotationY</code> functionality handled by the
27081      * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
27082      */
27083     public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
27084         @Override
27085         public void setValue(View object, float value) {
27086             object.setRotationY(value);
27087         }
27088 
27089         @Override
27090         public Float get(View object) {
27091             return object.getRotationY();
27092         }
27093     };
27094 
27095     /**
27096      * A Property wrapper around the <code>scaleX</code> functionality handled by the
27097      * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
27098      */
27099     public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
27100         @Override
27101         public void setValue(View object, float value) {
27102             object.setScaleX(value);
27103         }
27104 
27105         @Override
27106         public Float get(View object) {
27107             return object.getScaleX();
27108         }
27109     };
27110 
27111     /**
27112      * A Property wrapper around the <code>scaleY</code> functionality handled by the
27113      * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
27114      */
27115     public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
27116         @Override
27117         public void setValue(View object, float value) {
27118             object.setScaleY(value);
27119         }
27120 
27121         @Override
27122         public Float get(View object) {
27123             return object.getScaleY();
27124         }
27125     };
27126 
27127     /**
27128      * A MeasureSpec encapsulates the layout requirements passed from parent to child.
27129      * Each MeasureSpec represents a requirement for either the width or the height.
27130      * A MeasureSpec is comprised of a size and a mode. There are three possible
27131      * modes:
27132      * <dl>
27133      * <dt>UNSPECIFIED</dt>
27134      * <dd>
27135      * The parent has not imposed any constraint on the child. It can be whatever size
27136      * it wants.
27137      * </dd>
27138      *
27139      * <dt>EXACTLY</dt>
27140      * <dd>
27141      * The parent has determined an exact size for the child. The child is going to be
27142      * given those bounds regardless of how big it wants to be.
27143      * </dd>
27144      *
27145      * <dt>AT_MOST</dt>
27146      * <dd>
27147      * The child can be as large as it wants up to the specified size.
27148      * </dd>
27149      * </dl>
27150      *
27151      * MeasureSpecs are implemented as ints to reduce object allocation. This class
27152      * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
27153      */
27154     public static class MeasureSpec {
27155         private static final int MODE_SHIFT = 30;
27156         private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
27157 
27158         /** @hide */
27159         @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
27160         @Retention(RetentionPolicy.SOURCE)
27161         public @interface MeasureSpecMode {}
27162 
27163         /**
27164          * Measure specification mode: The parent has not imposed any constraint
27165          * on the child. It can be whatever size it wants.
27166          */
27167         public static final int UNSPECIFIED = 0 << MODE_SHIFT;
27168 
27169         /**
27170          * Measure specification mode: The parent has determined an exact size
27171          * for the child. The child is going to be given those bounds regardless
27172          * of how big it wants to be.
27173          */
27174         public static final int EXACTLY     = 1 << MODE_SHIFT;
27175 
27176         /**
27177          * Measure specification mode: The child can be as large as it wants up
27178          * to the specified size.
27179          */
27180         public static final int AT_MOST     = 2 << MODE_SHIFT;
27181 
27182         /**
27183          * Creates a measure specification based on the supplied size and mode.
27184          *
27185          * The mode must always be one of the following:
27186          * <ul>
27187          *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
27188          *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
27189          *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
27190          * </ul>
27191          *
27192          * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
27193          * implementation was such that the order of arguments did not matter
27194          * and overflow in either value could impact the resulting MeasureSpec.
27195          * {@link android.widget.RelativeLayout} was affected by this bug.
27196          * Apps targeting API levels greater than 17 will get the fixed, more strict
27197          * behavior.</p>
27198          *
27199          * @param size the size of the measure specification
27200          * @param mode the mode of the measure specification
27201          * @return the measure specification based on size and mode
27202          */
makeMeasureSpec(@ntRangefrom = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size, @MeasureSpecMode int mode)27203         public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
27204                                           @MeasureSpecMode int mode) {
27205             if (sUseBrokenMakeMeasureSpec) {
27206                 return size + mode;
27207             } else {
27208                 return (size & ~MODE_MASK) | (mode & MODE_MASK);
27209             }
27210         }
27211 
27212         /**
27213          * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
27214          * will automatically get a size of 0. Older apps expect this.
27215          *
27216          * @hide internal use only for compatibility with system widgets and older apps
27217          */
27218         @UnsupportedAppUsage
makeSafeMeasureSpec(int size, int mode)27219         public static int makeSafeMeasureSpec(int size, int mode) {
27220             if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
27221                 return 0;
27222             }
27223             return makeMeasureSpec(size, mode);
27224         }
27225 
27226         /**
27227          * Extracts the mode from the supplied measure specification.
27228          *
27229          * @param measureSpec the measure specification to extract the mode from
27230          * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
27231          *         {@link android.view.View.MeasureSpec#AT_MOST} or
27232          *         {@link android.view.View.MeasureSpec#EXACTLY}
27233          */
27234         @MeasureSpecMode
getMode(int measureSpec)27235         public static int getMode(int measureSpec) {
27236             //noinspection ResourceType
27237             return (measureSpec & MODE_MASK);
27238         }
27239 
27240         /**
27241          * Extracts the size from the supplied measure specification.
27242          *
27243          * @param measureSpec the measure specification to extract the size from
27244          * @return the size in pixels defined in the supplied measure specification
27245          */
getSize(int measureSpec)27246         public static int getSize(int measureSpec) {
27247             return (measureSpec & ~MODE_MASK);
27248         }
27249 
adjust(int measureSpec, int delta)27250         static int adjust(int measureSpec, int delta) {
27251             final int mode = getMode(measureSpec);
27252             int size = getSize(measureSpec);
27253             if (mode == UNSPECIFIED) {
27254                 // No need to adjust size for UNSPECIFIED mode.
27255                 return makeMeasureSpec(size, UNSPECIFIED);
27256             }
27257             size += delta;
27258             if (size < 0) {
27259                 Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
27260                         ") spec: " + toString(measureSpec) + " delta: " + delta);
27261                 size = 0;
27262             }
27263             return makeMeasureSpec(size, mode);
27264         }
27265 
27266         /**
27267          * Returns a String representation of the specified measure
27268          * specification.
27269          *
27270          * @param measureSpec the measure specification to convert to a String
27271          * @return a String with the following format: "MeasureSpec: MODE SIZE"
27272          */
toString(int measureSpec)27273         public static String toString(int measureSpec) {
27274             int mode = getMode(measureSpec);
27275             int size = getSize(measureSpec);
27276 
27277             StringBuilder sb = new StringBuilder("MeasureSpec: ");
27278 
27279             if (mode == UNSPECIFIED)
27280                 sb.append("UNSPECIFIED ");
27281             else if (mode == EXACTLY)
27282                 sb.append("EXACTLY ");
27283             else if (mode == AT_MOST)
27284                 sb.append("AT_MOST ");
27285             else
27286                 sb.append(mode).append(" ");
27287 
27288             sb.append(size);
27289             return sb.toString();
27290         }
27291     }
27292 
27293     private final class CheckForLongPress implements Runnable {
27294         private int mOriginalWindowAttachCount;
27295         private float mX;
27296         private float mY;
27297         private boolean mOriginalPressedState;
27298         /**
27299          * The classification of the long click being checked: one of the
27300          * StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__* constants.
27301          */
27302         private int mClassification;
27303 
27304         @Override
run()27305         public void run() {
27306             if ((mOriginalPressedState == isPressed()) && (mParent != null)
27307                     && mOriginalWindowAttachCount == mWindowAttachCount) {
27308                 recordGestureClassification(mClassification);
27309                 if (performLongClick(mX, mY)) {
27310                     mHasPerformedLongPress = true;
27311                 }
27312             }
27313         }
27314 
setAnchor(float x, float y)27315         public void setAnchor(float x, float y) {
27316             mX = x;
27317             mY = y;
27318         }
27319 
rememberWindowAttachCount()27320         public void rememberWindowAttachCount() {
27321             mOriginalWindowAttachCount = mWindowAttachCount;
27322         }
27323 
rememberPressedState()27324         public void rememberPressedState() {
27325             mOriginalPressedState = isPressed();
27326         }
27327 
setClassification(int classification)27328         public void setClassification(int classification) {
27329             mClassification = classification;
27330         }
27331     }
27332 
27333     private final class CheckForTap implements Runnable {
27334         public float x;
27335         public float y;
27336 
27337         @Override
run()27338         public void run() {
27339             mPrivateFlags &= ~PFLAG_PREPRESSED;
27340             setPressed(true, x, y);
27341             final long delay =
27342                     ViewConfiguration.getLongPressTimeout() - ViewConfiguration.getTapTimeout();
27343             checkForLongClick(delay, x, y, TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
27344         }
27345     }
27346 
27347     private final class PerformClick implements Runnable {
27348         @Override
run()27349         public void run() {
27350             recordGestureClassification(TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP);
27351             performClickInternal();
27352         }
27353     }
27354 
27355     /** Records a classification for the current event stream. */
recordGestureClassification(int classification)27356     private void recordGestureClassification(int classification) {
27357         if (classification == TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION) {
27358             return;
27359         }
27360         // To avoid negatively impacting View performance, the latency and displacement metrics
27361         // are omitted.
27362         StatsLog.write(StatsLog.TOUCH_GESTURE_CLASSIFIED, getClass().getName(), classification);
27363     }
27364 
27365     /**
27366      * This method returns a ViewPropertyAnimator object, which can be used to animate
27367      * specific properties on this View.
27368      *
27369      * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
27370      */
animate()27371     public ViewPropertyAnimator animate() {
27372         if (mAnimator == null) {
27373             mAnimator = new ViewPropertyAnimator(this);
27374         }
27375         return mAnimator;
27376     }
27377 
27378     /**
27379      * Sets the name of the View to be used to identify Views in Transitions.
27380      * Names should be unique in the View hierarchy.
27381      *
27382      * @param transitionName The name of the View to uniquely identify it for Transitions.
27383      */
setTransitionName(String transitionName)27384     public final void setTransitionName(String transitionName) {
27385         mTransitionName = transitionName;
27386     }
27387 
27388     /**
27389      * Returns the name of the View to be used to identify Views in Transitions.
27390      * Names should be unique in the View hierarchy.
27391      *
27392      * <p>This returns null if the View has not been given a name.</p>
27393      *
27394      * @return The name used of the View to be used to identify Views in Transitions or null
27395      * if no name has been given.
27396      */
27397     @ViewDebug.ExportedProperty
27398     @InspectableProperty
getTransitionName()27399     public String getTransitionName() {
27400         return mTransitionName;
27401     }
27402 
27403     /**
27404      * @hide
27405      */
requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId)27406     public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
27407         // Do nothing.
27408     }
27409 
27410     /**
27411      * Interface definition for a callback to be invoked when a hardware key event is
27412      * dispatched to this view. The callback will be invoked before the key event is
27413      * given to the view. This is only useful for hardware keyboards; a software input
27414      * method has no obligation to trigger this listener.
27415      */
27416     public interface OnKeyListener {
27417         /**
27418          * Called when a hardware key is dispatched to a view. This allows listeners to
27419          * get a chance to respond before the target view.
27420          * <p>Key presses in software keyboards will generally NOT trigger this method,
27421          * although some may elect to do so in some situations. Do not assume a
27422          * software input method has to be key-based; even if it is, it may use key presses
27423          * in a different way than you expect, so there is no way to reliably catch soft
27424          * input key presses.
27425          *
27426          * @param v The view the key has been dispatched to.
27427          * @param keyCode The code for the physical key that was pressed
27428          * @param event The KeyEvent object containing full information about
27429          *        the event.
27430          * @return True if the listener has consumed the event, false otherwise.
27431          */
onKey(View v, int keyCode, KeyEvent event)27432         boolean onKey(View v, int keyCode, KeyEvent event);
27433     }
27434 
27435     /**
27436      * Interface definition for a callback to be invoked when a hardware key event hasn't
27437      * been handled by the view hierarchy.
27438      */
27439     public interface OnUnhandledKeyEventListener {
27440         /**
27441          * Called when a hardware key is dispatched to a view after being unhandled during normal
27442          * {@link KeyEvent} dispatch.
27443          *
27444          * @param v The view the key has been dispatched to.
27445          * @param event The KeyEvent object containing information about the event.
27446          * @return {@code true} if the listener has consumed the event, {@code false} otherwise.
27447          */
onUnhandledKeyEvent(View v, KeyEvent event)27448         boolean onUnhandledKeyEvent(View v, KeyEvent event);
27449     }
27450 
27451     /**
27452      * Interface definition for a callback to be invoked when a touch event is
27453      * dispatched to this view. The callback will be invoked before the touch
27454      * event is given to the view.
27455      */
27456     public interface OnTouchListener {
27457         /**
27458          * Called when a touch event is dispatched to a view. This allows listeners to
27459          * get a chance to respond before the target view.
27460          *
27461          * @param v The view the touch event has been dispatched to.
27462          * @param event The MotionEvent object containing full information about
27463          *        the event.
27464          * @return True if the listener has consumed the event, false otherwise.
27465          */
onTouch(View v, MotionEvent event)27466         boolean onTouch(View v, MotionEvent event);
27467     }
27468 
27469     /**
27470      * Interface definition for a callback to be invoked when a hover event is
27471      * dispatched to this view. The callback will be invoked before the hover
27472      * event is given to the view.
27473      */
27474     public interface OnHoverListener {
27475         /**
27476          * Called when a hover event is dispatched to a view. This allows listeners to
27477          * get a chance to respond before the target view.
27478          *
27479          * @param v The view the hover event has been dispatched to.
27480          * @param event The MotionEvent object containing full information about
27481          *        the event.
27482          * @return True if the listener has consumed the event, false otherwise.
27483          */
onHover(View v, MotionEvent event)27484         boolean onHover(View v, MotionEvent event);
27485     }
27486 
27487     /**
27488      * Interface definition for a callback to be invoked when a generic motion event is
27489      * dispatched to this view. The callback will be invoked before the generic motion
27490      * event is given to the view.
27491      */
27492     public interface OnGenericMotionListener {
27493         /**
27494          * Called when a generic motion event is dispatched to a view. This allows listeners to
27495          * get a chance to respond before the target view.
27496          *
27497          * @param v The view the generic motion event has been dispatched to.
27498          * @param event The MotionEvent object containing full information about
27499          *        the event.
27500          * @return True if the listener has consumed the event, false otherwise.
27501          */
onGenericMotion(View v, MotionEvent event)27502         boolean onGenericMotion(View v, MotionEvent event);
27503     }
27504 
27505     /**
27506      * Interface definition for a callback to be invoked when a view has been clicked and held.
27507      */
27508     public interface OnLongClickListener {
27509         /**
27510          * Called when a view has been clicked and held.
27511          *
27512          * @param v The view that was clicked and held.
27513          *
27514          * @return true if the callback consumed the long click, false otherwise.
27515          */
onLongClick(View v)27516         boolean onLongClick(View v);
27517     }
27518 
27519     /**
27520      * Interface definition for a callback to be invoked when a drag is being dispatched
27521      * to this view.  The callback will be invoked before the hosting view's own
27522      * onDrag(event) method.  If the listener wants to fall back to the hosting view's
27523      * onDrag(event) behavior, it should return 'false' from this callback.
27524      *
27525      * <div class="special reference">
27526      * <h3>Developer Guides</h3>
27527      * <p>For a guide to implementing drag and drop features, read the
27528      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
27529      * </div>
27530      */
27531     public interface OnDragListener {
27532         /**
27533          * Called when a drag event is dispatched to a view. This allows listeners
27534          * to get a chance to override base View behavior.
27535          *
27536          * @param v The View that received the drag event.
27537          * @param event The {@link android.view.DragEvent} object for the drag event.
27538          * @return {@code true} if the drag event was handled successfully, or {@code false}
27539          * if the drag event was not handled. Note that {@code false} will trigger the View
27540          * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
27541          */
onDrag(View v, DragEvent event)27542         boolean onDrag(View v, DragEvent event);
27543     }
27544 
27545     /**
27546      * Interface definition for a callback to be invoked when the focus state of
27547      * a view changed.
27548      */
27549     public interface OnFocusChangeListener {
27550         /**
27551          * Called when the focus state of a view has changed.
27552          *
27553          * @param v The view whose state has changed.
27554          * @param hasFocus The new focus state of v.
27555          */
onFocusChange(View v, boolean hasFocus)27556         void onFocusChange(View v, boolean hasFocus);
27557     }
27558 
27559     /**
27560      * Interface definition for a callback to be invoked when a view is clicked.
27561      */
27562     public interface OnClickListener {
27563         /**
27564          * Called when a view has been clicked.
27565          *
27566          * @param v The view that was clicked.
27567          */
onClick(View v)27568         void onClick(View v);
27569     }
27570 
27571     /**
27572      * Interface definition for a callback to be invoked when a view is context clicked.
27573      */
27574     public interface OnContextClickListener {
27575         /**
27576          * Called when a view is context clicked.
27577          *
27578          * @param v The view that has been context clicked.
27579          * @return true if the callback consumed the context click, false otherwise.
27580          */
onContextClick(View v)27581         boolean onContextClick(View v);
27582     }
27583 
27584     /**
27585      * Interface definition for a callback to be invoked when the context menu
27586      * for this view is being built.
27587      */
27588     public interface OnCreateContextMenuListener {
27589         /**
27590          * Called when the context menu for this view is being built. It is not
27591          * safe to hold onto the menu after this method returns.
27592          *
27593          * @param menu The context menu that is being built
27594          * @param v The view for which the context menu is being built
27595          * @param menuInfo Extra information about the item for which the
27596          *            context menu should be shown. This information will vary
27597          *            depending on the class of v.
27598          */
onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)27599         void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
27600     }
27601 
27602     /**
27603      * Interface definition for a callback to be invoked when the status bar changes
27604      * visibility.  This reports <strong>global</strong> changes to the system UI
27605      * state, not what the application is requesting.
27606      *
27607      * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
27608      */
27609     public interface OnSystemUiVisibilityChangeListener {
27610         /**
27611          * Called when the status bar changes visibility because of a call to
27612          * {@link View#setSystemUiVisibility(int)}.
27613          *
27614          * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
27615          * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
27616          * This tells you the <strong>global</strong> state of these UI visibility
27617          * flags, not what your app is currently applying.
27618          */
onSystemUiVisibilityChange(int visibility)27619         public void onSystemUiVisibilityChange(int visibility);
27620     }
27621 
27622     /**
27623      * Interface definition for a callback to be invoked when this view is attached
27624      * or detached from its window.
27625      */
27626     public interface OnAttachStateChangeListener {
27627         /**
27628          * Called when the view is attached to a window.
27629          * @param v The view that was attached
27630          */
onViewAttachedToWindow(View v)27631         public void onViewAttachedToWindow(View v);
27632         /**
27633          * Called when the view is detached from a window.
27634          * @param v The view that was detached
27635          */
onViewDetachedFromWindow(View v)27636         public void onViewDetachedFromWindow(View v);
27637     }
27638 
27639     /**
27640      * Listener for applying window insets on a view in a custom way.
27641      *
27642      * <p>Apps may choose to implement this interface if they want to apply custom policy
27643      * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
27644      * is set, its
27645      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
27646      * method will be called instead of the View's own
27647      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
27648      * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
27649      * the View's normal behavior as part of its own.</p>
27650      */
27651     public interface OnApplyWindowInsetsListener {
27652         /**
27653          * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
27654          * on a View, this listener method will be called instead of the view's own
27655          * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
27656          *
27657          * @param v The view applying window insets
27658          * @param insets The insets to apply
27659          * @return The insets supplied, minus any insets that were consumed
27660          */
onApplyWindowInsets(View v, WindowInsets insets)27661         public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
27662     }
27663 
27664     private final class UnsetPressedState implements Runnable {
27665         @Override
run()27666         public void run() {
27667             setPressed(false);
27668         }
27669     }
27670 
27671     /**
27672      * When a view becomes invisible checks if autofill considers the view invisible too. This
27673      * happens after the regular removal operation to make sure the operation is finished by the
27674      * time this is called.
27675      */
27676     private static class VisibilityChangeForAutofillHandler extends Handler {
27677         private final AutofillManager mAfm;
27678         private final View mView;
27679 
VisibilityChangeForAutofillHandler(@onNull AutofillManager afm, @NonNull View view)27680         private VisibilityChangeForAutofillHandler(@NonNull AutofillManager afm,
27681                 @NonNull View view) {
27682             mAfm = afm;
27683             mView = view;
27684         }
27685 
27686         @Override
handleMessage(Message msg)27687         public void handleMessage(Message msg) {
27688             mAfm.notifyViewVisibilityChanged(mView, mView.isShown());
27689         }
27690     }
27691 
27692     /**
27693      * Base class for derived classes that want to save and restore their own
27694      * state in {@link android.view.View#onSaveInstanceState()}.
27695      */
27696     public static class BaseSavedState extends AbsSavedState {
27697         static final int START_ACTIVITY_REQUESTED_WHO_SAVED = 0b1;
27698         static final int IS_AUTOFILLED = 0b10;
27699         static final int AUTOFILL_ID = 0b100;
27700 
27701         // Flags that describe what data in this state is valid
27702         int mSavedData;
27703         String mStartActivityRequestWhoSaved;
27704         boolean mIsAutofilled;
27705         int mAutofillViewId;
27706 
27707         /**
27708          * Constructor used when reading from a parcel. Reads the state of the superclass.
27709          *
27710          * @param source parcel to read from
27711          */
BaseSavedState(Parcel source)27712         public BaseSavedState(Parcel source) {
27713             this(source, null);
27714         }
27715 
27716         /**
27717          * Constructor used when reading from a parcel using a given class loader.
27718          * Reads the state of the superclass.
27719          *
27720          * @param source parcel to read from
27721          * @param loader ClassLoader to use for reading
27722          */
BaseSavedState(Parcel source, ClassLoader loader)27723         public BaseSavedState(Parcel source, ClassLoader loader) {
27724             super(source, loader);
27725             mSavedData = source.readInt();
27726             mStartActivityRequestWhoSaved = source.readString();
27727             mIsAutofilled = source.readBoolean();
27728             mAutofillViewId = source.readInt();
27729         }
27730 
27731         /**
27732          * Constructor called by derived classes when creating their SavedState objects
27733          *
27734          * @param superState The state of the superclass of this view
27735          */
BaseSavedState(Parcelable superState)27736         public BaseSavedState(Parcelable superState) {
27737             super(superState);
27738         }
27739 
27740         @Override
writeToParcel(Parcel out, int flags)27741         public void writeToParcel(Parcel out, int flags) {
27742             super.writeToParcel(out, flags);
27743 
27744             out.writeInt(mSavedData);
27745             out.writeString(mStartActivityRequestWhoSaved);
27746             out.writeBoolean(mIsAutofilled);
27747             out.writeInt(mAutofillViewId);
27748         }
27749 
27750         public static final @android.annotation.NonNull Parcelable.Creator<BaseSavedState> CREATOR
27751                 = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
27752             @Override
27753             public BaseSavedState createFromParcel(Parcel in) {
27754                 return new BaseSavedState(in);
27755             }
27756 
27757             @Override
27758             public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
27759                 return new BaseSavedState(in, loader);
27760             }
27761 
27762             @Override
27763             public BaseSavedState[] newArray(int size) {
27764                 return new BaseSavedState[size];
27765             }
27766         };
27767     }
27768 
27769     /**
27770      * A set of information given to a view when it is attached to its parent
27771      * window.
27772      */
27773     final static class AttachInfo {
27774         interface Callbacks {
playSoundEffect(int effectId)27775             void playSoundEffect(int effectId);
performHapticFeedback(int effectId, boolean always)27776             boolean performHapticFeedback(int effectId, boolean always);
27777         }
27778 
27779         /**
27780          * InvalidateInfo is used to post invalidate(int, int, int, int) messages
27781          * to a Handler. This class contains the target (View) to invalidate and
27782          * the coordinates of the dirty rectangle.
27783          *
27784          * For performance purposes, this class also implements a pool of up to
27785          * POOL_LIMIT objects that get reused. This reduces memory allocations
27786          * whenever possible.
27787          */
27788         static class InvalidateInfo {
27789             private static final int POOL_LIMIT = 10;
27790 
27791             private static final SynchronizedPool<InvalidateInfo> sPool =
27792                     new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
27793 
27794             @UnsupportedAppUsage
27795             View target;
27796 
27797             @UnsupportedAppUsage
27798             int left;
27799             @UnsupportedAppUsage
27800             int top;
27801             @UnsupportedAppUsage
27802             int right;
27803             @UnsupportedAppUsage
27804             int bottom;
27805 
obtain()27806             public static InvalidateInfo obtain() {
27807                 InvalidateInfo instance = sPool.acquire();
27808                 return (instance != null) ? instance : new InvalidateInfo();
27809             }
27810 
recycle()27811             public void recycle() {
27812                 target = null;
27813                 sPool.release(this);
27814             }
27815         }
27816 
27817         @UnsupportedAppUsage
27818         final IWindowSession mSession;
27819 
27820         @UnsupportedAppUsage
27821         final IWindow mWindow;
27822 
27823         final IBinder mWindowToken;
27824 
27825         Display mDisplay;
27826 
27827         final Callbacks mRootCallbacks;
27828 
27829         IWindowId mIWindowId;
27830         WindowId mWindowId;
27831 
27832         /**
27833          * The top view of the hierarchy.
27834          */
27835         View mRootView;
27836 
27837         IBinder mPanelParentWindowToken;
27838 
27839         boolean mHardwareAccelerated;
27840         boolean mHardwareAccelerationRequested;
27841         ThreadedRenderer mThreadedRenderer;
27842         List<RenderNode> mPendingAnimatingRenderNodes;
27843 
27844         /**
27845          * The state of the display to which the window is attached, as reported
27846          * by {@link Display#getState()}.  Note that the display state constants
27847          * declared by {@link Display} do not exactly line up with the screen state
27848          * constants declared by {@link View} (there are more display states than
27849          * screen states).
27850          */
27851         @UnsupportedAppUsage
27852         int mDisplayState = Display.STATE_UNKNOWN;
27853 
27854         /**
27855          * Scale factor used by the compatibility mode
27856          */
27857         @UnsupportedAppUsage
27858         float mApplicationScale;
27859 
27860         /**
27861          * Indicates whether the application is in compatibility mode
27862          */
27863         @UnsupportedAppUsage
27864         boolean mScalingRequired;
27865 
27866         /**
27867          * Left position of this view's window
27868          */
27869         int mWindowLeft;
27870 
27871         /**
27872          * Top position of this view's window
27873          */
27874         int mWindowTop;
27875 
27876         /**
27877          * Indicates whether views need to use 32-bit drawing caches
27878          */
27879         boolean mUse32BitDrawingCache;
27880 
27881         /**
27882          * For windows that are full-screen but using insets to layout inside
27883          * of the screen areas, these are the current insets to appear inside
27884          * the overscan area of the display.
27885          */
27886         final Rect mOverscanInsets = new Rect();
27887 
27888         /**
27889          * For windows that are full-screen but using insets to layout inside
27890          * of the screen decorations, these are the current insets for the
27891          * content of the window.
27892          */
27893         @UnsupportedAppUsage
27894         final Rect mContentInsets = new Rect();
27895 
27896         /**
27897          * For windows that are full-screen but using insets to layout inside
27898          * of the screen decorations, these are the current insets for the
27899          * actual visible parts of the window.
27900          */
27901         @UnsupportedAppUsage
27902         final Rect mVisibleInsets = new Rect();
27903 
27904         /**
27905          * For windows that are full-screen but using insets to layout inside
27906          * of the screen decorations, these are the current insets for the
27907          * stable system windows.
27908          */
27909         @UnsupportedAppUsage
27910         final Rect mStableInsets = new Rect();
27911 
27912         final DisplayCutout.ParcelableWrapper mDisplayCutout =
27913                 new DisplayCutout.ParcelableWrapper(DisplayCutout.NO_CUTOUT);
27914 
27915         /**
27916          * For windows that include areas that are not covered by real surface these are the outsets
27917          * for real surface.
27918          */
27919         final Rect mOutsets = new Rect();
27920 
27921         /**
27922          * In multi-window we force show the system bars. Because we don't want that the surface
27923          * size changes in this mode, we instead have a flag whether the system bars sizes should
27924          * always be consumed, so the app is treated like there are no virtual system bars at all.
27925          */
27926         boolean mAlwaysConsumeSystemBars;
27927 
27928         /**
27929          * The internal insets given by this window.  This value is
27930          * supplied by the client (through
27931          * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
27932          * be given to the window manager when changed to be used in laying
27933          * out windows behind it.
27934          */
27935         @UnsupportedAppUsage
27936         final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
27937                 = new ViewTreeObserver.InternalInsetsInfo();
27938 
27939         /**
27940          * Set to true when mGivenInternalInsets is non-empty.
27941          */
27942         boolean mHasNonEmptyGivenInternalInsets;
27943 
27944         /**
27945          * All views in the window's hierarchy that serve as scroll containers,
27946          * used to determine if the window can be resized or must be panned
27947          * to adjust for a soft input area.
27948          */
27949         @UnsupportedAppUsage
27950         final ArrayList<View> mScrollContainers = new ArrayList<View>();
27951 
27952         @UnsupportedAppUsage
27953         final KeyEvent.DispatcherState mKeyDispatchState
27954                 = new KeyEvent.DispatcherState();
27955 
27956         /**
27957          * Indicates whether the view's window currently has the focus.
27958          */
27959         @UnsupportedAppUsage
27960         boolean mHasWindowFocus;
27961 
27962         /**
27963          * The current visibility of the window.
27964          */
27965         int mWindowVisibility;
27966 
27967         /**
27968          * Indicates the time at which drawing started to occur.
27969          */
27970         @UnsupportedAppUsage
27971         long mDrawingTime;
27972 
27973         /**
27974          * Indicates whether the view's window is currently in touch mode.
27975          */
27976         @UnsupportedAppUsage
27977         boolean mInTouchMode;
27978 
27979         /**
27980          * Indicates whether the view has requested unbuffered input dispatching for the current
27981          * event stream.
27982          */
27983         boolean mUnbufferedDispatchRequested;
27984 
27985         /**
27986          * Indicates that ViewAncestor should trigger a global layout change
27987          * the next time it performs a traversal
27988          */
27989         @UnsupportedAppUsage
27990         boolean mRecomputeGlobalAttributes;
27991 
27992         /**
27993          * Always report new attributes at next traversal.
27994          */
27995         boolean mForceReportNewAttributes;
27996 
27997         /**
27998          * Set during a traveral if any views want to keep the screen on.
27999          */
28000         @UnsupportedAppUsage
28001         boolean mKeepScreenOn;
28002 
28003         /**
28004          * Set during a traveral if the light center needs to be updated.
28005          */
28006         boolean mNeedsUpdateLightCenter;
28007 
28008         /**
28009          * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
28010          */
28011         int mSystemUiVisibility;
28012 
28013         /**
28014          * Hack to force certain system UI visibility flags to be cleared.
28015          */
28016         int mDisabledSystemUiVisibility;
28017 
28018         /**
28019          * Last global system UI visibility reported by the window manager.
28020          */
28021         int mGlobalSystemUiVisibility = -1;
28022 
28023         /**
28024          * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
28025          * attached.
28026          */
28027         boolean mHasSystemUiListeners;
28028 
28029         /**
28030          * Set if the window has requested to extend into the overscan region
28031          * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
28032          */
28033         boolean mOverscanRequested;
28034 
28035         /**
28036          * Set if the visibility of any views has changed.
28037          */
28038         @UnsupportedAppUsage
28039         boolean mViewVisibilityChanged;
28040 
28041         /**
28042          * Set to true if a view has been scrolled.
28043          */
28044         @UnsupportedAppUsage
28045         boolean mViewScrollChanged;
28046 
28047         /**
28048          * Set to true if a pointer event is currently being handled.
28049          */
28050         boolean mHandlingPointerEvent;
28051 
28052         /**
28053          * Global to the view hierarchy used as a temporary for dealing with
28054          * x/y points in the transparent region computations.
28055          */
28056         final int[] mTransparentLocation = new int[2];
28057 
28058         /**
28059          * Global to the view hierarchy used as a temporary for dealing with
28060          * x/y points in the ViewGroup.invalidateChild implementation.
28061          */
28062         final int[] mInvalidateChildLocation = new int[2];
28063 
28064         /**
28065          * Global to the view hierarchy used as a temporary for dealing with
28066          * computing absolute on-screen location.
28067          */
28068         final int[] mTmpLocation = new int[2];
28069 
28070         /**
28071          * Global to the view hierarchy used as a temporary for dealing with
28072          * x/y location when view is transformed.
28073          */
28074         final float[] mTmpTransformLocation = new float[2];
28075 
28076         /**
28077          * The view tree observer used to dispatch global events like
28078          * layout, pre-draw, touch mode change, etc.
28079          */
28080         @UnsupportedAppUsage
28081         final ViewTreeObserver mTreeObserver;
28082 
28083         /**
28084          * A Canvas used by the view hierarchy to perform bitmap caching.
28085          */
28086         Canvas mCanvas;
28087 
28088         /**
28089          * The view root impl.
28090          */
28091         final ViewRootImpl mViewRootImpl;
28092 
28093         /**
28094          * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
28095          * handler can be used to pump events in the UI events queue.
28096          */
28097         @UnsupportedAppUsage
28098         final Handler mHandler;
28099 
28100         /**
28101          * Temporary for use in computing invalidate rectangles while
28102          * calling up the hierarchy.
28103          */
28104         final Rect mTmpInvalRect = new Rect();
28105 
28106         /**
28107          * Temporary for use in computing hit areas with transformed views
28108          */
28109         final RectF mTmpTransformRect = new RectF();
28110 
28111         /**
28112          * Temporary for use in computing hit areas with transformed views
28113          */
28114         final RectF mTmpTransformRect1 = new RectF();
28115 
28116         /**
28117          * Temporary list of rectanges.
28118          */
28119         final List<RectF> mTmpRectList = new ArrayList<>();
28120 
28121         /**
28122          * Temporary for use in transforming invalidation rect
28123          */
28124         final Matrix mTmpMatrix = new Matrix();
28125 
28126         /**
28127          * Temporary for use in transforming invalidation rect
28128          */
28129         final Transformation mTmpTransformation = new Transformation();
28130 
28131         /**
28132          * Temporary for use in querying outlines from OutlineProviders
28133          */
28134         final Outline mTmpOutline = new Outline();
28135 
28136         /**
28137          * Temporary list for use in collecting focusable descendents of a view.
28138          */
28139         final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
28140 
28141         /**
28142          * The id of the window for accessibility purposes.
28143          */
28144         int mAccessibilityWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
28145 
28146         /**
28147          * Flags related to accessibility processing.
28148          *
28149          * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
28150          * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
28151          */
28152         int mAccessibilityFetchFlags;
28153 
28154         /**
28155          * The drawable for highlighting accessibility focus.
28156          */
28157         Drawable mAccessibilityFocusDrawable;
28158 
28159         /**
28160          * The drawable for highlighting autofilled views.
28161          *
28162          * @see #isAutofilled()
28163          */
28164         Drawable mAutofilledDrawable;
28165 
28166         /**
28167          * Show where the margins, bounds and layout bounds are for each view.
28168          */
28169         boolean mDebugLayout = DisplayProperties.debug_layout().orElse(false);
28170 
28171         /**
28172          * Point used to compute visible regions.
28173          */
28174         final Point mPoint = new Point();
28175 
28176         /**
28177          * Used to track which View originated a requestLayout() call, used when
28178          * requestLayout() is called during layout.
28179          */
28180         View mViewRequestingLayout;
28181 
28182         /**
28183          * Used to track the identity of the current drag operation.
28184          */
28185         IBinder mDragToken;
28186 
28187         /**
28188          * The drag shadow surface for the current drag operation.
28189          */
28190         public Surface mDragSurface;
28191 
28192 
28193         /**
28194          * The view that currently has a tooltip displayed.
28195          */
28196         View mTooltipHost;
28197 
28198         /**
28199          * Creates a new set of attachment information with the specified
28200          * events handler and thread.
28201          *
28202          * @param handler the events handler the view must use
28203          */
AttachInfo(IWindowSession session, IWindow window, Display display, ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer, Context context)28204         AttachInfo(IWindowSession session, IWindow window, Display display,
28205                 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer,
28206                 Context context) {
28207             mSession = session;
28208             mWindow = window;
28209             mWindowToken = window.asBinder();
28210             mDisplay = display;
28211             mViewRootImpl = viewRootImpl;
28212             mHandler = handler;
28213             mRootCallbacks = effectPlayer;
28214             mTreeObserver = new ViewTreeObserver(context);
28215         }
28216     }
28217 
28218     /**
28219      * <p>ScrollabilityCache holds various fields used by a View when scrolling
28220      * is supported. This avoids keeping too many unused fields in most
28221      * instances of View.</p>
28222      */
28223     private static class ScrollabilityCache implements Runnable {
28224 
28225         /**
28226          * Scrollbars are not visible
28227          */
28228         public static final int OFF = 0;
28229 
28230         /**
28231          * Scrollbars are visible
28232          */
28233         public static final int ON = 1;
28234 
28235         /**
28236          * Scrollbars are fading away
28237          */
28238         public static final int FADING = 2;
28239 
28240         public boolean fadeScrollBars;
28241 
28242         public int fadingEdgeLength;
28243         public int scrollBarDefaultDelayBeforeFade;
28244         public int scrollBarFadeDuration;
28245 
28246         public int scrollBarSize;
28247         public int scrollBarMinTouchTarget;
28248         @UnsupportedAppUsage
28249         public ScrollBarDrawable scrollBar;
28250         public float[] interpolatorValues;
28251         @UnsupportedAppUsage
28252         public View host;
28253 
28254         public final Paint paint;
28255         public final Matrix matrix;
28256         public Shader shader;
28257 
28258         public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
28259 
28260         private static final float[] OPAQUE = { 255 };
28261         private static final float[] TRANSPARENT = { 0.0f };
28262 
28263         /**
28264          * When fading should start. This time moves into the future every time
28265          * a new scroll happens. Measured based on SystemClock.uptimeMillis()
28266          */
28267         public long fadeStartTime;
28268 
28269 
28270         /**
28271          * The current state of the scrollbars: ON, OFF, or FADING
28272          */
28273         @UnsupportedAppUsage
28274         public int state = OFF;
28275 
28276         private int mLastColor;
28277 
28278         public final Rect mScrollBarBounds = new Rect();
28279         public final Rect mScrollBarTouchBounds = new Rect();
28280 
28281         public static final int NOT_DRAGGING = 0;
28282         public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
28283         public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
28284         public int mScrollBarDraggingState = NOT_DRAGGING;
28285 
28286         public float mScrollBarDraggingPos = 0;
28287 
ScrollabilityCache(ViewConfiguration configuration, View host)28288         public ScrollabilityCache(ViewConfiguration configuration, View host) {
28289             fadingEdgeLength = configuration.getScaledFadingEdgeLength();
28290             scrollBarSize = configuration.getScaledScrollBarSize();
28291             scrollBarMinTouchTarget = configuration.getScaledMinScrollbarTouchTarget();
28292             scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
28293             scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
28294 
28295             paint = new Paint();
28296             matrix = new Matrix();
28297             // use use a height of 1, and then wack the matrix each time we
28298             // actually use it.
28299             shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
28300             paint.setShader(shader);
28301             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
28302 
28303             this.host = host;
28304         }
28305 
setFadeColor(int color)28306         public void setFadeColor(int color) {
28307             if (color != mLastColor) {
28308                 mLastColor = color;
28309 
28310                 if (color != 0) {
28311                     shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
28312                             color & 0x00FFFFFF, Shader.TileMode.CLAMP);
28313                     paint.setShader(shader);
28314                     // Restore the default transfer mode (src_over)
28315                     paint.setXfermode(null);
28316                 } else {
28317                     shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
28318                     paint.setShader(shader);
28319                     paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
28320                 }
28321             }
28322         }
28323 
run()28324         public void run() {
28325             long now = AnimationUtils.currentAnimationTimeMillis();
28326             if (now >= fadeStartTime) {
28327 
28328                 // the animation fades the scrollbars out by changing
28329                 // the opacity (alpha) from fully opaque to fully
28330                 // transparent
28331                 int nextFrame = (int) now;
28332                 int framesCount = 0;
28333 
28334                 Interpolator interpolator = scrollBarInterpolator;
28335 
28336                 // Start opaque
28337                 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
28338 
28339                 // End transparent
28340                 nextFrame += scrollBarFadeDuration;
28341                 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
28342 
28343                 state = FADING;
28344 
28345                 // Kick off the fade animation
28346                 host.invalidate(true);
28347             }
28348         }
28349     }
28350 
28351     /**
28352      * Resuable callback for sending
28353      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
28354      */
28355     private class SendViewScrolledAccessibilityEvent implements Runnable {
28356         public volatile boolean mIsPending;
28357         public int mDeltaX;
28358         public int mDeltaY;
28359 
post(int dx, int dy)28360         public void post(int dx, int dy) {
28361             mDeltaX += dx;
28362             mDeltaY += dy;
28363             if (!mIsPending) {
28364                 mIsPending = true;
28365                 postDelayed(this, ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
28366             }
28367         }
28368 
28369         @Override
run()28370         public void run() {
28371             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
28372                 AccessibilityEvent event = AccessibilityEvent.obtain(
28373                         AccessibilityEvent.TYPE_VIEW_SCROLLED);
28374                 event.setScrollDeltaX(mDeltaX);
28375                 event.setScrollDeltaY(mDeltaY);
28376                 sendAccessibilityEventUnchecked(event);
28377             }
28378             reset();
28379         }
28380 
reset()28381         private void reset() {
28382             mIsPending = false;
28383             mDeltaX = 0;
28384             mDeltaY = 0;
28385         }
28386     }
28387 
28388     /**
28389      * Remove the pending callback for sending a
28390      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
28391      */
28392     @UnsupportedAppUsage
cancel(@ullable SendViewScrolledAccessibilityEvent callback)28393     private void cancel(@Nullable SendViewScrolledAccessibilityEvent callback) {
28394         if (callback == null || !callback.mIsPending) return;
28395         removeCallbacks(callback);
28396         callback.reset();
28397     }
28398 
28399     /**
28400      * <p>
28401      * This class represents a delegate that can be registered in a {@link View}
28402      * to enhance accessibility support via composition rather via inheritance.
28403      * It is specifically targeted to widget developers that extend basic View
28404      * classes i.e. classes in package android.view, that would like their
28405      * applications to be backwards compatible.
28406      * </p>
28407      * <div class="special reference">
28408      * <h3>Developer Guides</h3>
28409      * <p>For more information about making applications accessible, read the
28410      * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
28411      * developer guide.</p>
28412      * </div>
28413      * <p>
28414      * A scenario in which a developer would like to use an accessibility delegate
28415      * is overriding a method introduced in a later API version than the minimal API
28416      * version supported by the application. For example, the method
28417      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
28418      * in API version 4 when the accessibility APIs were first introduced. If a
28419      * developer would like their application to run on API version 4 devices (assuming
28420      * all other APIs used by the application are version 4 or lower) and take advantage
28421      * of this method, instead of overriding the method which would break the application's
28422      * backwards compatibility, they can override the corresponding method in this
28423      * delegate and register the delegate in the target View if the API version of
28424      * the system is high enough, i.e. the API version is the same as or higher than the API
28425      * version that introduced
28426      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
28427      * </p>
28428      * <p>
28429      * Here is an example implementation:
28430      * </p>
28431      * <code><pre><p>
28432      * if (Build.VERSION.SDK_INT >= 14) {
28433      *     // If the API version is equal of higher than the version in
28434      *     // which onInitializeAccessibilityNodeInfo was introduced we
28435      *     // register a delegate with a customized implementation.
28436      *     View view = findViewById(R.id.view_id);
28437      *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
28438      *         public void onInitializeAccessibilityNodeInfo(View host,
28439      *                 AccessibilityNodeInfo info) {
28440      *             // Let the default implementation populate the info.
28441      *             super.onInitializeAccessibilityNodeInfo(host, info);
28442      *             // Set some other information.
28443      *             info.setEnabled(host.isEnabled());
28444      *         }
28445      *     });
28446      * }
28447      * </code></pre></p>
28448      * <p>
28449      * This delegate contains methods that correspond to the accessibility methods
28450      * in View. If a delegate has been specified the implementation in View hands
28451      * off handling to the corresponding method in this delegate. The default
28452      * implementation the delegate methods behaves exactly as the corresponding
28453      * method in View for the case of no accessibility delegate been set. Hence,
28454      * to customize the behavior of a View method, clients can override only the
28455      * corresponding delegate method without altering the behavior of the rest
28456      * accessibility related methods of the host view.
28457      * </p>
28458      * <p>
28459      * <strong>Note:</strong> On platform versions prior to
28460      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
28461      * views in the {@code android.widget.*} package are called <i>before</i>
28462      * host methods. This prevents certain properties such as class name from
28463      * being modified by overriding
28464      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
28465      * as any changes will be overwritten by the host class.
28466      * <p>
28467      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
28468      * methods are called <i>after</i> host methods, which all properties to be
28469      * modified without being overwritten by the host class.
28470      */
28471     public static class AccessibilityDelegate {
28472 
28473         /**
28474          * Sends an accessibility event of the given type. If accessibility is not
28475          * enabled this method has no effect.
28476          * <p>
28477          * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
28478          *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
28479          * been set.
28480          * </p>
28481          *
28482          * @param host The View hosting the delegate.
28483          * @param eventType The type of the event to send.
28484          *
28485          * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
28486          */
sendAccessibilityEvent(View host, int eventType)28487         public void sendAccessibilityEvent(View host, int eventType) {
28488             host.sendAccessibilityEventInternal(eventType);
28489         }
28490 
28491         /**
28492          * Performs the specified accessibility action on the view. For
28493          * possible accessibility actions look at {@link AccessibilityNodeInfo}.
28494          * <p>
28495          * The default implementation behaves as
28496          * {@link View#performAccessibilityAction(int, Bundle)
28497          *  View#performAccessibilityAction(int, Bundle)} for the case of
28498          *  no accessibility delegate been set.
28499          * </p>
28500          *
28501          * @param action The action to perform.
28502          * @return Whether the action was performed.
28503          *
28504          * @see View#performAccessibilityAction(int, Bundle)
28505          *      View#performAccessibilityAction(int, Bundle)
28506          */
performAccessibilityAction(View host, int action, Bundle args)28507         public boolean performAccessibilityAction(View host, int action, Bundle args) {
28508             return host.performAccessibilityActionInternal(action, args);
28509         }
28510 
28511         /**
28512          * Sends an accessibility event. This method behaves exactly as
28513          * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
28514          * empty {@link AccessibilityEvent} and does not perform a check whether
28515          * accessibility is enabled.
28516          * <p>
28517          * The default implementation behaves as
28518          * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
28519          *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
28520          * the case of no accessibility delegate been set.
28521          * </p>
28522          *
28523          * @param host The View hosting the delegate.
28524          * @param event The event to send.
28525          *
28526          * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
28527          *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
28528          */
sendAccessibilityEventUnchecked(View host, AccessibilityEvent event)28529         public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
28530             host.sendAccessibilityEventUncheckedInternal(event);
28531         }
28532 
28533         /**
28534          * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
28535          * to its children for adding their text content to the event.
28536          * <p>
28537          * The default implementation behaves as
28538          * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
28539          *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
28540          * the case of no accessibility delegate been set.
28541          * </p>
28542          *
28543          * @param host The View hosting the delegate.
28544          * @param event The event.
28545          * @return True if the event population was completed.
28546          *
28547          * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
28548          *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
28549          */
dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event)28550         public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
28551             return host.dispatchPopulateAccessibilityEventInternal(event);
28552         }
28553 
28554         /**
28555          * Gives a chance to the host View to populate the accessibility event with its
28556          * text content.
28557          * <p>
28558          * The default implementation behaves as
28559          * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
28560          *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
28561          * the case of no accessibility delegate been set.
28562          * </p>
28563          *
28564          * @param host The View hosting the delegate.
28565          * @param event The accessibility event which to populate.
28566          *
28567          * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
28568          *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
28569          */
onPopulateAccessibilityEvent(View host, AccessibilityEvent event)28570         public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
28571             host.onPopulateAccessibilityEventInternal(event);
28572         }
28573 
28574         /**
28575          * Initializes an {@link AccessibilityEvent} with information about the
28576          * the host View which is the event source.
28577          * <p>
28578          * The default implementation behaves as
28579          * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
28580          *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
28581          * the case of no accessibility delegate been set.
28582          * </p>
28583          *
28584          * @param host The View hosting the delegate.
28585          * @param event The event to initialize.
28586          *
28587          * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
28588          *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
28589          */
onInitializeAccessibilityEvent(View host, AccessibilityEvent event)28590         public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
28591             host.onInitializeAccessibilityEventInternal(event);
28592         }
28593 
28594         /**
28595          * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
28596          * <p>
28597          * The default implementation behaves as
28598          * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
28599          *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
28600          * the case of no accessibility delegate been set.
28601          * </p>
28602          *
28603          * @param host The View hosting the delegate.
28604          * @param info The instance to initialize.
28605          *
28606          * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
28607          *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
28608          */
onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info)28609         public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
28610             host.onInitializeAccessibilityNodeInfoInternal(info);
28611         }
28612 
28613         /**
28614          * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
28615          * additional data.
28616          * <p>
28617          * This method only needs to be implemented if the View offers to provide additional data.
28618          * </p>
28619          * <p>
28620          * The default implementation behaves as
28621          * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, String, Bundle)
28622          * for the case where no accessibility delegate is set.
28623          * </p>
28624          *
28625          * @param host The View hosting the delegate. Never {@code null}.
28626          * @param info The info to which to add the extra data. Never {@code null}.
28627          * @param extraDataKey A key specifying the type of extra data to add to the info. The
28628          *                     extra data should be added to the {@link Bundle} returned by
28629          *                     the info's {@link AccessibilityNodeInfo#getExtras} method.  Never
28630          *                     {@code null}.
28631          * @param arguments A {@link Bundle} holding any arguments relevant for this request.
28632          *                  May be {@code null} if the if the service provided no arguments.
28633          *
28634          * @see AccessibilityNodeInfo#setAvailableExtraData(List)
28635          */
addExtraDataToAccessibilityNodeInfo(@onNull View host, @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey, @Nullable Bundle arguments)28636         public void addExtraDataToAccessibilityNodeInfo(@NonNull View host,
28637                 @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
28638                 @Nullable Bundle arguments) {
28639             host.addExtraDataToAccessibilityNodeInfo(info, extraDataKey, arguments);
28640         }
28641 
28642         /**
28643          * Called when a child of the host View has requested sending an
28644          * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
28645          * to augment the event.
28646          * <p>
28647          * The default implementation behaves as
28648          * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
28649          *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
28650          * the case of no accessibility delegate been set.
28651          * </p>
28652          *
28653          * @param host The View hosting the delegate.
28654          * @param child The child which requests sending the event.
28655          * @param event The event to be sent.
28656          * @return True if the event should be sent
28657          *
28658          * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
28659          *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
28660          */
onRequestSendAccessibilityEvent(ViewGroup host, View child, AccessibilityEvent event)28661         public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
28662                 AccessibilityEvent event) {
28663             return host.onRequestSendAccessibilityEventInternal(child, event);
28664         }
28665 
28666         /**
28667          * Gets the provider for managing a virtual view hierarchy rooted at this View
28668          * and reported to {@link android.accessibilityservice.AccessibilityService}s
28669          * that explore the window content.
28670          * <p>
28671          * The default implementation behaves as
28672          * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
28673          * the case of no accessibility delegate been set.
28674          * </p>
28675          *
28676          * @return The provider.
28677          *
28678          * @see AccessibilityNodeProvider
28679          */
getAccessibilityNodeProvider(View host)28680         public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
28681             return null;
28682         }
28683 
28684         /**
28685          * Returns an {@link AccessibilityNodeInfo} representing the host view from the
28686          * point of view of an {@link android.accessibilityservice.AccessibilityService}.
28687          * This method is responsible for obtaining an accessibility node info from a
28688          * pool of reusable instances and calling
28689          * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
28690          * view to initialize the former.
28691          * <p>
28692          * <strong>Note:</strong> The client is responsible for recycling the obtained
28693          * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
28694          * creation.
28695          * </p>
28696          * <p>
28697          * The default implementation behaves as
28698          * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
28699          * the case of no accessibility delegate been set.
28700          * </p>
28701          * @return A populated {@link AccessibilityNodeInfo}.
28702          *
28703          * @see AccessibilityNodeInfo
28704          *
28705          * @hide
28706          */
28707         @UnsupportedAppUsage
createAccessibilityNodeInfo(View host)28708         public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
28709             return host.createAccessibilityNodeInfoInternal();
28710         }
28711     }
28712 
28713     private static class MatchIdPredicate implements Predicate<View> {
28714         public int mId;
28715 
28716         @Override
test(View view)28717         public boolean test(View view) {
28718             return (view.mID == mId);
28719         }
28720     }
28721 
28722     private static class MatchLabelForPredicate implements Predicate<View> {
28723         private int mLabeledId;
28724 
28725         @Override
test(View view)28726         public boolean test(View view) {
28727             return (view.mLabelForId == mLabeledId);
28728         }
28729     }
28730 
28731     /**
28732      * Dump all private flags in readable format, useful for documentation and
28733      * sanity checking.
28734      */
dumpFlags()28735     private static void dumpFlags() {
28736         final HashMap<String, String> found = Maps.newHashMap();
28737         try {
28738             for (Field field : View.class.getDeclaredFields()) {
28739                 final int modifiers = field.getModifiers();
28740                 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
28741                     if (field.getType().equals(int.class)) {
28742                         final int value = field.getInt(null);
28743                         dumpFlag(found, field.getName(), value);
28744                     } else if (field.getType().equals(int[].class)) {
28745                         final int[] values = (int[]) field.get(null);
28746                         for (int i = 0; i < values.length; i++) {
28747                             dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
28748                         }
28749                     }
28750                 }
28751             }
28752         } catch (IllegalAccessException e) {
28753             throw new RuntimeException(e);
28754         }
28755 
28756         final ArrayList<String> keys = Lists.newArrayList();
28757         keys.addAll(found.keySet());
28758         Collections.sort(keys);
28759         for (String key : keys) {
28760             Log.d(VIEW_LOG_TAG, found.get(key));
28761         }
28762     }
28763 
dumpFlag(HashMap<String, String> found, String name, int value)28764     private static void dumpFlag(HashMap<String, String> found, String name, int value) {
28765         // Sort flags by prefix, then by bits, always keeping unique keys
28766         final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
28767         final int prefix = name.indexOf('_');
28768         final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
28769         final String output = bits + " " + name;
28770         found.put(key, output);
28771     }
28772 
28773     /** {@hide} */
encode(@onNull ViewHierarchyEncoder stream)28774     public void encode(@NonNull ViewHierarchyEncoder stream) {
28775         stream.beginObject(this);
28776         encodeProperties(stream);
28777         stream.endObject();
28778     }
28779 
28780     /** {@hide} */
28781     @CallSuper
encodeProperties(@onNull ViewHierarchyEncoder stream)28782     protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
28783         Object resolveId = ViewDebug.resolveId(getContext(), mID);
28784         if (resolveId instanceof String) {
28785             stream.addProperty("id", (String) resolveId);
28786         } else {
28787             stream.addProperty("id", mID);
28788         }
28789 
28790         stream.addProperty("misc:transformation.alpha",
28791                 mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
28792         stream.addProperty("misc:transitionName", getTransitionName());
28793 
28794         // layout
28795         stream.addProperty("layout:left", mLeft);
28796         stream.addProperty("layout:right", mRight);
28797         stream.addProperty("layout:top", mTop);
28798         stream.addProperty("layout:bottom", mBottom);
28799         stream.addProperty("layout:width", getWidth());
28800         stream.addProperty("layout:height", getHeight());
28801         stream.addProperty("layout:layoutDirection", getLayoutDirection());
28802         stream.addProperty("layout:layoutRtl", isLayoutRtl());
28803         stream.addProperty("layout:hasTransientState", hasTransientState());
28804         stream.addProperty("layout:baseline", getBaseline());
28805 
28806         // layout params
28807         ViewGroup.LayoutParams layoutParams = getLayoutParams();
28808         if (layoutParams != null) {
28809             stream.addPropertyKey("layoutParams");
28810             layoutParams.encode(stream);
28811         }
28812 
28813         // scrolling
28814         stream.addProperty("scrolling:scrollX", mScrollX);
28815         stream.addProperty("scrolling:scrollY", mScrollY);
28816 
28817         // padding
28818         stream.addProperty("padding:paddingLeft", mPaddingLeft);
28819         stream.addProperty("padding:paddingRight", mPaddingRight);
28820         stream.addProperty("padding:paddingTop", mPaddingTop);
28821         stream.addProperty("padding:paddingBottom", mPaddingBottom);
28822         stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
28823         stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
28824         stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
28825         stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
28826         stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
28827 
28828         // measurement
28829         stream.addProperty("measurement:minHeight", mMinHeight);
28830         stream.addProperty("measurement:minWidth", mMinWidth);
28831         stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
28832         stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
28833 
28834         // drawing
28835         stream.addProperty("drawing:elevation", getElevation());
28836         stream.addProperty("drawing:translationX", getTranslationX());
28837         stream.addProperty("drawing:translationY", getTranslationY());
28838         stream.addProperty("drawing:translationZ", getTranslationZ());
28839         stream.addProperty("drawing:rotation", getRotation());
28840         stream.addProperty("drawing:rotationX", getRotationX());
28841         stream.addProperty("drawing:rotationY", getRotationY());
28842         stream.addProperty("drawing:scaleX", getScaleX());
28843         stream.addProperty("drawing:scaleY", getScaleY());
28844         stream.addProperty("drawing:pivotX", getPivotX());
28845         stream.addProperty("drawing:pivotY", getPivotY());
28846         stream.addProperty("drawing:clipBounds",
28847                 mClipBounds == null ? null : mClipBounds.toString());
28848         stream.addProperty("drawing:opaque", isOpaque());
28849         stream.addProperty("drawing:alpha", getAlpha());
28850         stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
28851         stream.addProperty("drawing:shadow", hasShadow());
28852         stream.addProperty("drawing:solidColor", getSolidColor());
28853         stream.addProperty("drawing:layerType", mLayerType);
28854         stream.addProperty("drawing:willNotDraw", willNotDraw());
28855         stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
28856         stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
28857         stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
28858         stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
28859         stream.addProperty("drawing:outlineAmbientShadowColor", getOutlineAmbientShadowColor());
28860         stream.addProperty("drawing:outlineSpotShadowColor", getOutlineSpotShadowColor());
28861 
28862         // focus
28863         stream.addProperty("focus:hasFocus", hasFocus());
28864         stream.addProperty("focus:isFocused", isFocused());
28865         stream.addProperty("focus:focusable", getFocusable());
28866         stream.addProperty("focus:isFocusable", isFocusable());
28867         stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
28868 
28869         stream.addProperty("misc:clickable", isClickable());
28870         stream.addProperty("misc:pressed", isPressed());
28871         stream.addProperty("misc:selected", isSelected());
28872         stream.addProperty("misc:touchMode", isInTouchMode());
28873         stream.addProperty("misc:hovered", isHovered());
28874         stream.addProperty("misc:activated", isActivated());
28875 
28876         stream.addProperty("misc:visibility", getVisibility());
28877         stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
28878         stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
28879 
28880         stream.addProperty("misc:enabled", isEnabled());
28881         stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
28882         stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
28883 
28884         // theme attributes
28885         Resources.Theme theme = getContext().getTheme();
28886         if (theme != null) {
28887             stream.addPropertyKey("theme");
28888             theme.encode(stream);
28889         }
28890 
28891         // view attribute information
28892         int n = mAttributes != null ? mAttributes.length : 0;
28893         stream.addProperty("meta:__attrCount__", n/2);
28894         for (int i = 0; i < n; i += 2) {
28895             stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
28896         }
28897 
28898         stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
28899 
28900         // text
28901         stream.addProperty("text:textDirection", getTextDirection());
28902         stream.addProperty("text:textAlignment", getTextAlignment());
28903 
28904         // accessibility
28905         CharSequence contentDescription = getContentDescription();
28906         stream.addProperty("accessibility:contentDescription",
28907                 contentDescription == null ? "" : contentDescription.toString());
28908         stream.addProperty("accessibility:labelFor", getLabelFor());
28909         stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
28910     }
28911 
28912     /**
28913      * Determine if this view is rendered on a round wearable device and is the main view
28914      * on the screen.
28915      */
shouldDrawRoundScrollbar()28916     boolean shouldDrawRoundScrollbar() {
28917         if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
28918             return false;
28919         }
28920 
28921         final View rootView = getRootView();
28922         final WindowInsets insets = getRootWindowInsets();
28923 
28924         int height = getHeight();
28925         int width = getWidth();
28926         int displayHeight = rootView.getHeight();
28927         int displayWidth = rootView.getWidth();
28928 
28929         if (height != displayHeight || width != displayWidth) {
28930             return false;
28931         }
28932 
28933         getLocationInWindow(mAttachInfo.mTmpLocation);
28934         return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
28935                 && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
28936     }
28937 
28938     /**
28939      * Sets the tooltip text which will be displayed in a small popup next to the view.
28940      * <p>
28941      * The tooltip will be displayed:
28942      * <ul>
28943      * <li>On long click, unless it is handled otherwise (by OnLongClickListener or a context
28944      * menu). </li>
28945      * <li>On hover, after a brief delay since the pointer has stopped moving </li>
28946      * </ul>
28947      * <p>
28948      * <strong>Note:</strong> Do not override this method, as it will have no
28949      * effect on the text displayed in the tooltip.
28950      *
28951      * @param tooltipText the tooltip text, or null if no tooltip is required
28952      * @see #getTooltipText()
28953      * @attr ref android.R.styleable#View_tooltipText
28954      */
setTooltipText(@ullable CharSequence tooltipText)28955     public void setTooltipText(@Nullable CharSequence tooltipText) {
28956         if (TextUtils.isEmpty(tooltipText)) {
28957             setFlags(0, TOOLTIP);
28958             hideTooltip();
28959             mTooltipInfo = null;
28960         } else {
28961             setFlags(TOOLTIP, TOOLTIP);
28962             if (mTooltipInfo == null) {
28963                 mTooltipInfo = new TooltipInfo();
28964                 mTooltipInfo.mShowTooltipRunnable = this::showHoverTooltip;
28965                 mTooltipInfo.mHideTooltipRunnable = this::hideTooltip;
28966                 mTooltipInfo.mHoverSlop = ViewConfiguration.get(mContext).getScaledHoverSlop();
28967                 mTooltipInfo.clearAnchorPos();
28968             }
28969             mTooltipInfo.mTooltipText = tooltipText;
28970         }
28971     }
28972 
28973     /**
28974      * @hide Binary compatibility stub. To be removed when we finalize O APIs.
28975      */
28976     @UnsupportedAppUsage
setTooltip(@ullable CharSequence tooltipText)28977     public void setTooltip(@Nullable CharSequence tooltipText) {
28978         setTooltipText(tooltipText);
28979     }
28980 
28981     /**
28982      * Returns the view's tooltip text.
28983      *
28984      * <strong>Note:</strong> Do not override this method, as it will have no
28985      * effect on the text displayed in the tooltip. You must call
28986      * {@link #setTooltipText(CharSequence)} to modify the tooltip text.
28987      *
28988      * @return the tooltip text
28989      * @see #setTooltipText(CharSequence)
28990      * @attr ref android.R.styleable#View_tooltipText
28991      */
28992     @InspectableProperty
28993     @Nullable
getTooltipText()28994     public CharSequence getTooltipText() {
28995         return mTooltipInfo != null ? mTooltipInfo.mTooltipText : null;
28996     }
28997 
28998     /**
28999      * @hide Binary compatibility stub. To be removed when we finalize O APIs.
29000      */
29001     @Nullable
getTooltip()29002     public CharSequence getTooltip() {
29003         return getTooltipText();
29004     }
29005 
showTooltip(int x, int y, boolean fromLongClick)29006     private boolean showTooltip(int x, int y, boolean fromLongClick) {
29007         if (mAttachInfo == null || mTooltipInfo == null) {
29008             return false;
29009         }
29010         if (fromLongClick && (mViewFlags & ENABLED_MASK) != ENABLED) {
29011             return false;
29012         }
29013         if (TextUtils.isEmpty(mTooltipInfo.mTooltipText)) {
29014             return false;
29015         }
29016         hideTooltip();
29017         mTooltipInfo.mTooltipFromLongClick = fromLongClick;
29018         mTooltipInfo.mTooltipPopup = new TooltipPopup(getContext());
29019         final boolean fromTouch = (mPrivateFlags3 & PFLAG3_FINGER_DOWN) == PFLAG3_FINGER_DOWN;
29020         mTooltipInfo.mTooltipPopup.show(this, x, y, fromTouch, mTooltipInfo.mTooltipText);
29021         mAttachInfo.mTooltipHost = this;
29022         // The available accessibility actions have changed
29023         notifyViewAccessibilityStateChangedIfNeeded(CONTENT_CHANGE_TYPE_UNDEFINED);
29024         return true;
29025     }
29026 
29027     @UnsupportedAppUsage
hideTooltip()29028     void hideTooltip() {
29029         if (mTooltipInfo == null) {
29030             return;
29031         }
29032         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
29033         if (mTooltipInfo.mTooltipPopup == null) {
29034             return;
29035         }
29036         mTooltipInfo.mTooltipPopup.hide();
29037         mTooltipInfo.mTooltipPopup = null;
29038         mTooltipInfo.mTooltipFromLongClick = false;
29039         mTooltipInfo.clearAnchorPos();
29040         if (mAttachInfo != null) {
29041             mAttachInfo.mTooltipHost = null;
29042         }
29043         // The available accessibility actions have changed
29044         notifyViewAccessibilityStateChangedIfNeeded(CONTENT_CHANGE_TYPE_UNDEFINED);
29045     }
29046 
showLongClickTooltip(int x, int y)29047     private boolean showLongClickTooltip(int x, int y) {
29048         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
29049         removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
29050         return showTooltip(x, y, true);
29051     }
29052 
showHoverTooltip()29053     private boolean showHoverTooltip() {
29054         return showTooltip(mTooltipInfo.mAnchorX, mTooltipInfo.mAnchorY, false);
29055     }
29056 
dispatchTooltipHoverEvent(MotionEvent event)29057     boolean dispatchTooltipHoverEvent(MotionEvent event) {
29058         if (mTooltipInfo == null) {
29059             return false;
29060         }
29061         switch(event.getAction()) {
29062             case MotionEvent.ACTION_HOVER_MOVE:
29063                 if ((mViewFlags & TOOLTIP) != TOOLTIP) {
29064                     break;
29065                 }
29066                 if (!mTooltipInfo.mTooltipFromLongClick && mTooltipInfo.updateAnchorPos(event)) {
29067                     if (mTooltipInfo.mTooltipPopup == null) {
29068                         // Schedule showing the tooltip after a timeout.
29069                         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
29070                         postDelayed(mTooltipInfo.mShowTooltipRunnable,
29071                                 ViewConfiguration.getHoverTooltipShowTimeout());
29072                     }
29073 
29074                     // Hide hover-triggered tooltip after a period of inactivity.
29075                     // Match the timeout used by NativeInputManager to hide the mouse pointer
29076                     // (depends on SYSTEM_UI_FLAG_LOW_PROFILE being set).
29077                     final int timeout;
29078                     if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LOW_PROFILE)
29079                             == SYSTEM_UI_FLAG_LOW_PROFILE) {
29080                         timeout = ViewConfiguration.getHoverTooltipHideShortTimeout();
29081                     } else {
29082                         timeout = ViewConfiguration.getHoverTooltipHideTimeout();
29083                     }
29084                     removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
29085                     postDelayed(mTooltipInfo.mHideTooltipRunnable, timeout);
29086                 }
29087                 return true;
29088 
29089             case MotionEvent.ACTION_HOVER_EXIT:
29090                 mTooltipInfo.clearAnchorPos();
29091                 if (!mTooltipInfo.mTooltipFromLongClick) {
29092                     hideTooltip();
29093                 }
29094                 break;
29095         }
29096         return false;
29097     }
29098 
handleTooltipKey(KeyEvent event)29099     void handleTooltipKey(KeyEvent event) {
29100         switch (event.getAction()) {
29101             case KeyEvent.ACTION_DOWN:
29102                 if (event.getRepeatCount() == 0) {
29103                     hideTooltip();
29104                 }
29105                 break;
29106 
29107             case KeyEvent.ACTION_UP:
29108                 handleTooltipUp();
29109                 break;
29110         }
29111     }
29112 
handleTooltipUp()29113     private void handleTooltipUp() {
29114         if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
29115             return;
29116         }
29117         removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
29118         postDelayed(mTooltipInfo.mHideTooltipRunnable,
29119                 ViewConfiguration.getLongPressTooltipHideTimeout());
29120     }
29121 
getFocusableAttribute(TypedArray attributes)29122     private int getFocusableAttribute(TypedArray attributes) {
29123         TypedValue val = new TypedValue();
29124         if (attributes.getValue(com.android.internal.R.styleable.View_focusable, val)) {
29125             if (val.type == TypedValue.TYPE_INT_BOOLEAN) {
29126                 return (val.data == 0 ? NOT_FOCUSABLE : FOCUSABLE);
29127             } else {
29128                 return val.data;
29129             }
29130         } else {
29131             return FOCUSABLE_AUTO;
29132         }
29133     }
29134 
29135     /**
29136      * @return The content view of the tooltip popup currently being shown, or null if the tooltip
29137      * is not showing.
29138      * @hide
29139      */
29140     @TestApi
getTooltipView()29141     public View getTooltipView() {
29142         if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
29143             return null;
29144         }
29145         return mTooltipInfo.mTooltipPopup.getContentView();
29146     }
29147 
29148     /**
29149      * @return {@code true} if the default focus highlight is enabled, {@code false} otherwies.
29150      * @hide
29151      */
29152     @TestApi
isDefaultFocusHighlightEnabled()29153     public static boolean isDefaultFocusHighlightEnabled() {
29154         return sUseDefaultFocusHighlight;
29155     }
29156 
29157     /**
29158      * Dispatch a previously unhandled {@link KeyEvent} to this view. Unlike normal key dispatch,
29159      * this dispatches to ALL child views until it is consumed. The dispatch order is z-order
29160      * (visually on-top views first).
29161      *
29162      * @param evt the previously unhandled {@link KeyEvent}.
29163      * @return the {@link View} which consumed the event or {@code null} if not consumed.
29164      */
dispatchUnhandledKeyEvent(KeyEvent evt)29165     View dispatchUnhandledKeyEvent(KeyEvent evt) {
29166         if (onUnhandledKeyEvent(evt)) {
29167             return this;
29168         }
29169         return null;
29170     }
29171 
29172     /**
29173      * Allows this view to handle {@link KeyEvent}s which weren't handled by normal dispatch. This
29174      * occurs after the normal view hierarchy dispatch, but before the window callback. By default,
29175      * this will dispatch into all the listeners registered via
29176      * {@link #addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener)} in last-in-first-out
29177      * order (most recently added will receive events first).
29178      *
29179      * @param event An unhandled event.
29180      * @return {@code true} if the event was handled, {@code false} otherwise.
29181      * @see #addOnUnhandledKeyEventListener
29182      */
onUnhandledKeyEvent(@onNull KeyEvent event)29183     boolean onUnhandledKeyEvent(@NonNull KeyEvent event) {
29184         if (mListenerInfo != null && mListenerInfo.mUnhandledKeyListeners != null) {
29185             for (int i = mListenerInfo.mUnhandledKeyListeners.size() - 1; i >= 0; --i) {
29186                 if (mListenerInfo.mUnhandledKeyListeners.get(i).onUnhandledKeyEvent(this, event)) {
29187                     return true;
29188                 }
29189             }
29190         }
29191         return false;
29192     }
29193 
hasUnhandledKeyListener()29194     boolean hasUnhandledKeyListener() {
29195         return (mListenerInfo != null && mListenerInfo.mUnhandledKeyListeners != null
29196                 && !mListenerInfo.mUnhandledKeyListeners.isEmpty());
29197     }
29198 
29199     /**
29200      * Adds a listener which will receive unhandled {@link KeyEvent}s. This must be called on the
29201      * UI thread.
29202      *
29203      * @param listener a receiver of unhandled {@link KeyEvent}s.
29204      * @see #removeOnUnhandledKeyEventListener
29205      */
addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener)29206     public void addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener) {
29207         ArrayList<OnUnhandledKeyEventListener> listeners = getListenerInfo().mUnhandledKeyListeners;
29208         if (listeners == null) {
29209             listeners = new ArrayList<>();
29210             getListenerInfo().mUnhandledKeyListeners = listeners;
29211         }
29212         listeners.add(listener);
29213         if (listeners.size() == 1 && mParent instanceof ViewGroup) {
29214             ((ViewGroup) mParent).incrementChildUnhandledKeyListeners();
29215         }
29216     }
29217 
29218     /**
29219      * Removes a listener which will receive unhandled {@link KeyEvent}s. This must be called on the
29220      * UI thread.
29221      *
29222      * @param listener a receiver of unhandled {@link KeyEvent}s.
29223      * @see #addOnUnhandledKeyEventListener
29224      */
removeOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener)29225     public void removeOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener) {
29226         if (mListenerInfo != null) {
29227             if (mListenerInfo.mUnhandledKeyListeners != null
29228                     && !mListenerInfo.mUnhandledKeyListeners.isEmpty()) {
29229                 mListenerInfo.mUnhandledKeyListeners.remove(listener);
29230                 if (mListenerInfo.mUnhandledKeyListeners.isEmpty()) {
29231                     mListenerInfo.mUnhandledKeyListeners = null;
29232                     if (mParent instanceof ViewGroup) {
29233                         ((ViewGroup) mParent).decrementChildUnhandledKeyListeners();
29234                     }
29235                 }
29236             }
29237         }
29238     }
29239 }
29240