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.compat.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 it 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 1x1 surface instead.
946      */
947     private static boolean sAcceptZeroSizeDragShadow;
948 
949     /**
950      * Prior to Q, {@link #dispatchApplyWindowInsets} had some issues:
951      * <ul>
952      *     <li>The modified insets changed by {@link #onApplyWindowInsets} were passed to the
953      *     entire view hierarchy in prefix order, including siblings as well as siblings of parents
954      *     further down the hierarchy. This violates the basic concepts of the view hierarchy, and
955      *     thus, the hierarchical dispatching mechanism was hard to use for apps.</li>
956      *
957      *     <li>Dispatch was stopped after the insets were fully consumed. This is somewhat confusing
958      *     for developers, but more importantly, by adding more granular information to
959      *     {@link WindowInsets} it becomes really cumbersome to define what consumed actually means
960      *     </li>
961      * </ul>
962      *
963      * In order to make window inset dispatching work properly, we dispatch window insets
964      * in the view hierarchy in a proper hierarchical manner and don't stop dispatching if the
965      * insets are consumed if this flag is set to {@code false}.
966      */
967     static boolean sBrokenInsetsDispatch;
968 
969     /**
970      * Prior to Q, calling
971      * {@link com.android.internal.policy.DecorView#setBackgroundDrawable(Drawable)}
972      * did not call update the window format so the opacity of the background was not correctly
973      * applied to the window. Some applications rely on this misbehavior to work properly.
974      * <p>
975      * From Q, {@link com.android.internal.policy.DecorView#setBackgroundDrawable(Drawable)} is
976      * the same as {@link com.android.internal.policy.DecorView#setWindowBackground(Drawable)}
977      * which updates the window format.
978      * @hide
979      */
980     protected static boolean sBrokenWindowBackground;
981 
982     /** @hide */
983     @IntDef({NOT_FOCUSABLE, FOCUSABLE, FOCUSABLE_AUTO})
984     @Retention(RetentionPolicy.SOURCE)
985     public @interface Focusable {}
986 
987     /**
988      * This view does not want keystrokes.
989      * <p>
990      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
991      * android:focusable}.
992      */
993     public static final int NOT_FOCUSABLE = 0x00000000;
994 
995     /**
996      * This view wants keystrokes.
997      * <p>
998      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
999      * android:focusable}.
1000      */
1001     public static final int FOCUSABLE = 0x00000001;
1002 
1003     /**
1004      * This view determines focusability automatically. This is the default.
1005      * <p>
1006      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
1007      * android:focusable}.
1008      */
1009     public static final int FOCUSABLE_AUTO = 0x00000010;
1010 
1011     /**
1012      * Mask for use with setFlags indicating bits used for focus.
1013      */
1014     private static final int FOCUSABLE_MASK = 0x00000011;
1015 
1016     /**
1017      * This view will adjust its padding to fit sytem windows (e.g. status bar)
1018      */
1019     private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
1020 
1021     /** @hide */
1022     @IntDef({VISIBLE, INVISIBLE, GONE})
1023     @Retention(RetentionPolicy.SOURCE)
1024     public @interface Visibility {}
1025 
1026     /**
1027      * This view is visible.
1028      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
1029      * android:visibility}.
1030      */
1031     public static final int VISIBLE = 0x00000000;
1032 
1033     /**
1034      * This view is invisible, but it still takes up space for layout purposes.
1035      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
1036      * android:visibility}.
1037      */
1038     public static final int INVISIBLE = 0x00000004;
1039 
1040     /**
1041      * This view is invisible, and it doesn't take any space for layout
1042      * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
1043      * android:visibility}.
1044      */
1045     public static final int GONE = 0x00000008;
1046 
1047     /**
1048      * Mask for use with setFlags indicating bits used for visibility.
1049      * {@hide}
1050      */
1051     static final int VISIBILITY_MASK = 0x0000000C;
1052 
1053     private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
1054 
1055     /**
1056      * Hint indicating that this view can be autofilled with an email address.
1057      *
1058      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1059      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1060      * value should be <code>{@value #AUTOFILL_HINT_EMAIL_ADDRESS}</code>).
1061      *
1062      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1063      */
1064     public static final String AUTOFILL_HINT_EMAIL_ADDRESS = "emailAddress";
1065 
1066     /**
1067      * Hint indicating that this view can be autofilled with a user's real name.
1068      *
1069      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1070      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1071      * value should be <code>{@value #AUTOFILL_HINT_NAME}</code>).
1072      *
1073      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1074      */
1075     public static final String AUTOFILL_HINT_NAME = "name";
1076 
1077     /**
1078      * Hint indicating that this view can be autofilled with a username.
1079      *
1080      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1081      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1082      * value should be <code>{@value #AUTOFILL_HINT_USERNAME}</code>).
1083      *
1084      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1085      */
1086     public static final String AUTOFILL_HINT_USERNAME = "username";
1087 
1088     /**
1089      * Hint indicating that this view can be autofilled with a password.
1090      *
1091      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1092      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1093      * value should be <code>{@value #AUTOFILL_HINT_PASSWORD}</code>).
1094      *
1095      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1096      */
1097     public static final String AUTOFILL_HINT_PASSWORD = "password";
1098 
1099     /**
1100      * Hint indicating that this view can be autofilled with a phone number.
1101      *
1102      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1103      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1104      * value should be <code>{@value #AUTOFILL_HINT_PHONE}</code>).
1105      *
1106      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1107      */
1108     public static final String AUTOFILL_HINT_PHONE = "phone";
1109 
1110     /**
1111      * Hint indicating that this view can be autofilled with a postal address.
1112      *
1113      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1114      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1115      * value should be <code>{@value #AUTOFILL_HINT_POSTAL_ADDRESS}</code>).
1116      *
1117      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1118      */
1119     public static final String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress";
1120 
1121     /**
1122      * Hint indicating that this view can be autofilled with a postal code.
1123      *
1124      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1125      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1126      * value should be <code>{@value #AUTOFILL_HINT_POSTAL_CODE}</code>).
1127      *
1128      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1129      */
1130     public static final String AUTOFILL_HINT_POSTAL_CODE = "postalCode";
1131 
1132     /**
1133      * Hint indicating that this view can be autofilled with a credit card number.
1134      *
1135      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1136      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1137      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_NUMBER}</code>).
1138      *
1139      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1140      */
1141     public static final String AUTOFILL_HINT_CREDIT_CARD_NUMBER = "creditCardNumber";
1142 
1143     /**
1144      * Hint indicating that this view can be autofilled with a credit card security code.
1145      *
1146      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1147      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1148      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE}</code>).
1149      *
1150      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1151      */
1152     public static final String AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE = "creditCardSecurityCode";
1153 
1154     /**
1155      * Hint indicating that this view can be autofilled with a credit card expiration date.
1156      *
1157      * <p>It should be used when the credit card expiration date is represented by just one view;
1158      * if it is represented by more than one (for example, one view for the month and another view
1159      * for the year), then each of these views should use the hint specific for the unit
1160      * ({@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
1161      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH},
1162      * or {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}).
1163      *
1164      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1165      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1166      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE}</code>).
1167      *
1168      * <p>When annotating a view with this hint, it's recommended to use a date autofill value to
1169      * avoid ambiguity when the autofill service provides a value for it. To understand why a
1170      * value can be ambiguous, consider "April of 2020", which could be represented as either of
1171      * the following options:
1172      *
1173      * <ul>
1174      *   <li>{@code "04/2020"}
1175      *   <li>{@code "4/2020"}
1176      *   <li>{@code "2020/04"}
1177      *   <li>{@code "2020/4"}
1178      *   <li>{@code "April/2020"}
1179      *   <li>{@code "Apr/2020"}
1180      * </ul>
1181      *
1182      * <p>You define a date autofill value for the view by overriding the following methods:
1183      *
1184      * <ol>
1185      *   <li>{@link #getAutofillType()} to return {@link #AUTOFILL_TYPE_DATE}.
1186      *   <li>{@link #getAutofillValue()} to return a
1187      *       {@link AutofillValue#forDate(long) date autofillvalue}.
1188      *   <li>{@link #autofill(AutofillValue)} to expect a data autofillvalue.
1189      * </ol>
1190      *
1191      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1192      */
1193     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE =
1194             "creditCardExpirationDate";
1195 
1196     /**
1197      * Hint indicating that this view can be autofilled with a credit card expiration month.
1198      *
1199      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1200      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1201      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH}</code>).
1202      *
1203      * <p>When annotating a view with this hint, it's recommended to use a text autofill value
1204      * whose value is the numerical representation of the month, starting on {@code 1} to avoid
1205      * ambiguity when the autofill service provides a value for it. To understand why a
1206      * value can be ambiguous, consider "January", which could be represented as either of
1207      *
1208      * <ul>
1209      *   <li>{@code "1"}: recommended way.
1210      *   <li>{@code "0"}: if following the {@link Calendar#MONTH} convention.
1211      *   <li>{@code "January"}: full name, in English.
1212      *   <li>{@code "jan"}: abbreviated name, in English.
1213      *   <li>{@code "Janeiro"}: full name, in another language.
1214      * </ul>
1215      *
1216      * <p>Another recommended approach is to use a date autofill value - see
1217      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE} for more details.
1218      *
1219      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1220      */
1221     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH =
1222             "creditCardExpirationMonth";
1223 
1224     /**
1225      * Hint indicating that this view can be autofilled with a credit card expiration year.
1226      *
1227      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1228      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1229      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}</code>).
1230      *
1231      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1232      */
1233     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR =
1234             "creditCardExpirationYear";
1235 
1236     /**
1237      * Hint indicating that this view can be autofilled with a credit card expiration day.
1238      *
1239      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1240      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1241      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY}</code>).
1242      *
1243      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1244      */
1245     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY = "creditCardExpirationDay";
1246 
1247     /**
1248      * Hints for the autofill services that describes the content of the view.
1249      */
1250     private @Nullable String[] mAutofillHints;
1251 
1252     /**
1253      * Autofill id, lazily created on calls to {@link #getAutofillId()}.
1254      */
1255     private AutofillId mAutofillId;
1256 
1257     /** @hide */
1258     @IntDef(prefix = { "AUTOFILL_TYPE_" }, value = {
1259             AUTOFILL_TYPE_NONE,
1260             AUTOFILL_TYPE_TEXT,
1261             AUTOFILL_TYPE_TOGGLE,
1262             AUTOFILL_TYPE_LIST,
1263             AUTOFILL_TYPE_DATE
1264     })
1265     @Retention(RetentionPolicy.SOURCE)
1266     public @interface AutofillType {}
1267 
1268     /**
1269      * Autofill type for views that cannot be autofilled.
1270      *
1271      * <p>Typically used when the view is read-only; for example, a text label.
1272      *
1273      * @see #getAutofillType()
1274      */
1275     public static final int AUTOFILL_TYPE_NONE = 0;
1276 
1277     /**
1278      * Autofill type for a text field, which is filled by a {@link CharSequence}.
1279      *
1280      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1281      * {@link AutofillValue#forText(CharSequence)}, and the value passed to autofill a
1282      * {@link View} can be fetched through {@link AutofillValue#getTextValue()}.
1283      *
1284      * @see #getAutofillType()
1285      */
1286     public static final int AUTOFILL_TYPE_TEXT = 1;
1287 
1288     /**
1289      * Autofill type for a togglable field, which is filled by a {@code boolean}.
1290      *
1291      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1292      * {@link AutofillValue#forToggle(boolean)}, and the value passed to autofill a
1293      * {@link View} can be fetched through {@link AutofillValue#getToggleValue()}.
1294      *
1295      * @see #getAutofillType()
1296      */
1297     public static final int AUTOFILL_TYPE_TOGGLE = 2;
1298 
1299     /**
1300      * Autofill type for a selection list field, which is filled by an {@code int}
1301      * representing the element index inside the list (starting at {@code 0}).
1302      *
1303      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1304      * {@link AutofillValue#forList(int)}, and the value passed to autofill a
1305      * {@link View} can be fetched through {@link AutofillValue#getListValue()}.
1306      *
1307      * <p>The available options in the selection list are typically provided by
1308      * {@link android.app.assist.AssistStructure.ViewNode#getAutofillOptions()}.
1309      *
1310      * @see #getAutofillType()
1311      */
1312     public static final int AUTOFILL_TYPE_LIST = 3;
1313 
1314 
1315     /**
1316      * Autofill type for a field that contains a date, which is represented by a long representing
1317      * the number of milliseconds since the standard base time known as "the epoch", namely
1318      * January 1, 1970, 00:00:00 GMT (see {@link java.util.Date#getTime()}.
1319      *
1320      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1321      * {@link AutofillValue#forDate(long)}, and the values passed to
1322      * autofill a {@link View} can be fetched through {@link AutofillValue#getDateValue()}.
1323      *
1324      * @see #getAutofillType()
1325      */
1326     public static final int AUTOFILL_TYPE_DATE = 4;
1327 
1328     /** @hide */
1329     @IntDef(prefix = { "IMPORTANT_FOR_AUTOFILL_" }, value = {
1330             IMPORTANT_FOR_AUTOFILL_AUTO,
1331             IMPORTANT_FOR_AUTOFILL_YES,
1332             IMPORTANT_FOR_AUTOFILL_NO,
1333             IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
1334             IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
1335     })
1336     @Retention(RetentionPolicy.SOURCE)
1337     public @interface AutofillImportance {}
1338 
1339     /**
1340      * Automatically determine whether a view is important for autofill.
1341      *
1342      * @see #isImportantForAutofill()
1343      * @see #setImportantForAutofill(int)
1344      */
1345     public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0x0;
1346 
1347     /**
1348      * The view is important for autofill, and its children (if any) will be traversed.
1349      *
1350      * @see #isImportantForAutofill()
1351      * @see #setImportantForAutofill(int)
1352      */
1353     public static final int IMPORTANT_FOR_AUTOFILL_YES = 0x1;
1354 
1355     /**
1356      * The view is not important for autofill, but its children (if any) will be traversed.
1357      *
1358      * @see #isImportantForAutofill()
1359      * @see #setImportantForAutofill(int)
1360      */
1361     public static final int IMPORTANT_FOR_AUTOFILL_NO = 0x2;
1362 
1363     /**
1364      * The view is important for autofill, but its children (if any) will not be traversed.
1365      *
1366      * @see #isImportantForAutofill()
1367      * @see #setImportantForAutofill(int)
1368      */
1369     public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 0x4;
1370 
1371     /**
1372      * The view is not important for autofill, and its children (if any) will not be traversed.
1373      *
1374      * @see #isImportantForAutofill()
1375      * @see #setImportantForAutofill(int)
1376      */
1377     public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 0x8;
1378 
1379     /** @hide */
1380     @IntDef(flag = true, prefix = { "AUTOFILL_FLAG_" }, value = {
1381             AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
1382     })
1383     @Retention(RetentionPolicy.SOURCE)
1384     public @interface AutofillFlags {}
1385 
1386     /**
1387      * Flag requesting you to add views that are marked as not important for autofill
1388      * (see {@link #setImportantForAutofill(int)}) to a {@link ViewStructure}.
1389      */
1390     public static final int AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x1;
1391 
1392     /** @hide */
1393     @IntDef(prefix = { "IMPORTANT_FOR_CONTENT_CAPTURE_" }, value = {
1394             IMPORTANT_FOR_CONTENT_CAPTURE_AUTO,
1395             IMPORTANT_FOR_CONTENT_CAPTURE_YES,
1396             IMPORTANT_FOR_CONTENT_CAPTURE_NO,
1397             IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
1398             IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
1399     })
1400     @Retention(RetentionPolicy.SOURCE)
1401     public @interface ContentCaptureImportance {}
1402 
1403     /**
1404      * Automatically determine whether a view is important for content capture.
1405      *
1406      * @see #isImportantForContentCapture()
1407      * @see #setImportantForContentCapture(int)
1408      *
1409      * @hide
1410      */
1411     @TestApi
1412     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_AUTO = 0x0;
1413 
1414     /**
1415      * The view is important for content capture, and its children (if any) will be traversed.
1416      *
1417      * @see #isImportantForContentCapture()
1418      * @see #setImportantForContentCapture(int)
1419      *
1420      * @hide
1421      */
1422     @TestApi
1423     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES = 0x1;
1424 
1425     /**
1426      * The view is not important for content capture, but its children (if any) will be traversed.
1427      *
1428      * @see #isImportantForContentCapture()
1429      * @see #setImportantForContentCapture(int)
1430      *
1431      * @hide
1432      */
1433     @TestApi
1434     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO = 0x2;
1435 
1436     /**
1437      * The view is important for content capture, but its children (if any) will not be traversed.
1438      *
1439      * @see #isImportantForContentCapture()
1440      * @see #setImportantForContentCapture(int)
1441      *
1442      * @hide
1443      */
1444     @TestApi
1445     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS = 0x4;
1446 
1447     /**
1448      * The view is not important for content capture, and its children (if any) will not be
1449      * traversed.
1450      *
1451      * @see #isImportantForContentCapture()
1452      * @see #setImportantForContentCapture(int)
1453      *
1454      * @hide
1455      */
1456     @TestApi
1457     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS = 0x8;
1458 
1459 
1460     /**
1461      * This view is enabled. Interpretation varies by subclass.
1462      * Use with ENABLED_MASK when calling setFlags.
1463      * {@hide}
1464      */
1465     static final int ENABLED = 0x00000000;
1466 
1467     /**
1468      * This view is disabled. Interpretation varies by subclass.
1469      * Use with ENABLED_MASK when calling setFlags.
1470      * {@hide}
1471      */
1472     static final int DISABLED = 0x00000020;
1473 
1474    /**
1475     * Mask for use with setFlags indicating bits used for indicating whether
1476     * this view is enabled
1477     * {@hide}
1478     */
1479     static final int ENABLED_MASK = 0x00000020;
1480 
1481     /**
1482      * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
1483      * called and further optimizations will be performed. It is okay to have
1484      * this flag set and a background. Use with DRAW_MASK when calling setFlags.
1485      * {@hide}
1486      */
1487     static final int WILL_NOT_DRAW = 0x00000080;
1488 
1489     /**
1490      * Mask for use with setFlags indicating bits used for indicating whether
1491      * this view is will draw
1492      * {@hide}
1493      */
1494     static final int DRAW_MASK = 0x00000080;
1495 
1496     /**
1497      * <p>This view doesn't show scrollbars.</p>
1498      * {@hide}
1499      */
1500     static final int SCROLLBARS_NONE = 0x00000000;
1501 
1502     /**
1503      * <p>This view shows horizontal scrollbars.</p>
1504      * {@hide}
1505      */
1506     static final int SCROLLBARS_HORIZONTAL = 0x00000100;
1507 
1508     /**
1509      * <p>This view shows vertical scrollbars.</p>
1510      * {@hide}
1511      */
1512     static final int SCROLLBARS_VERTICAL = 0x00000200;
1513 
1514     /**
1515      * <p>Mask for use with setFlags indicating bits used for indicating which
1516      * scrollbars are enabled.</p>
1517      * {@hide}
1518      */
1519     static final int SCROLLBARS_MASK = 0x00000300;
1520 
1521     /**
1522      * Indicates that the view should filter touches when its window is obscured.
1523      * Refer to the class comments for more information about this security feature.
1524      * {@hide}
1525      */
1526     static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
1527 
1528     /**
1529      * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
1530      * that they are optional and should be skipped if the window has
1531      * requested system UI flags that ignore those insets for layout.
1532      */
1533     static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
1534 
1535     /**
1536      * <p>This view doesn't show fading edges.</p>
1537      * {@hide}
1538      */
1539     static final int FADING_EDGE_NONE = 0x00000000;
1540 
1541     /**
1542      * <p>This view shows horizontal fading edges.</p>
1543      * {@hide}
1544      */
1545     static final int FADING_EDGE_HORIZONTAL = 0x00001000;
1546 
1547     /**
1548      * <p>This view shows vertical fading edges.</p>
1549      * {@hide}
1550      */
1551     static final int FADING_EDGE_VERTICAL = 0x00002000;
1552 
1553     /**
1554      * <p>Mask for use with setFlags indicating bits used for indicating which
1555      * fading edges are enabled.</p>
1556      * {@hide}
1557      */
1558     static final int FADING_EDGE_MASK = 0x00003000;
1559 
1560     /**
1561      * <p>Indicates this view can be clicked. When clickable, a View reacts
1562      * to clicks by notifying the OnClickListener.<p>
1563      * {@hide}
1564      */
1565     static final int CLICKABLE = 0x00004000;
1566 
1567     /**
1568      * <p>Indicates this view is caching its drawing into a bitmap.</p>
1569      * {@hide}
1570      */
1571     static final int DRAWING_CACHE_ENABLED = 0x00008000;
1572 
1573     /**
1574      * <p>Indicates that no icicle should be saved for this view.<p>
1575      * {@hide}
1576      */
1577     static final int SAVE_DISABLED = 0x000010000;
1578 
1579     /**
1580      * <p>Mask for use with setFlags indicating bits used for the saveEnabled
1581      * property.</p>
1582      * {@hide}
1583      */
1584     static final int SAVE_DISABLED_MASK = 0x000010000;
1585 
1586     /**
1587      * <p>Indicates that no drawing cache should ever be created for this view.<p>
1588      * {@hide}
1589      */
1590     static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
1591 
1592     /**
1593      * <p>Indicates this view can take / keep focus when int touch mode.</p>
1594      * {@hide}
1595      */
1596     static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
1597 
1598     /** @hide */
1599     @Retention(RetentionPolicy.SOURCE)
1600     @IntDef(prefix = { "DRAWING_CACHE_QUALITY_" }, value = {
1601             DRAWING_CACHE_QUALITY_LOW,
1602             DRAWING_CACHE_QUALITY_HIGH,
1603             DRAWING_CACHE_QUALITY_AUTO
1604     })
1605     public @interface DrawingCacheQuality {}
1606 
1607     /**
1608      * <p>Enables low quality mode for the drawing cache.</p>
1609      *
1610      * @deprecated The view drawing cache was largely made obsolete with the introduction of
1611      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
1612      * layers are largely unnecessary and can easily result in a net loss in performance due to the
1613      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
1614      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
1615      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
1616      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
1617      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
1618      * software-rendered usages are discouraged and have compatibility issues with hardware-only
1619      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
1620      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
1621      * reports or unit testing the {@link PixelCopy} API is recommended.
1622      */
1623     @Deprecated
1624     public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
1625 
1626     /**
1627      * <p>Enables high quality mode for the drawing cache.</p>
1628      *
1629      * @deprecated The view drawing cache was largely made obsolete with the introduction of
1630      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
1631      * layers are largely unnecessary and can easily result in a net loss in performance due to the
1632      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
1633      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
1634      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
1635      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
1636      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
1637      * software-rendered usages are discouraged and have compatibility issues with hardware-only
1638      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
1639      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
1640      * reports or unit testing the {@link PixelCopy} API is recommended.
1641      */
1642     @Deprecated
1643     public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
1644 
1645     /**
1646      * <p>Enables automatic quality mode for the drawing cache.</p>
1647      *
1648      * @deprecated The view drawing cache was largely made obsolete with the introduction of
1649      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
1650      * layers are largely unnecessary and can easily result in a net loss in performance due to the
1651      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
1652      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
1653      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
1654      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
1655      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
1656      * software-rendered usages are discouraged and have compatibility issues with hardware-only
1657      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
1658      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
1659      * reports or unit testing the {@link PixelCopy} API is recommended.
1660      */
1661     @Deprecated
1662     public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
1663 
1664     private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
1665             DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
1666     };
1667 
1668     /**
1669      * <p>Mask for use with setFlags indicating bits used for the cache
1670      * quality property.</p>
1671      * {@hide}
1672      */
1673     static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
1674 
1675     /**
1676      * <p>
1677      * Indicates this view can be long clicked. When long clickable, a View
1678      * reacts to long clicks by notifying the OnLongClickListener or showing a
1679      * context menu.
1680      * </p>
1681      * {@hide}
1682      */
1683     static final int LONG_CLICKABLE = 0x00200000;
1684 
1685     /**
1686      * <p>Indicates that this view gets its drawable states from its direct parent
1687      * and ignores its original internal states.</p>
1688      *
1689      * @hide
1690      */
1691     static final int DUPLICATE_PARENT_STATE = 0x00400000;
1692 
1693     /**
1694      * <p>
1695      * Indicates this view can be context clicked. When context clickable, a View reacts to a
1696      * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1697      * OnContextClickListener.
1698      * </p>
1699      * {@hide}
1700      */
1701     static final int CONTEXT_CLICKABLE = 0x00800000;
1702 
1703     /** @hide */
1704     @IntDef(prefix = { "SCROLLBARS_" }, value = {
1705             SCROLLBARS_INSIDE_OVERLAY,
1706             SCROLLBARS_INSIDE_INSET,
1707             SCROLLBARS_OUTSIDE_OVERLAY,
1708             SCROLLBARS_OUTSIDE_INSET
1709     })
1710     @Retention(RetentionPolicy.SOURCE)
1711     public @interface ScrollBarStyle {}
1712 
1713     /**
1714      * The scrollbar style to display the scrollbars inside the content area,
1715      * without increasing the padding. The scrollbars will be overlaid with
1716      * translucency on the view's content.
1717      */
1718     public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1719 
1720     /**
1721      * The scrollbar style to display the scrollbars inside the padded area,
1722      * increasing the padding of the view. The scrollbars will not overlap the
1723      * content area of the view.
1724      */
1725     public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1726 
1727     /**
1728      * The scrollbar style to display the scrollbars at the edge of the view,
1729      * without increasing the padding. The scrollbars will be overlaid with
1730      * translucency.
1731      */
1732     public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1733 
1734     /**
1735      * The scrollbar style to display the scrollbars at the edge of the view,
1736      * increasing the padding of the view. The scrollbars will only overlap the
1737      * background, if any.
1738      */
1739     public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1740 
1741     /**
1742      * Mask to check if the scrollbar style is overlay or inset.
1743      * {@hide}
1744      */
1745     static final int SCROLLBARS_INSET_MASK = 0x01000000;
1746 
1747     /**
1748      * Mask to check if the scrollbar style is inside or outside.
1749      * {@hide}
1750      */
1751     static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1752 
1753     /**
1754      * Mask for scrollbar style.
1755      * {@hide}
1756      */
1757     static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1758 
1759     /**
1760      * View flag indicating that the screen should remain on while the
1761      * window containing this view is visible to the user.  This effectively
1762      * takes care of automatically setting the WindowManager's
1763      * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1764      */
1765     public static final int KEEP_SCREEN_ON = 0x04000000;
1766 
1767     /**
1768      * View flag indicating whether this view should have sound effects enabled
1769      * for events such as clicking and touching.
1770      */
1771     public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1772 
1773     /**
1774      * View flag indicating whether this view should have haptic feedback
1775      * enabled for events such as long presses.
1776      */
1777     public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1778 
1779     /**
1780      * <p>Indicates that the view hierarchy should stop saving state when
1781      * it reaches this view.  If state saving is initiated immediately at
1782      * the view, it will be allowed.
1783      * {@hide}
1784      */
1785     static final int PARENT_SAVE_DISABLED = 0x20000000;
1786 
1787     /**
1788      * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1789      * {@hide}
1790      */
1791     static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1792 
1793     private static Paint sDebugPaint;
1794 
1795     /**
1796      * <p>Indicates this view can display a tooltip on hover or long press.</p>
1797      * {@hide}
1798      */
1799     static final int TOOLTIP = 0x40000000;
1800 
1801     /** @hide */
1802     @IntDef(flag = true, prefix = { "FOCUSABLES_" }, value = {
1803             FOCUSABLES_ALL,
1804             FOCUSABLES_TOUCH_MODE
1805     })
1806     @Retention(RetentionPolicy.SOURCE)
1807     public @interface FocusableMode {}
1808 
1809     /**
1810      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1811      * should add all focusable Views regardless if they are focusable in touch mode.
1812      */
1813     public static final int FOCUSABLES_ALL = 0x00000000;
1814 
1815     /**
1816      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1817      * should add only Views focusable in touch mode.
1818      */
1819     public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1820 
1821     /** @hide */
1822     @IntDef(prefix = { "FOCUS_" }, value = {
1823             FOCUS_BACKWARD,
1824             FOCUS_FORWARD,
1825             FOCUS_LEFT,
1826             FOCUS_UP,
1827             FOCUS_RIGHT,
1828             FOCUS_DOWN
1829     })
1830     @Retention(RetentionPolicy.SOURCE)
1831     public @interface FocusDirection {}
1832 
1833     /** @hide */
1834     @IntDef(prefix = { "FOCUS_" }, value = {
1835             FOCUS_LEFT,
1836             FOCUS_UP,
1837             FOCUS_RIGHT,
1838             FOCUS_DOWN
1839     })
1840     @Retention(RetentionPolicy.SOURCE)
1841     public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1842 
1843     /**
1844      * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1845      * item.
1846      */
1847     public static final int FOCUS_BACKWARD = 0x00000001;
1848 
1849     /**
1850      * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1851      * item.
1852      */
1853     public static final int FOCUS_FORWARD = 0x00000002;
1854 
1855     /**
1856      * Use with {@link #focusSearch(int)}. Move focus to the left.
1857      */
1858     public static final int FOCUS_LEFT = 0x00000011;
1859 
1860     /**
1861      * Use with {@link #focusSearch(int)}. Move focus up.
1862      */
1863     public static final int FOCUS_UP = 0x00000021;
1864 
1865     /**
1866      * Use with {@link #focusSearch(int)}. Move focus to the right.
1867      */
1868     public static final int FOCUS_RIGHT = 0x00000042;
1869 
1870     /**
1871      * Use with {@link #focusSearch(int)}. Move focus down.
1872      */
1873     public static final int FOCUS_DOWN = 0x00000082;
1874 
1875     /**
1876      * Bits of {@link #getMeasuredWidthAndState()} and
1877      * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1878      */
1879     public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1880 
1881     /**
1882      * Bits of {@link #getMeasuredWidthAndState()} and
1883      * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1884      */
1885     public static final int MEASURED_STATE_MASK = 0xff000000;
1886 
1887     /**
1888      * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1889      * for functions that combine both width and height into a single int,
1890      * such as {@link #getMeasuredState()} and the childState argument of
1891      * {@link #resolveSizeAndState(int, int, int)}.
1892      */
1893     public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1894 
1895     /**
1896      * Bit of {@link #getMeasuredWidthAndState()} and
1897      * {@link #getMeasuredWidthAndState()} that indicates the measured size
1898      * is smaller that the space the view would like to have.
1899      */
1900     public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1901 
1902     /**
1903      * Base View state sets
1904      */
1905     // Singles
1906     /**
1907      * Indicates the view has no states set. States are used with
1908      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1909      * view depending on its state.
1910      *
1911      * @see android.graphics.drawable.Drawable
1912      * @see #getDrawableState()
1913      */
1914     protected static final int[] EMPTY_STATE_SET;
1915     /**
1916      * Indicates the view is enabled. States are used with
1917      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1918      * view depending on its state.
1919      *
1920      * @see android.graphics.drawable.Drawable
1921      * @see #getDrawableState()
1922      */
1923     protected static final int[] ENABLED_STATE_SET;
1924     /**
1925      * Indicates the view is focused. States are used with
1926      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1927      * view depending on its state.
1928      *
1929      * @see android.graphics.drawable.Drawable
1930      * @see #getDrawableState()
1931      */
1932     protected static final int[] FOCUSED_STATE_SET;
1933     /**
1934      * Indicates the view is selected. States are used with
1935      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1936      * view depending on its state.
1937      *
1938      * @see android.graphics.drawable.Drawable
1939      * @see #getDrawableState()
1940      */
1941     protected static final int[] SELECTED_STATE_SET;
1942     /**
1943      * Indicates the view is pressed. States are used with
1944      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1945      * view depending on its state.
1946      *
1947      * @see android.graphics.drawable.Drawable
1948      * @see #getDrawableState()
1949      */
1950     protected static final int[] PRESSED_STATE_SET;
1951     /**
1952      * Indicates the view's window has focus. States are used with
1953      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1954      * view depending on its state.
1955      *
1956      * @see android.graphics.drawable.Drawable
1957      * @see #getDrawableState()
1958      */
1959     protected static final int[] WINDOW_FOCUSED_STATE_SET;
1960     // Doubles
1961     /**
1962      * Indicates the view is enabled and has the focus.
1963      *
1964      * @see #ENABLED_STATE_SET
1965      * @see #FOCUSED_STATE_SET
1966      */
1967     protected static final int[] ENABLED_FOCUSED_STATE_SET;
1968     /**
1969      * Indicates the view is enabled and selected.
1970      *
1971      * @see #ENABLED_STATE_SET
1972      * @see #SELECTED_STATE_SET
1973      */
1974     protected static final int[] ENABLED_SELECTED_STATE_SET;
1975     /**
1976      * Indicates the view is enabled and that its window has focus.
1977      *
1978      * @see #ENABLED_STATE_SET
1979      * @see #WINDOW_FOCUSED_STATE_SET
1980      */
1981     protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1982     /**
1983      * Indicates the view is focused and selected.
1984      *
1985      * @see #FOCUSED_STATE_SET
1986      * @see #SELECTED_STATE_SET
1987      */
1988     protected static final int[] FOCUSED_SELECTED_STATE_SET;
1989     /**
1990      * Indicates the view has the focus and that its window has the focus.
1991      *
1992      * @see #FOCUSED_STATE_SET
1993      * @see #WINDOW_FOCUSED_STATE_SET
1994      */
1995     protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1996     /**
1997      * Indicates the view is selected and that its window has the focus.
1998      *
1999      * @see #SELECTED_STATE_SET
2000      * @see #WINDOW_FOCUSED_STATE_SET
2001      */
2002     protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
2003     // Triples
2004     /**
2005      * Indicates the view is enabled, focused and selected.
2006      *
2007      * @see #ENABLED_STATE_SET
2008      * @see #FOCUSED_STATE_SET
2009      * @see #SELECTED_STATE_SET
2010      */
2011     protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
2012     /**
2013      * Indicates the view is enabled, focused and its window has the focus.
2014      *
2015      * @see #ENABLED_STATE_SET
2016      * @see #FOCUSED_STATE_SET
2017      * @see #WINDOW_FOCUSED_STATE_SET
2018      */
2019     protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
2020     /**
2021      * Indicates the view is enabled, selected and its window has the focus.
2022      *
2023      * @see #ENABLED_STATE_SET
2024      * @see #SELECTED_STATE_SET
2025      * @see #WINDOW_FOCUSED_STATE_SET
2026      */
2027     protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2028     /**
2029      * Indicates the view is focused, selected and its window has the focus.
2030      *
2031      * @see #FOCUSED_STATE_SET
2032      * @see #SELECTED_STATE_SET
2033      * @see #WINDOW_FOCUSED_STATE_SET
2034      */
2035     protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2036     /**
2037      * Indicates the view is enabled, focused, selected and its window
2038      * has the focus.
2039      *
2040      * @see #ENABLED_STATE_SET
2041      * @see #FOCUSED_STATE_SET
2042      * @see #SELECTED_STATE_SET
2043      * @see #WINDOW_FOCUSED_STATE_SET
2044      */
2045     protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2046     /**
2047      * Indicates the view is pressed and its window has the focus.
2048      *
2049      * @see #PRESSED_STATE_SET
2050      * @see #WINDOW_FOCUSED_STATE_SET
2051      */
2052     protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
2053     /**
2054      * Indicates the view is pressed and selected.
2055      *
2056      * @see #PRESSED_STATE_SET
2057      * @see #SELECTED_STATE_SET
2058      */
2059     protected static final int[] PRESSED_SELECTED_STATE_SET;
2060     /**
2061      * Indicates the view is pressed, selected and its window has the focus.
2062      *
2063      * @see #PRESSED_STATE_SET
2064      * @see #SELECTED_STATE_SET
2065      * @see #WINDOW_FOCUSED_STATE_SET
2066      */
2067     protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2068     /**
2069      * Indicates the view is pressed and focused.
2070      *
2071      * @see #PRESSED_STATE_SET
2072      * @see #FOCUSED_STATE_SET
2073      */
2074     protected static final int[] PRESSED_FOCUSED_STATE_SET;
2075     /**
2076      * Indicates the view is pressed, focused and its window has the focus.
2077      *
2078      * @see #PRESSED_STATE_SET
2079      * @see #FOCUSED_STATE_SET
2080      * @see #WINDOW_FOCUSED_STATE_SET
2081      */
2082     protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
2083     /**
2084      * Indicates the view is pressed, focused and selected.
2085      *
2086      * @see #PRESSED_STATE_SET
2087      * @see #SELECTED_STATE_SET
2088      * @see #FOCUSED_STATE_SET
2089      */
2090     protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
2091     /**
2092      * Indicates the view is pressed, focused, selected and its window has the focus.
2093      *
2094      * @see #PRESSED_STATE_SET
2095      * @see #FOCUSED_STATE_SET
2096      * @see #SELECTED_STATE_SET
2097      * @see #WINDOW_FOCUSED_STATE_SET
2098      */
2099     protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2100     /**
2101      * Indicates the view is pressed and enabled.
2102      *
2103      * @see #PRESSED_STATE_SET
2104      * @see #ENABLED_STATE_SET
2105      */
2106     protected static final int[] PRESSED_ENABLED_STATE_SET;
2107     /**
2108      * Indicates the view is pressed, enabled and its window has the focus.
2109      *
2110      * @see #PRESSED_STATE_SET
2111      * @see #ENABLED_STATE_SET
2112      * @see #WINDOW_FOCUSED_STATE_SET
2113      */
2114     protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
2115     /**
2116      * Indicates the view is pressed, enabled and selected.
2117      *
2118      * @see #PRESSED_STATE_SET
2119      * @see #ENABLED_STATE_SET
2120      * @see #SELECTED_STATE_SET
2121      */
2122     protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
2123     /**
2124      * Indicates the view is pressed, enabled, selected and its window has the
2125      * focus.
2126      *
2127      * @see #PRESSED_STATE_SET
2128      * @see #ENABLED_STATE_SET
2129      * @see #SELECTED_STATE_SET
2130      * @see #WINDOW_FOCUSED_STATE_SET
2131      */
2132     protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2133     /**
2134      * Indicates the view is pressed, enabled and focused.
2135      *
2136      * @see #PRESSED_STATE_SET
2137      * @see #ENABLED_STATE_SET
2138      * @see #FOCUSED_STATE_SET
2139      */
2140     protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
2141     /**
2142      * Indicates the view is pressed, enabled, focused and its window has the
2143      * focus.
2144      *
2145      * @see #PRESSED_STATE_SET
2146      * @see #ENABLED_STATE_SET
2147      * @see #FOCUSED_STATE_SET
2148      * @see #WINDOW_FOCUSED_STATE_SET
2149      */
2150     protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
2151     /**
2152      * Indicates the view is pressed, enabled, focused and selected.
2153      *
2154      * @see #PRESSED_STATE_SET
2155      * @see #ENABLED_STATE_SET
2156      * @see #SELECTED_STATE_SET
2157      * @see #FOCUSED_STATE_SET
2158      */
2159     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
2160     /**
2161      * Indicates the view is pressed, enabled, focused, selected and its window
2162      * has the focus.
2163      *
2164      * @see #PRESSED_STATE_SET
2165      * @see #ENABLED_STATE_SET
2166      * @see #SELECTED_STATE_SET
2167      * @see #FOCUSED_STATE_SET
2168      * @see #WINDOW_FOCUSED_STATE_SET
2169      */
2170     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2171 
2172     static {
2173         EMPTY_STATE_SET = StateSet.get(0);
2174 
2175         WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
2176 
2177         SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
2178         SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2179                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
2180 
2181         FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
2182         FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2183                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
2184         FOCUSED_SELECTED_STATE_SET = StateSet.get(
2185                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
2186         FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2187                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2188                         | StateSet.VIEW_STATE_FOCUSED);
2189 
2190         ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
2191         ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2192                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
2193         ENABLED_SELECTED_STATE_SET = StateSet.get(
2194                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
2195         ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2196                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2197                         | StateSet.VIEW_STATE_ENABLED);
2198         ENABLED_FOCUSED_STATE_SET = StateSet.get(
2199                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
2200         ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2201                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2202                         | StateSet.VIEW_STATE_ENABLED);
2203         ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2204                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2205                         | StateSet.VIEW_STATE_ENABLED);
2206         ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2207                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2208                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
2209 
2210         PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
2211         PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2212                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
2213         PRESSED_SELECTED_STATE_SET = StateSet.get(
2214                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
2215         PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2216                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2217                         | StateSet.VIEW_STATE_PRESSED);
2218         PRESSED_FOCUSED_STATE_SET = StateSet.get(
2219                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
2220         PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2221                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2222                         | StateSet.VIEW_STATE_PRESSED);
2223         PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2224                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2225                         | StateSet.VIEW_STATE_PRESSED);
2226         PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2227                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2228                         | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
2229         PRESSED_ENABLED_STATE_SET = StateSet.get(
2230                 StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2231         PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2232                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
2233                         | StateSet.VIEW_STATE_PRESSED);
2234         PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
2235                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
2236                         | StateSet.VIEW_STATE_PRESSED);
2237         PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2238                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2239                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2240         PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
2241                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
2242                         | StateSet.VIEW_STATE_PRESSED);
2243         PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2244                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2245                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2246         PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2247                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2248                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2249         PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2250                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2251                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
2252                         | StateSet.VIEW_STATE_PRESSED);
2253     }
2254 
2255     /**
2256      * Accessibility event types that are dispatched for text population.
2257      */
2258     private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
2259             AccessibilityEvent.TYPE_VIEW_CLICKED
2260             | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
2261             | AccessibilityEvent.TYPE_VIEW_SELECTED
2262             | AccessibilityEvent.TYPE_VIEW_FOCUSED
2263             | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
2264             | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
2265             | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
2266             | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
2267             | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
2268             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
2269             | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
2270 
2271     static final int DEBUG_CORNERS_COLOR = Color.rgb(63, 127, 255);
2272 
2273     static final int DEBUG_CORNERS_SIZE_DIP = 8;
2274 
2275     /**
2276      * Temporary Rect currently for use in setBackground().  This will probably
2277      * be extended in the future to hold our own class with more than just
2278      * a Rect. :)
2279      */
2280     static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
2281 
2282     /**
2283      * Map used to store views' tags.
2284      */
2285     @UnsupportedAppUsage
2286     private SparseArray<Object> mKeyedTags;
2287 
2288     /**
2289      * The next available accessibility id.
2290      */
2291     private static int sNextAccessibilityViewId;
2292 
2293     /**
2294      * The animation currently associated with this view.
2295      * @hide
2296      */
2297     protected Animation mCurrentAnimation = null;
2298 
2299     /**
2300      * Width as measured during measure pass.
2301      * {@hide}
2302      */
2303     @ViewDebug.ExportedProperty(category = "measurement")
2304     @UnsupportedAppUsage
2305     int mMeasuredWidth;
2306 
2307     /**
2308      * Height as measured during measure pass.
2309      * {@hide}
2310      */
2311     @ViewDebug.ExportedProperty(category = "measurement")
2312     @UnsupportedAppUsage
2313     int mMeasuredHeight;
2314 
2315     /**
2316      * Flag to indicate that this view was marked INVALIDATED, or had its display list
2317      * invalidated, prior to the current drawing iteration. If true, the view must re-draw
2318      * its display list. This flag, used only when hw accelerated, allows us to clear the
2319      * flag while retaining this information until it's needed (at getDisplayList() time and
2320      * in drawChild(), when we decide to draw a view's children's display lists into our own).
2321      *
2322      * {@hide}
2323      */
2324     @UnsupportedAppUsage
2325     boolean mRecreateDisplayList = false;
2326 
2327     /**
2328      * The view's identifier.
2329      * {@hide}
2330      *
2331      * @see #setId(int)
2332      * @see #getId()
2333      */
2334     @IdRes
2335     @ViewDebug.ExportedProperty(resolveId = true)
2336     int mID = NO_ID;
2337 
2338     /** The ID of this view for autofill purposes.
2339      * <ul>
2340      *     <li>== {@link #NO_ID}: ID has not been assigned yet
2341      *     <li>&le; {@link #LAST_APP_AUTOFILL_ID}: View is not part of a activity. The ID is
2342      *                                                  unique in the process. This might change
2343      *                                                  over activity lifecycle events.
2344      *     <li>&gt; {@link #LAST_APP_AUTOFILL_ID}: View is part of a activity. The ID is
2345      *                                                  unique in the activity. This stays the same
2346      *                                                  over activity lifecycle events.
2347      */
2348     private int mAutofillViewId = NO_ID;
2349 
2350     // ID for accessibility purposes. This ID must be unique for every window
2351     @UnsupportedAppUsage
2352     private int mAccessibilityViewId = NO_ID;
2353 
2354     private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
2355 
2356     /**
2357      * The view's tag.
2358      * {@hide}
2359      *
2360      * @see #setTag(Object)
2361      * @see #getTag()
2362      */
2363     @UnsupportedAppUsage
2364     protected Object mTag = null;
2365 
2366     /*
2367      * Masks for mPrivateFlags, as generated by dumpFlags():
2368      *
2369      * |-------|-------|-------|-------|
2370      *                                 1 PFLAG_WANTS_FOCUS
2371      *                                1  PFLAG_FOCUSED
2372      *                               1   PFLAG_SELECTED
2373      *                              1    PFLAG_IS_ROOT_NAMESPACE
2374      *                             1     PFLAG_HAS_BOUNDS
2375      *                            1      PFLAG_DRAWN
2376      *                           1       PFLAG_DRAW_ANIMATION
2377      *                          1        PFLAG_SKIP_DRAW
2378      *                        1          PFLAG_REQUEST_TRANSPARENT_REGIONS
2379      *                       1           PFLAG_DRAWABLE_STATE_DIRTY
2380      *                      1            PFLAG_MEASURED_DIMENSION_SET
2381      *                     1             PFLAG_FORCE_LAYOUT
2382      *                    1              PFLAG_LAYOUT_REQUIRED
2383      *                   1               PFLAG_PRESSED
2384      *                  1                PFLAG_DRAWING_CACHE_VALID
2385      *                 1                 PFLAG_ANIMATION_STARTED
2386      *                1                  PFLAG_SAVE_STATE_CALLED
2387      *               1                   PFLAG_ALPHA_SET
2388      *              1                    PFLAG_SCROLL_CONTAINER
2389      *             1                     PFLAG_SCROLL_CONTAINER_ADDED
2390      *            1                      PFLAG_DIRTY
2391      *            1                      PFLAG_DIRTY_MASK
2392      *          1                        PFLAG_OPAQUE_BACKGROUND
2393      *         1                         PFLAG_OPAQUE_SCROLLBARS
2394      *         11                        PFLAG_OPAQUE_MASK
2395      *        1                          PFLAG_PREPRESSED
2396      *       1                           PFLAG_CANCEL_NEXT_UP_EVENT
2397      *      1                            PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH
2398      *     1                             PFLAG_HOVERED
2399      *    1                              PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK
2400      *   1                               PFLAG_ACTIVATED
2401      *  1                                PFLAG_INVALIDATED
2402      * |-------|-------|-------|-------|
2403      */
2404     /** {@hide} */
2405     static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
2406     /** {@hide} */
2407     static final int PFLAG_FOCUSED                     = 0x00000002;
2408     /** {@hide} */
2409     static final int PFLAG_SELECTED                    = 0x00000004;
2410     /** {@hide} */
2411     static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
2412     /** {@hide} */
2413     static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
2414     /** {@hide} */
2415     static final int PFLAG_DRAWN                       = 0x00000020;
2416     /**
2417      * When this flag is set, this view is running an animation on behalf of its
2418      * children and should therefore not cancel invalidate requests, even if they
2419      * lie outside of this view's bounds.
2420      *
2421      * {@hide}
2422      */
2423     static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
2424     /** {@hide} */
2425     static final int PFLAG_SKIP_DRAW                   = 0x00000080;
2426     /** {@hide} */
2427     static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
2428     /** {@hide} */
2429     static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
2430     /** {@hide} */
2431     static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
2432     /** {@hide} */
2433     static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
2434     /** {@hide} */
2435     static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
2436 
2437     private static final int PFLAG_PRESSED             = 0x00004000;
2438 
2439     /** {@hide} */
2440     static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
2441     /**
2442      * Flag used to indicate that this view should be drawn once more (and only once
2443      * more) after its animation has completed.
2444      * {@hide}
2445      */
2446     static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
2447 
2448     private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
2449 
2450     /**
2451      * Indicates that the View returned true when onSetAlpha() was called and that
2452      * the alpha must be restored.
2453      * {@hide}
2454      */
2455     static final int PFLAG_ALPHA_SET                   = 0x00040000;
2456 
2457     /**
2458      * Set by {@link #setScrollContainer(boolean)}.
2459      */
2460     static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
2461 
2462     /**
2463      * Set by {@link #setScrollContainer(boolean)}.
2464      */
2465     static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
2466 
2467     /**
2468      * View flag indicating whether this view was invalidated (fully or partially.)
2469      *
2470      * @hide
2471      */
2472     static final int PFLAG_DIRTY                       = 0x00200000;
2473 
2474     /**
2475      * Mask for {@link #PFLAG_DIRTY}.
2476      *
2477      * @hide
2478      */
2479     static final int PFLAG_DIRTY_MASK                  = 0x00200000;
2480 
2481     /**
2482      * Indicates whether the background is opaque.
2483      *
2484      * @hide
2485      */
2486     static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
2487 
2488     /**
2489      * Indicates whether the scrollbars are opaque.
2490      *
2491      * @hide
2492      */
2493     static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
2494 
2495     /**
2496      * Indicates whether the view is opaque.
2497      *
2498      * @hide
2499      */
2500     static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
2501 
2502     /**
2503      * Indicates a prepressed state;
2504      * the short time between ACTION_DOWN and recognizing
2505      * a 'real' press. Prepressed is used to recognize quick taps
2506      * even when they are shorter than ViewConfiguration.getTapTimeout().
2507      *
2508      * @hide
2509      */
2510     private static final int PFLAG_PREPRESSED          = 0x02000000;
2511 
2512     /**
2513      * Indicates whether the view is temporarily detached.
2514      *
2515      * @hide
2516      */
2517     static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
2518 
2519     /**
2520      * Indicates that we should awaken scroll bars once attached
2521      *
2522      * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
2523      * during window attachment and it is no longer needed. Feel free to repurpose it.
2524      *
2525      * @hide
2526      */
2527     private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
2528 
2529     /**
2530      * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
2531      * @hide
2532      */
2533     private static final int PFLAG_HOVERED             = 0x10000000;
2534 
2535     /**
2536      * Flag set by {@link AutofillManager} if it needs to be notified when this view is clicked.
2537      */
2538     private static final int PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK = 0x20000000;
2539 
2540     /** {@hide} */
2541     static final int PFLAG_ACTIVATED                   = 0x40000000;
2542 
2543     /**
2544      * Indicates that this view was specifically invalidated, not just dirtied because some
2545      * child view was invalidated. The flag is used to determine when we need to recreate
2546      * a view's display list (as opposed to just returning a reference to its existing
2547      * display list).
2548      *
2549      * @hide
2550      */
2551     static final int PFLAG_INVALIDATED                 = 0x80000000;
2552 
2553     /* End of masks for mPrivateFlags */
2554 
2555     /*
2556      * Masks for mPrivateFlags2, as generated by dumpFlags():
2557      *
2558      * |-------|-------|-------|-------|
2559      *                                 1 PFLAG2_DRAG_CAN_ACCEPT
2560      *                                1  PFLAG2_DRAG_HOVERED
2561      *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
2562      *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
2563      *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
2564      *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
2565      *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
2566      *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
2567      *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
2568      *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
2569      *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
2570      *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
2571      *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
2572      *                         111       PFLAG2_TEXT_DIRECTION_MASK
2573      *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
2574      *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
2575      *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
2576      *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
2577      *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
2578      *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
2579      *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
2580      *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
2581      *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
2582      *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
2583      *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
2584      *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
2585      *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
2586      *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
2587      *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
2588      *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
2589      *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
2590      *     1                             PFLAG2_VIEW_QUICK_REJECTED
2591      *    1                              PFLAG2_PADDING_RESOLVED
2592      *   1                               PFLAG2_DRAWABLE_RESOLVED
2593      *  1                                PFLAG2_HAS_TRANSIENT_STATE
2594      * |-------|-------|-------|-------|
2595      */
2596 
2597     /**
2598      * Indicates that this view has reported that it can accept the current drag's content.
2599      * Cleared when the drag operation concludes.
2600      * @hide
2601      */
2602     static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
2603 
2604     /**
2605      * Indicates that this view is currently directly under the drag location in a
2606      * drag-and-drop operation involving content that it can accept.  Cleared when
2607      * the drag exits the view, or when the drag operation concludes.
2608      * @hide
2609      */
2610     static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
2611 
2612     /** @hide */
2613     @IntDef(prefix = { "LAYOUT_DIRECTION_" }, value = {
2614             LAYOUT_DIRECTION_LTR,
2615             LAYOUT_DIRECTION_RTL,
2616             LAYOUT_DIRECTION_INHERIT,
2617             LAYOUT_DIRECTION_LOCALE
2618     })
2619     @Retention(RetentionPolicy.SOURCE)
2620     // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
2621     public @interface LayoutDir {}
2622 
2623     /** @hide */
2624     @IntDef(prefix = { "LAYOUT_DIRECTION_" }, value = {
2625             LAYOUT_DIRECTION_LTR,
2626             LAYOUT_DIRECTION_RTL
2627     })
2628     @Retention(RetentionPolicy.SOURCE)
2629     public @interface ResolvedLayoutDir {}
2630 
2631     /**
2632      * A flag to indicate that the layout direction of this view has not been defined yet.
2633      * @hide
2634      */
2635     public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
2636 
2637     /**
2638      * Horizontal layout direction of this view is from Left to Right.
2639      * Use with {@link #setLayoutDirection}.
2640      */
2641     public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
2642 
2643     /**
2644      * Horizontal layout direction of this view is from Right to Left.
2645      * Use with {@link #setLayoutDirection}.
2646      */
2647     public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
2648 
2649     /**
2650      * Horizontal layout direction of this view is inherited from its parent.
2651      * Use with {@link #setLayoutDirection}.
2652      */
2653     public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
2654 
2655     /**
2656      * Horizontal layout direction of this view is from deduced from the default language
2657      * script for the locale. Use with {@link #setLayoutDirection}.
2658      */
2659     public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
2660 
2661     /**
2662      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2663      * @hide
2664      */
2665     static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
2666 
2667     /**
2668      * Mask for use with private flags indicating bits used for horizontal layout direction.
2669      * @hide
2670      */
2671     static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2672 
2673     /**
2674      * Indicates whether the view horizontal layout direction has been resolved and drawn to the
2675      * right-to-left direction.
2676      * @hide
2677      */
2678     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2679 
2680     /**
2681      * Indicates whether the view horizontal layout direction has been resolved.
2682      * @hide
2683      */
2684     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2685 
2686     /**
2687      * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
2688      * @hide
2689      */
2690     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
2691             << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2692 
2693     /*
2694      * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
2695      * flag value.
2696      * @hide
2697      */
2698     private static final int[] LAYOUT_DIRECTION_FLAGS = {
2699             LAYOUT_DIRECTION_LTR,
2700             LAYOUT_DIRECTION_RTL,
2701             LAYOUT_DIRECTION_INHERIT,
2702             LAYOUT_DIRECTION_LOCALE
2703     };
2704 
2705     /**
2706      * Default horizontal layout direction.
2707      */
2708     private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
2709 
2710     /**
2711      * Default horizontal layout direction.
2712      * @hide
2713      */
2714     static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
2715 
2716     /**
2717      * Text direction is inherited through {@link ViewGroup}
2718      */
2719     public static final int TEXT_DIRECTION_INHERIT = 0;
2720 
2721     /**
2722      * Text direction is using "first strong algorithm". The first strong directional character
2723      * determines the paragraph direction. If there is no strong directional character, the
2724      * paragraph direction is the view's resolved layout direction.
2725      */
2726     public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2727 
2728     /**
2729      * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2730      * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2731      * If there are neither, the paragraph direction is the view's resolved layout direction.
2732      */
2733     public static final int TEXT_DIRECTION_ANY_RTL = 2;
2734 
2735     /**
2736      * Text direction is forced to LTR.
2737      */
2738     public static final int TEXT_DIRECTION_LTR = 3;
2739 
2740     /**
2741      * Text direction is forced to RTL.
2742      */
2743     public static final int TEXT_DIRECTION_RTL = 4;
2744 
2745     /**
2746      * Text direction is coming from the system Locale.
2747      */
2748     public static final int TEXT_DIRECTION_LOCALE = 5;
2749 
2750     /**
2751      * Text direction is using "first strong algorithm". The first strong directional character
2752      * determines the paragraph direction. If there is no strong directional character, the
2753      * paragraph direction is LTR.
2754      */
2755     public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2756 
2757     /**
2758      * Text direction is using "first strong algorithm". The first strong directional character
2759      * determines the paragraph direction. If there is no strong directional character, the
2760      * paragraph direction is RTL.
2761      */
2762     public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2763 
2764     /**
2765      * Default text direction is inherited
2766      */
2767     private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2768 
2769     /**
2770      * Default resolved text direction
2771      * @hide
2772      */
2773     static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2774 
2775     /**
2776      * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2777      * @hide
2778      */
2779     static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2780 
2781     /**
2782      * Mask for use with private flags indicating bits used for text direction.
2783      * @hide
2784      */
2785     static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2786             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2787 
2788     /**
2789      * Array of text direction flags for mapping attribute "textDirection" to correct
2790      * flag value.
2791      * @hide
2792      */
2793     private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2794             TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2795             TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2796             TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2797             TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2798             TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2799             TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2800             TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2801             TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2802     };
2803 
2804     /**
2805      * Indicates whether the view text direction has been resolved.
2806      * @hide
2807      */
2808     static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2809             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2810 
2811     /**
2812      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2813      * @hide
2814      */
2815     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2816 
2817     /**
2818      * Mask for use with private flags indicating bits used for resolved text direction.
2819      * @hide
2820      */
2821     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2822             << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2823 
2824     /**
2825      * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2826      * @hide
2827      */
2828     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2829             TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2830 
2831     /** @hide */
2832     @IntDef(prefix = { "TEXT_ALIGNMENT_" }, value = {
2833             TEXT_ALIGNMENT_INHERIT,
2834             TEXT_ALIGNMENT_GRAVITY,
2835             TEXT_ALIGNMENT_CENTER,
2836             TEXT_ALIGNMENT_TEXT_START,
2837             TEXT_ALIGNMENT_TEXT_END,
2838             TEXT_ALIGNMENT_VIEW_START,
2839             TEXT_ALIGNMENT_VIEW_END
2840     })
2841     @Retention(RetentionPolicy.SOURCE)
2842     public @interface TextAlignment {}
2843 
2844     /**
2845      * Default text alignment. The text alignment of this View is inherited from its parent.
2846      * Use with {@link #setTextAlignment(int)}
2847      */
2848     public static final int TEXT_ALIGNMENT_INHERIT = 0;
2849 
2850     /**
2851      * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2852      * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph's text direction.
2853      *
2854      * Use with {@link #setTextAlignment(int)}
2855      */
2856     public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2857 
2858     /**
2859      * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2860      *
2861      * Use with {@link #setTextAlignment(int)}
2862      */
2863     public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2864 
2865     /**
2866      * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2867      *
2868      * Use with {@link #setTextAlignment(int)}
2869      */
2870     public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2871 
2872     /**
2873      * Center the paragraph, e.g. ALIGN_CENTER.
2874      *
2875      * Use with {@link #setTextAlignment(int)}
2876      */
2877     public static final int TEXT_ALIGNMENT_CENTER = 4;
2878 
2879     /**
2880      * Align to the start of the view, which is ALIGN_LEFT if the view's resolved
2881      * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2882      *
2883      * Use with {@link #setTextAlignment(int)}
2884      */
2885     public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2886 
2887     /**
2888      * Align to the end of the view, which is ALIGN_RIGHT if the view's resolved
2889      * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2890      *
2891      * Use with {@link #setTextAlignment(int)}
2892      */
2893     public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2894 
2895     /**
2896      * Default text alignment is inherited
2897      */
2898     private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2899 
2900     /**
2901      * Default resolved text alignment
2902      * @hide
2903      */
2904     static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2905 
2906     /**
2907       * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2908       * @hide
2909       */
2910     static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2911 
2912     /**
2913       * Mask for use with private flags indicating bits used for text alignment.
2914       * @hide
2915       */
2916     static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2917 
2918     /**
2919      * Array of text direction flags for mapping attribute "textAlignment" to correct
2920      * flag value.
2921      * @hide
2922      */
2923     private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2924             TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2925             TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2926             TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2927             TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2928             TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2929             TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2930             TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2931     };
2932 
2933     /**
2934      * Indicates whether the view text alignment has been resolved.
2935      * @hide
2936      */
2937     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2938 
2939     /**
2940      * Bit shift to get the resolved text alignment.
2941      * @hide
2942      */
2943     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2944 
2945     /**
2946      * Mask for use with private flags indicating bits used for text alignment.
2947      * @hide
2948      */
2949     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2950             << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2951 
2952     /**
2953      * Indicates whether if the view text alignment has been resolved to gravity
2954      */
2955     private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2956             TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2957 
2958     // Accessiblity constants for mPrivateFlags2
2959 
2960     /**
2961      * Shift for the bits in {@link #mPrivateFlags2} related to the
2962      * "importantForAccessibility" attribute.
2963      */
2964     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2965 
2966     /**
2967      * Automatically determine whether a view is important for accessibility.
2968      */
2969     public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2970 
2971     /**
2972      * The view is important for accessibility.
2973      */
2974     public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2975 
2976     /**
2977      * The view is not important for accessibility.
2978      */
2979     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2980 
2981     /**
2982      * The view is not important for accessibility, nor are any of its
2983      * descendant views.
2984      */
2985     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2986 
2987     /**
2988      * The default whether the view is important for accessibility.
2989      */
2990     static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2991 
2992     /**
2993      * Mask for obtaining the bits which specify how to determine
2994      * whether a view is important for accessibility.
2995      */
2996     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2997         | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2998         | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2999         << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
3000 
3001     /**
3002      * Shift for the bits in {@link #mPrivateFlags2} related to the
3003      * "accessibilityLiveRegion" attribute.
3004      */
3005     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
3006 
3007     /**
3008      * Live region mode specifying that accessibility services should not
3009      * automatically announce changes to this view. This is the default live
3010      * region mode for most views.
3011      * <p>
3012      * Use with {@link #setAccessibilityLiveRegion(int)}.
3013      */
3014     public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
3015 
3016     /**
3017      * Live region mode specifying that accessibility services should announce
3018      * changes to this view.
3019      * <p>
3020      * Use with {@link #setAccessibilityLiveRegion(int)}.
3021      */
3022     public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
3023 
3024     /**
3025      * Live region mode specifying that accessibility services should interrupt
3026      * ongoing speech to immediately announce changes to this view.
3027      * <p>
3028      * Use with {@link #setAccessibilityLiveRegion(int)}.
3029      */
3030     public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
3031 
3032     /**
3033      * The default whether the view is important for accessibility.
3034      */
3035     static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
3036 
3037     /**
3038      * Mask for obtaining the bits which specify a view's accessibility live
3039      * region mode.
3040      */
3041     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
3042             | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
3043             << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
3044 
3045     /**
3046      * Flag indicating whether a view has accessibility focus.
3047      */
3048     static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
3049 
3050     /**
3051      * Flag whether the accessibility state of the subtree rooted at this view changed.
3052      */
3053     static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
3054 
3055     /**
3056      * Flag indicating whether a view failed the quickReject() check in draw(). This condition
3057      * is used to check whether later changes to the view's transform should invalidate the
3058      * view to force the quickReject test to run again.
3059      */
3060     static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
3061 
3062     /**
3063      * Flag indicating that start/end padding has been resolved into left/right padding
3064      * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
3065      * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
3066      * during measurement. In some special cases this is required such as when an adapter-based
3067      * view measures prospective children without attaching them to a window.
3068      */
3069     static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
3070 
3071     /**
3072      * Flag indicating that the start/end drawables has been resolved into left/right ones.
3073      */
3074     static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
3075 
3076     /**
3077      * Indicates that the view is tracking some sort of transient state
3078      * that the app should not need to be aware of, but that the framework
3079      * should take special care to preserve.
3080      */
3081     static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
3082 
3083     /**
3084      * Group of bits indicating that RTL properties resolution is done.
3085      */
3086     static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
3087             PFLAG2_TEXT_DIRECTION_RESOLVED |
3088             PFLAG2_TEXT_ALIGNMENT_RESOLVED |
3089             PFLAG2_PADDING_RESOLVED |
3090             PFLAG2_DRAWABLE_RESOLVED;
3091 
3092     // There are a couple of flags left in mPrivateFlags2
3093 
3094     /* End of masks for mPrivateFlags2 */
3095 
3096     /*
3097      * Masks for mPrivateFlags3, as generated by dumpFlags():
3098      *
3099      * |-------|-------|-------|-------|
3100      *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
3101      *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
3102      *                               1   PFLAG3_IS_LAID_OUT
3103      *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
3104      *                             1     PFLAG3_CALLED_SUPER
3105      *                            1      PFLAG3_APPLYING_INSETS
3106      *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
3107      *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
3108      *                         1         PFLAG3_SCROLL_INDICATOR_TOP
3109      *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
3110      *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
3111      *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
3112      *                     1             PFLAG3_SCROLL_INDICATOR_START
3113      *                    1              PFLAG3_SCROLL_INDICATOR_END
3114      *                   1               PFLAG3_ASSIST_BLOCKED
3115      *                  1                PFLAG3_CLUSTER
3116      *                 1                 PFLAG3_IS_AUTOFILLED
3117      *                1                  PFLAG3_FINGER_DOWN
3118      *               1                   PFLAG3_FOCUSED_BY_DEFAULT
3119      *           1111                    PFLAG3_IMPORTANT_FOR_AUTOFILL
3120      *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
3121      *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
3122      *        1                          PFLAG3_TEMPORARY_DETACH
3123      *       1                           PFLAG3_NO_REVEAL_ON_FOCUS
3124      *      1                            PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT
3125      *     1                             PFLAG3_SCREEN_READER_FOCUSABLE
3126      *    1                              PFLAG3_AGGREGATED_VISIBLE
3127      *   1                               PFLAG3_AUTOFILLID_EXPLICITLY_SET
3128      *  1                                PFLAG3_ACCESSIBILITY_HEADING
3129      * |-------|-------|-------|-------|
3130      */
3131 
3132     /**
3133      * Flag indicating that view has a transform animation set on it. This is used to track whether
3134      * an animation is cleared between successive frames, in order to tell the associated
3135      * DisplayList to clear its animation matrix.
3136      */
3137     static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
3138 
3139     /**
3140      * Flag indicating that view has an alpha animation set on it. This is used to track whether an
3141      * animation is cleared between successive frames, in order to tell the associated
3142      * DisplayList to restore its alpha value.
3143      */
3144     static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
3145 
3146     /**
3147      * Flag indicating that the view has been through at least one layout since it
3148      * was last attached to a window.
3149      */
3150     static final int PFLAG3_IS_LAID_OUT = 0x4;
3151 
3152     /**
3153      * Flag indicating that a call to measure() was skipped and should be done
3154      * instead when layout() is invoked.
3155      */
3156     static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
3157 
3158     /**
3159      * Flag indicating that an overridden method correctly called down to
3160      * the superclass implementation as required by the API spec.
3161      */
3162     static final int PFLAG3_CALLED_SUPER = 0x10;
3163 
3164     /**
3165      * Flag indicating that we're in the process of applying window insets.
3166      */
3167     static final int PFLAG3_APPLYING_INSETS = 0x20;
3168 
3169     /**
3170      * Flag indicating that we're in the process of fitting system windows using the old method.
3171      */
3172     static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
3173 
3174     /**
3175      * Flag indicating that nested scrolling is enabled for this view.
3176      * The view will optionally cooperate with views up its parent chain to allow for
3177      * integrated nested scrolling along the same axis.
3178      */
3179     static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
3180 
3181     /**
3182      * Flag indicating that the bottom scroll indicator should be displayed
3183      * when this view can scroll up.
3184      */
3185     static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
3186 
3187     /**
3188      * Flag indicating that the bottom scroll indicator should be displayed
3189      * when this view can scroll down.
3190      */
3191     static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
3192 
3193     /**
3194      * Flag indicating that the left scroll indicator should be displayed
3195      * when this view can scroll left.
3196      */
3197     static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
3198 
3199     /**
3200      * Flag indicating that the right scroll indicator should be displayed
3201      * when this view can scroll right.
3202      */
3203     static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
3204 
3205     /**
3206      * Flag indicating that the start scroll indicator should be displayed
3207      * when this view can scroll in the start direction.
3208      */
3209     static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
3210 
3211     /**
3212      * Flag indicating that the end scroll indicator should be displayed
3213      * when this view can scroll in the end direction.
3214      */
3215     static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
3216 
3217     static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
3218 
3219     static final int SCROLL_INDICATORS_NONE = 0x0000;
3220 
3221     /**
3222      * Mask for use with setFlags indicating bits used for indicating which
3223      * scroll indicators are enabled.
3224      */
3225     static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
3226             | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
3227             | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
3228             | PFLAG3_SCROLL_INDICATOR_END;
3229 
3230     /**
3231      * Left-shift required to translate between public scroll indicator flags
3232      * and internal PFLAGS3 flags. When used as a right-shift, translates
3233      * PFLAGS3 flags to public flags.
3234      */
3235     static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
3236 
3237     /** @hide */
3238     @Retention(RetentionPolicy.SOURCE)
3239     @IntDef(flag = true, prefix = { "SCROLL_INDICATOR_" }, value = {
3240             SCROLL_INDICATOR_TOP,
3241             SCROLL_INDICATOR_BOTTOM,
3242             SCROLL_INDICATOR_LEFT,
3243             SCROLL_INDICATOR_RIGHT,
3244             SCROLL_INDICATOR_START,
3245             SCROLL_INDICATOR_END,
3246     })
3247     public @interface ScrollIndicators {}
3248 
3249     /**
3250      * Scroll indicator direction for the top edge of the view.
3251      *
3252      * @see #setScrollIndicators(int)
3253      * @see #setScrollIndicators(int, int)
3254      * @see #getScrollIndicators()
3255      */
3256     public static final int SCROLL_INDICATOR_TOP =
3257             PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3258 
3259     /**
3260      * Scroll indicator direction for the bottom edge of the view.
3261      *
3262      * @see #setScrollIndicators(int)
3263      * @see #setScrollIndicators(int, int)
3264      * @see #getScrollIndicators()
3265      */
3266     public static final int SCROLL_INDICATOR_BOTTOM =
3267             PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3268 
3269     /**
3270      * Scroll indicator direction for the left edge of the view.
3271      *
3272      * @see #setScrollIndicators(int)
3273      * @see #setScrollIndicators(int, int)
3274      * @see #getScrollIndicators()
3275      */
3276     public static final int SCROLL_INDICATOR_LEFT =
3277             PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3278 
3279     /**
3280      * Scroll indicator direction for the right edge of the view.
3281      *
3282      * @see #setScrollIndicators(int)
3283      * @see #setScrollIndicators(int, int)
3284      * @see #getScrollIndicators()
3285      */
3286     public static final int SCROLL_INDICATOR_RIGHT =
3287             PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3288 
3289     /**
3290      * Scroll indicator direction for the starting edge of the view.
3291      * <p>
3292      * Resolved according to the view's layout direction, see
3293      * {@link #getLayoutDirection()} for more information.
3294      *
3295      * @see #setScrollIndicators(int)
3296      * @see #setScrollIndicators(int, int)
3297      * @see #getScrollIndicators()
3298      */
3299     public static final int SCROLL_INDICATOR_START =
3300             PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3301 
3302     /**
3303      * Scroll indicator direction for the ending edge of the view.
3304      * <p>
3305      * Resolved according to the view's layout direction, see
3306      * {@link #getLayoutDirection()} for more information.
3307      *
3308      * @see #setScrollIndicators(int)
3309      * @see #setScrollIndicators(int, int)
3310      * @see #getScrollIndicators()
3311      */
3312     public static final int SCROLL_INDICATOR_END =
3313             PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3314 
3315     /**
3316      * <p>Indicates that we are allowing {@link ViewStructure} to traverse
3317      * into this view.<p>
3318      */
3319     static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
3320 
3321     /**
3322      * Flag indicating that the view is a root of a keyboard navigation cluster.
3323      *
3324      * @see #isKeyboardNavigationCluster()
3325      * @see #setKeyboardNavigationCluster(boolean)
3326      */
3327     private static final int PFLAG3_CLUSTER = 0x8000;
3328 
3329     /**
3330      * Flag indicating that the view is autofilled
3331      *
3332      * @see #isAutofilled()
3333      * @see #setAutofilled(boolean)
3334      */
3335     private static final int PFLAG3_IS_AUTOFILLED = 0x10000;
3336 
3337     /**
3338      * Indicates that the user is currently touching the screen.
3339      * Currently used for the tooltip positioning only.
3340      */
3341     private static final int PFLAG3_FINGER_DOWN = 0x20000;
3342 
3343     /**
3344      * Flag indicating that this view is the default-focus view.
3345      *
3346      * @see #isFocusedByDefault()
3347      * @see #setFocusedByDefault(boolean)
3348      */
3349     private static final int PFLAG3_FOCUSED_BY_DEFAULT = 0x40000;
3350 
3351     /**
3352      * Shift for the bits in {@link #mPrivateFlags3} related to the
3353      * "importantForAutofill" attribute.
3354      */
3355     static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT = 19;
3356 
3357     /**
3358      * Mask for obtaining the bits which specify how to determine
3359      * whether a view is important for autofill.
3360      */
3361     static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK = (IMPORTANT_FOR_AUTOFILL_AUTO
3362             | IMPORTANT_FOR_AUTOFILL_YES | IMPORTANT_FOR_AUTOFILL_NO
3363             | IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
3364             | IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS)
3365             << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
3366 
3367     /**
3368      * Whether this view has rendered elements that overlap (see {@link
3369      * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
3370      * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
3371      * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
3372      * determined by whatever {@link #hasOverlappingRendering()} returns.
3373      */
3374     private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
3375 
3376     /**
3377      * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
3378      * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
3379      */
3380     private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
3381 
3382     /**
3383      * Flag indicating that the view is temporarily detached from the parent view.
3384      *
3385      * @see #onStartTemporaryDetach()
3386      * @see #onFinishTemporaryDetach()
3387      */
3388     static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
3389 
3390     /**
3391      * Flag indicating that the view does not wish to be revealed within its parent
3392      * hierarchy when it gains focus. Expressed in the negative since the historical
3393      * default behavior is to reveal on focus; this flag suppresses that behavior.
3394      *
3395      * @see #setRevealOnFocusHint(boolean)
3396      * @see #getRevealOnFocusHint()
3397      */
3398     private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
3399 
3400     /**
3401      * Flag indicating that when layout is completed we should notify
3402      * that the view was entered for autofill purposes. To minimize
3403      * showing autofill for views not visible to the user we evaluate
3404      * user visibility which cannot be done until the view is laid out.
3405      */
3406     static final int PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT = 0x8000000;
3407 
3408     /**
3409      * Works like focusable for screen readers, but without the side effects on input focus.
3410      * @see #setScreenReaderFocusable(boolean)
3411      */
3412     private static final int PFLAG3_SCREEN_READER_FOCUSABLE = 0x10000000;
3413 
3414     /**
3415      * The last aggregated visibility. Used to detect when it truly changes.
3416      */
3417     private static final int PFLAG3_AGGREGATED_VISIBLE = 0x20000000;
3418 
3419     /**
3420      * Used to indicate that {@link #mAutofillId} was explicitly set through
3421      * {@link #setAutofillId(AutofillId)}.
3422      */
3423     private static final int PFLAG3_AUTOFILLID_EXPLICITLY_SET = 0x40000000;
3424 
3425     /**
3426      * Indicates if the View is a heading for accessibility purposes
3427      */
3428     private static final int PFLAG3_ACCESSIBILITY_HEADING = 0x80000000;
3429 
3430     /* End of masks for mPrivateFlags3 */
3431 
3432     /*
3433      * Masks for mPrivateFlags4, as generated by dumpFlags():
3434      *
3435      * |-------|-------|-------|-------|
3436      *                             1111 PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK
3437      *                            1     PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED
3438      *                           1      PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED
3439      *                          1       PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED
3440      *                         1        PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE
3441      *                         11       PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK
3442      * |-------|-------|-------|-------|
3443      */
3444 
3445     /**
3446      * Mask for obtaining the bits which specify how to determine
3447      * whether a view is important for autofill.
3448      *
3449      * <p>NOTE: the important for content capture values were the first flags added and are set in
3450      * the rightmost position, so we don't need to shift them
3451      */
3452     private static final int PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK =
3453             IMPORTANT_FOR_CONTENT_CAPTURE_AUTO | IMPORTANT_FOR_CONTENT_CAPTURE_YES
3454             | IMPORTANT_FOR_CONTENT_CAPTURE_NO
3455             | IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
3456             | IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS;
3457 
3458     /*
3459      * Variables used to control when the IntelligenceManager.notifyNodeAdded()/removed() methods
3460      * should be called.
3461      *
3462      * The idea is to call notifyAppeared() after the view is layout and visible, then call
3463      * notifyDisappeared() when it's gone (without known when it was removed from the parent).
3464      */
3465     private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED = 0x10;
3466     private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED = 0x20;
3467 
3468     /*
3469      * Flags used to cache the value returned by isImportantForContentCapture while the view
3470      * hierarchy is being traversed.
3471      */
3472     private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED = 0x40;
3473     private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE = 0x80;
3474 
3475     private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK =
3476             PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED
3477             | PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
3478 
3479     /* End of masks for mPrivateFlags4 */
3480 
3481     /** @hide */
3482     protected static final int VIEW_STRUCTURE_FOR_ASSIST = 0;
3483     /** @hide */
3484     protected  static final int VIEW_STRUCTURE_FOR_AUTOFILL = 1;
3485     /** @hide */
3486     protected  static final int VIEW_STRUCTURE_FOR_CONTENT_CAPTURE = 2;
3487 
3488     /** @hide */
3489     @IntDef(flag = true, prefix = { "VIEW_STRUCTURE_FOR" }, value = {
3490             VIEW_STRUCTURE_FOR_ASSIST,
3491             VIEW_STRUCTURE_FOR_AUTOFILL,
3492             VIEW_STRUCTURE_FOR_CONTENT_CAPTURE
3493     })
3494     @Retention(RetentionPolicy.SOURCE)
3495     public @interface ViewStructureType {}
3496 
3497     /**
3498      * Always allow a user to over-scroll this view, provided it is a
3499      * view that can scroll.
3500      *
3501      * @see #getOverScrollMode()
3502      * @see #setOverScrollMode(int)
3503      */
3504     public static final int OVER_SCROLL_ALWAYS = 0;
3505 
3506     /**
3507      * Allow a user to over-scroll this view only if the content is large
3508      * enough to meaningfully scroll, provided it is a view that can scroll.
3509      *
3510      * @see #getOverScrollMode()
3511      * @see #setOverScrollMode(int)
3512      */
3513     public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
3514 
3515     /**
3516      * Never allow a user to over-scroll this view.
3517      *
3518      * @see #getOverScrollMode()
3519      * @see #setOverScrollMode(int)
3520      */
3521     public static final int OVER_SCROLL_NEVER = 2;
3522 
3523     /**
3524      * Special constant for {@link #setSystemUiVisibility(int)}: View has
3525      * requested the system UI (status bar) to be visible (the default).
3526      *
3527      * @see #setSystemUiVisibility(int)
3528      */
3529     public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
3530 
3531     /**
3532      * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
3533      * system UI to enter an unobtrusive "low profile" mode.
3534      *
3535      * <p>This is for use in games, book readers, video players, or any other
3536      * "immersive" application where the usual system chrome is deemed too distracting.
3537      *
3538      * <p>In low profile mode, the status bar and/or navigation icons may dim.
3539      *
3540      * @see #setSystemUiVisibility(int)
3541      */
3542     public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
3543 
3544     /**
3545      * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
3546      * system navigation be temporarily hidden.
3547      *
3548      * <p>This is an even less obtrusive state than that called for by
3549      * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
3550      * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
3551      * those to disappear. This is useful (in conjunction with the
3552      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
3553      * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
3554      * window flags) for displaying content using every last pixel on the display.
3555      *
3556      * <p>There is a limitation: because navigation controls are so important, the least user
3557      * interaction will cause them to reappear immediately.  When this happens, both
3558      * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
3559      * so that both elements reappear at the same time.
3560      *
3561      * @see #setSystemUiVisibility(int)
3562      */
3563     public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
3564 
3565     /**
3566      * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
3567      * into the normal fullscreen mode so that its content can take over the screen
3568      * while still allowing the user to interact with the application.
3569      *
3570      * <p>This has the same visual effect as
3571      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
3572      * WindowManager.LayoutParams.FLAG_FULLSCREEN},
3573      * meaning that non-critical screen decorations (such as the status bar) will be
3574      * hidden while the user is in the View's window, focusing the experience on
3575      * that content.  Unlike the window flag, if you are using ActionBar in
3576      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3577      * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
3578      * hide the action bar.
3579      *
3580      * <p>This approach to going fullscreen is best used over the window flag when
3581      * it is a transient state -- that is, the application does this at certain
3582      * points in its user interaction where it wants to allow the user to focus
3583      * on content, but not as a continuous state.  For situations where the application
3584      * would like to simply stay full screen the entire time (such as a game that
3585      * wants to take over the screen), the
3586      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
3587      * is usually a better approach.  The state set here will be removed by the system
3588      * in various situations (such as the user moving to another application) like
3589      * the other system UI states.
3590      *
3591      * <p>When using this flag, the application should provide some easy facility
3592      * for the user to go out of it.  A common example would be in an e-book
3593      * reader, where tapping on the screen brings back whatever screen and UI
3594      * decorations that had been hidden while the user was immersed in reading
3595      * the book.
3596      *
3597      * @see #setSystemUiVisibility(int)
3598      */
3599     public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
3600 
3601     /**
3602      * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
3603      * flags, we would like a stable view of the content insets given to
3604      * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
3605      * will always represent the worst case that the application can expect
3606      * as a continuous state.  In the stock Android UI this is the space for
3607      * the system bar, nav bar, and status bar, but not more transient elements
3608      * such as an input method.
3609      *
3610      * The stable layout your UI sees is based on the system UI modes you can
3611      * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
3612      * then you will get a stable layout for changes of the
3613      * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
3614      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
3615      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
3616      * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
3617      * with a stable layout.  (Note that you should avoid using
3618      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
3619      *
3620      * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
3621      * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
3622      * then a hidden status bar will be considered a "stable" state for purposes
3623      * here.  This allows your UI to continually hide the status bar, while still
3624      * using the system UI flags to hide the action bar while still retaining
3625      * a stable layout.  Note that changing the window fullscreen flag will never
3626      * provide a stable layout for a clean transition.
3627      *
3628      * <p>If you are using ActionBar in
3629      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3630      * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
3631      * insets it adds to those given to the application.
3632      */
3633     public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
3634 
3635     /**
3636      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3637      * to be laid out as if it has requested
3638      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
3639      * allows it to avoid artifacts when switching in and out of that mode, at
3640      * the expense that some of its user interface may be covered by screen
3641      * decorations when they are shown.  You can perform layout of your inner
3642      * UI elements to account for the navigation system UI through the
3643      * {@link #fitSystemWindows(Rect)} method.
3644      */
3645     public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
3646 
3647     /**
3648      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3649      * to be laid out as if it has requested
3650      * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
3651      * allows it to avoid artifacts when switching in and out of that mode, at
3652      * the expense that some of its user interface may be covered by screen
3653      * decorations when they are shown.  You can perform layout of your inner
3654      * UI elements to account for non-fullscreen system UI through the
3655      * {@link #fitSystemWindows(Rect)} method.
3656      *
3657      * <p>Note: on displays that have a {@link DisplayCutout}, the window may still be placed
3658      *  differently than if {@link #SYSTEM_UI_FLAG_FULLSCREEN} was set, if the
3659      *  window's {@link WindowManager.LayoutParams#layoutInDisplayCutoutMode
3660      *  layoutInDisplayCutoutMode} is
3661      *  {@link WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
3662      *  LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT}. To avoid this, use either of the other modes.
3663      *
3664      * @see WindowManager.LayoutParams#layoutInDisplayCutoutMode
3665      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
3666      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
3667      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
3668      */
3669     public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
3670 
3671     /**
3672      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3673      * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
3674      * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
3675      * user interaction.
3676      * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
3677      * has an effect when used in combination with that flag.</p>
3678      */
3679     public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
3680 
3681     /**
3682      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3683      * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
3684      * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
3685      * experience while also hiding the system bars.  If this flag is not set,
3686      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
3687      * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
3688      * if the user swipes from the top of the screen.
3689      * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
3690      * system gestures, such as swiping from the top of the screen.  These transient system bars
3691      * will overlay app's content, may have some degree of transparency, and will automatically
3692      * hide after a short timeout.
3693      * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
3694      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
3695      * with one or both of those flags.</p>
3696      */
3697     public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
3698 
3699     /**
3700      * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
3701      * is compatible with light status bar backgrounds.
3702      *
3703      * <p>For this to take effect, the window must request
3704      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3705      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3706      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
3707      *         FLAG_TRANSLUCENT_STATUS}.
3708      *
3709      * @see android.R.attr#windowLightStatusBar
3710      */
3711     public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
3712 
3713     /**
3714      * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3715      * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3716      */
3717     private static final int SYSTEM_UI_RESERVED_LEGACY1 = 0x00004000;
3718 
3719     /**
3720      * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3721      * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3722      */
3723     private static final int SYSTEM_UI_RESERVED_LEGACY2 = 0x00010000;
3724 
3725     /**
3726      * Flag for {@link #setSystemUiVisibility(int)}: Requests the navigation bar to draw in a mode
3727      * that is compatible with light navigation bar backgrounds.
3728      *
3729      * <p>For this to take effect, the window must request
3730      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3731      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3732      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION
3733      *         FLAG_TRANSLUCENT_NAVIGATION}.
3734      *
3735      * @see android.R.attr#windowLightNavigationBar
3736      */
3737     public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010;
3738 
3739     /**
3740      * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
3741      */
3742     @Deprecated
3743     public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
3744 
3745     /**
3746      * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
3747      */
3748     @Deprecated
3749     public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
3750 
3751     /**
3752      * @hide
3753      *
3754      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3755      * out of the public fields to keep the undefined bits out of the developer's way.
3756      *
3757      * Flag to make the status bar not expandable.  Unless you also
3758      * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
3759      */
3760     @UnsupportedAppUsage
3761     public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
3762 
3763     /**
3764      * @hide
3765      *
3766      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3767      * out of the public fields to keep the undefined bits out of the developer's way.
3768      *
3769      * Flag to hide notification icons and scrolling ticker text.
3770      */
3771     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
3772 
3773     /**
3774      * @hide
3775      *
3776      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3777      * out of the public fields to keep the undefined bits out of the developer's way.
3778      *
3779      * Flag to disable incoming notification alerts.  This will not block
3780      * icons, but it will block sound, vibrating and other visual or aural notifications.
3781      */
3782     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
3783 
3784     /**
3785      * @hide
3786      *
3787      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3788      * out of the public fields to keep the undefined bits out of the developer's way.
3789      *
3790      * Flag to hide only the scrolling ticker.  Note that
3791      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
3792      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
3793      */
3794     public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
3795 
3796     /**
3797      * @hide
3798      *
3799      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3800      * out of the public fields to keep the undefined bits out of the developer's way.
3801      *
3802      * Flag to hide the center system info area.
3803      */
3804     public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
3805 
3806     /**
3807      * @hide
3808      *
3809      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3810      * out of the public fields to keep the undefined bits out of the developer's way.
3811      *
3812      * Flag to hide only the home button.  Don't use this
3813      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3814      */
3815     @UnsupportedAppUsage
3816     public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
3817 
3818     /**
3819      * @hide
3820      *
3821      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3822      * out of the public fields to keep the undefined bits out of the developer's way.
3823      *
3824      * Flag to hide only the back button. Don't use this
3825      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3826      */
3827     @UnsupportedAppUsage
3828     public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
3829 
3830     /**
3831      * @hide
3832      *
3833      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3834      * out of the public fields to keep the undefined bits out of the developer's way.
3835      *
3836      * Flag to hide only the clock.  You might use this if your activity has
3837      * its own clock making the status bar's clock redundant.
3838      */
3839     public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
3840 
3841     /**
3842      * @hide
3843      *
3844      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3845      * out of the public fields to keep the undefined bits out of the developer's way.
3846      *
3847      * Flag to hide only the recent apps button. Don't use this
3848      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3849      */
3850     @UnsupportedAppUsage
3851     public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
3852 
3853     /**
3854      * @hide
3855      *
3856      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3857      * out of the public fields to keep the undefined bits out of the developer's way.
3858      *
3859      * Flag to disable the global search gesture. Don't use this
3860      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3861      */
3862     public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
3863 
3864     /**
3865      * @hide
3866      *
3867      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3868      * out of the public fields to keep the undefined bits out of the developer's way.
3869      *
3870      * Flag to specify that the status bar is displayed in transient mode.
3871      */
3872     public static final int STATUS_BAR_TRANSIENT = 0x04000000;
3873 
3874     /**
3875      * @hide
3876      *
3877      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3878      * out of the public fields to keep the undefined bits out of the developer's way.
3879      *
3880      * Flag to specify that the navigation bar is displayed in transient mode.
3881      */
3882     @UnsupportedAppUsage
3883     public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
3884 
3885     /**
3886      * @hide
3887      *
3888      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3889      * out of the public fields to keep the undefined bits out of the developer's way.
3890      *
3891      * Flag to specify that the hidden status bar would like to be shown.
3892      */
3893     public static final int STATUS_BAR_UNHIDE = 0x10000000;
3894 
3895     /**
3896      * @hide
3897      *
3898      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3899      * out of the public fields to keep the undefined bits out of the developer's way.
3900      *
3901      * Flag to specify that the hidden navigation bar would like to be shown.
3902      */
3903     public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
3904 
3905     /**
3906      * @hide
3907      *
3908      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3909      * out of the public fields to keep the undefined bits out of the developer's way.
3910      *
3911      * Flag to specify that the status bar is displayed in translucent mode.
3912      */
3913     public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
3914 
3915     /**
3916      * @hide
3917      *
3918      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3919      * out of the public fields to keep the undefined bits out of the developer's way.
3920      *
3921      * Flag to specify that the navigation bar is displayed in translucent mode.
3922      */
3923     public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
3924 
3925     /**
3926      * @hide
3927      *
3928      * Makes navigation bar transparent (but not the status bar).
3929      */
3930     public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
3931 
3932     /**
3933      * @hide
3934      *
3935      * Makes status bar transparent (but not the navigation bar).
3936      */
3937     public static final int STATUS_BAR_TRANSPARENT = 0x00000008;
3938 
3939     /**
3940      * @hide
3941      *
3942      * Makes both status bar and navigation bar transparent.
3943      */
3944     public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
3945             | STATUS_BAR_TRANSPARENT;
3946 
3947     /**
3948      * @hide
3949      */
3950     public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
3951 
3952     /**
3953      * These are the system UI flags that can be cleared by events outside
3954      * of an application.  Currently this is just the ability to tap on the
3955      * screen while hiding the navigation bar to have it return.
3956      * @hide
3957      */
3958     public static final int SYSTEM_UI_CLEARABLE_FLAGS =
3959             SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
3960             | SYSTEM_UI_FLAG_FULLSCREEN;
3961 
3962     /**
3963      * Flags that can impact the layout in relation to system UI.
3964      */
3965     public static final int SYSTEM_UI_LAYOUT_FLAGS =
3966             SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3967             | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
3968 
3969     /** @hide */
3970     @IntDef(flag = true, prefix = { "FIND_VIEWS_" }, value = {
3971             FIND_VIEWS_WITH_TEXT,
3972             FIND_VIEWS_WITH_CONTENT_DESCRIPTION
3973     })
3974     @Retention(RetentionPolicy.SOURCE)
3975     public @interface FindViewFlags {}
3976 
3977     /**
3978      * Find views that render the specified text.
3979      *
3980      * @see #findViewsWithText(ArrayList, CharSequence, int)
3981      */
3982     public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
3983 
3984     /**
3985      * Find find views that contain the specified content description.
3986      *
3987      * @see #findViewsWithText(ArrayList, CharSequence, int)
3988      */
3989     public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
3990 
3991     /**
3992      * Find views that contain {@link AccessibilityNodeProvider}. Such
3993      * a View is a root of virtual view hierarchy and may contain the searched
3994      * text. If this flag is set Views with providers are automatically
3995      * added and it is a responsibility of the client to call the APIs of
3996      * the provider to determine whether the virtual tree rooted at this View
3997      * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3998      * representing the virtual views with this text.
3999      *
4000      * @see #findViewsWithText(ArrayList, CharSequence, int)
4001      *
4002      * @hide
4003      */
4004     public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
4005 
4006     /**
4007      * The undefined cursor position.
4008      *
4009      * @hide
4010      */
4011     public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
4012 
4013     /**
4014      * Indicates that the screen has changed state and is now off.
4015      *
4016      * @see #onScreenStateChanged(int)
4017      */
4018     public static final int SCREEN_STATE_OFF = 0x0;
4019 
4020     /**
4021      * Indicates that the screen has changed state and is now on.
4022      *
4023      * @see #onScreenStateChanged(int)
4024      */
4025     public static final int SCREEN_STATE_ON = 0x1;
4026 
4027     /**
4028      * Indicates no axis of view scrolling.
4029      */
4030     public static final int SCROLL_AXIS_NONE = 0;
4031 
4032     /**
4033      * Indicates scrolling along the horizontal axis.
4034      */
4035     public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
4036 
4037     /**
4038      * Indicates scrolling along the vertical axis.
4039      */
4040     public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
4041 
4042     /**
4043      * Controls the over-scroll mode for this view.
4044      * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
4045      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
4046      * and {@link #OVER_SCROLL_NEVER}.
4047      */
4048     private int mOverScrollMode;
4049 
4050     /**
4051      * The parent this view is attached to.
4052      * {@hide}
4053      *
4054      * @see #getParent()
4055      */
4056     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4057     protected ViewParent mParent;
4058 
4059     /**
4060      * {@hide}
4061      *
4062      * Not available for general use. If you need help, hang up and then dial one of the following
4063      * public APIs:
4064      *
4065      * @see #isAttachedToWindow() for current attach state
4066      * @see #onAttachedToWindow() for subclasses performing work when becoming attached
4067      * @see #onDetachedFromWindow() for subclasses performing work when becoming detached
4068      * @see OnAttachStateChangeListener for other code performing work on attach/detach
4069      * @see #getHandler() for posting messages to this view's UI thread/looper
4070      * @see #getParent() for interacting with the parent chain
4071      * @see #getWindowToken() for the current window token
4072      * @see #getRootView() for the view at the root of the attached hierarchy
4073      * @see #getDisplay() for the Display this view is presented on
4074      * @see #getRootWindowInsets() for the current insets applied to the whole attached window
4075      * @see #hasWindowFocus() for whether the attached window is currently focused
4076      * @see #getWindowVisibility() for checking the visibility of the attached window
4077      */
4078     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4079     AttachInfo mAttachInfo;
4080 
4081     /**
4082      * {@hide}
4083      */
4084     @ViewDebug.ExportedProperty(flagMapping = {
4085         @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
4086                 name = "FORCE_LAYOUT"),
4087         @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
4088                 name = "LAYOUT_REQUIRED"),
4089         @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
4090             name = "DRAWING_CACHE_INVALID", outputIf = false),
4091         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
4092         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
4093         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
4094     }, formatToHexString = true)
4095 
4096     /* @hide */
4097     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769414)
4098     public int mPrivateFlags;
4099     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768943)
4100     int mPrivateFlags2;
4101     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 129147060)
4102     int mPrivateFlags3;
4103 
4104     private int mPrivateFlags4;
4105 
4106     /**
4107      * This view's request for the visibility of the status bar.
4108      * @hide
4109      */
4110     @ViewDebug.ExportedProperty(flagMapping = {
4111             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
4112                     equals = SYSTEM_UI_FLAG_LOW_PROFILE,
4113                     name = "LOW_PROFILE"),
4114             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
4115                     equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
4116                     name = "HIDE_NAVIGATION"),
4117             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_FULLSCREEN,
4118                     equals = SYSTEM_UI_FLAG_FULLSCREEN,
4119                     name = "FULLSCREEN"),
4120             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_STABLE,
4121                     equals = SYSTEM_UI_FLAG_LAYOUT_STABLE,
4122                     name = "LAYOUT_STABLE"),
4123             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
4124                     equals = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
4125                     name = "LAYOUT_HIDE_NAVIGATION"),
4126             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
4127                     equals = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
4128                     name = "LAYOUT_FULLSCREEN"),
4129             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE,
4130                     equals = SYSTEM_UI_FLAG_IMMERSIVE,
4131                     name = "IMMERSIVE"),
4132             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
4133                     equals = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
4134                     name = "IMMERSIVE_STICKY"),
4135             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
4136                     equals = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
4137                     name = "LIGHT_STATUS_BAR"),
4138             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
4139                     equals = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
4140                     name = "LIGHT_NAVIGATION_BAR"),
4141             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_EXPAND,
4142                     equals = STATUS_BAR_DISABLE_EXPAND,
4143                     name = "STATUS_BAR_DISABLE_EXPAND"),
4144             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
4145                     equals = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
4146                     name = "STATUS_BAR_DISABLE_NOTIFICATION_ICONS"),
4147             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
4148                     equals = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
4149                     name = "STATUS_BAR_DISABLE_NOTIFICATION_ALERTS"),
4150             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
4151                     equals = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
4152                     name = "STATUS_BAR_DISABLE_NOTIFICATION_TICKER"),
4153             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SYSTEM_INFO,
4154                     equals = STATUS_BAR_DISABLE_SYSTEM_INFO,
4155                     name = "STATUS_BAR_DISABLE_SYSTEM_INFO"),
4156             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_HOME,
4157                     equals = STATUS_BAR_DISABLE_HOME,
4158                     name = "STATUS_BAR_DISABLE_HOME"),
4159             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_BACK,
4160                     equals = STATUS_BAR_DISABLE_BACK,
4161                     name = "STATUS_BAR_DISABLE_BACK"),
4162             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_CLOCK,
4163                     equals = STATUS_BAR_DISABLE_CLOCK,
4164                     name = "STATUS_BAR_DISABLE_CLOCK"),
4165             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_RECENT,
4166                     equals = STATUS_BAR_DISABLE_RECENT,
4167                     name = "STATUS_BAR_DISABLE_RECENT"),
4168             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SEARCH,
4169                     equals = STATUS_BAR_DISABLE_SEARCH,
4170                     name = "STATUS_BAR_DISABLE_SEARCH"),
4171             @ViewDebug.FlagToString(mask = STATUS_BAR_TRANSIENT,
4172                     equals = STATUS_BAR_TRANSIENT,
4173                     name = "STATUS_BAR_TRANSIENT"),
4174             @ViewDebug.FlagToString(mask = NAVIGATION_BAR_TRANSIENT,
4175                     equals = NAVIGATION_BAR_TRANSIENT,
4176                     name = "NAVIGATION_BAR_TRANSIENT"),
4177             @ViewDebug.FlagToString(mask = STATUS_BAR_UNHIDE,
4178                     equals = STATUS_BAR_UNHIDE,
4179                     name = "STATUS_BAR_UNHIDE"),
4180             @ViewDebug.FlagToString(mask = NAVIGATION_BAR_UNHIDE,
4181                     equals = NAVIGATION_BAR_UNHIDE,
4182                     name = "NAVIGATION_BAR_UNHIDE"),
4183             @ViewDebug.FlagToString(mask = STATUS_BAR_TRANSLUCENT,
4184                     equals = STATUS_BAR_TRANSLUCENT,
4185                     name = "STATUS_BAR_TRANSLUCENT"),
4186             @ViewDebug.FlagToString(mask = NAVIGATION_BAR_TRANSLUCENT,
4187                     equals = NAVIGATION_BAR_TRANSLUCENT,
4188                     name = "NAVIGATION_BAR_TRANSLUCENT"),
4189             @ViewDebug.FlagToString(mask = NAVIGATION_BAR_TRANSPARENT,
4190                     equals = NAVIGATION_BAR_TRANSPARENT,
4191                     name = "NAVIGATION_BAR_TRANSPARENT"),
4192             @ViewDebug.FlagToString(mask = STATUS_BAR_TRANSPARENT,
4193                     equals = STATUS_BAR_TRANSPARENT,
4194                     name = "STATUS_BAR_TRANSPARENT")
4195     }, formatToHexString = true)
4196     int mSystemUiVisibility;
4197 
4198     /**
4199      * Reference count for transient state.
4200      * @see #setHasTransientState(boolean)
4201      */
4202     int mTransientStateCount = 0;
4203 
4204     /**
4205      * Count of how many windows this view has been attached to.
4206      */
4207     int mWindowAttachCount;
4208 
4209     /**
4210      * The layout parameters associated with this view and used by the parent
4211      * {@link android.view.ViewGroup} to determine how this view should be
4212      * laid out.
4213      *
4214      * The field should not be used directly. Instead {@link #getLayoutParams()} and {@link
4215      * #setLayoutParams(ViewGroup.LayoutParams)} should be used. The setter guarantees internal
4216      * state correctness of the class.
4217      * {@hide}
4218      */
4219     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4220     protected ViewGroup.LayoutParams mLayoutParams;
4221 
4222     /**
4223      * The view flags hold various views states.
4224      *
4225      * Use {@link #setTransitionVisibility(int)} to change the visibility of this view without
4226      * triggering updates.
4227      * {@hide}
4228      */
4229     @ViewDebug.ExportedProperty(formatToHexString = true)
4230     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4231     int mViewFlags;
4232 
4233     static class TransformationInfo {
4234         /**
4235          * The transform matrix for the View. This transform is calculated internally
4236          * based on the translation, rotation, and scale properties.
4237          *
4238          * Do *not* use this variable directly; instead call getMatrix(), which will
4239          * load the value from the View's RenderNode.
4240          */
4241         private final Matrix mMatrix = new Matrix();
4242 
4243         /**
4244          * The inverse transform matrix for the View. This transform is calculated
4245          * internally based on the translation, rotation, and scale properties.
4246          *
4247          * Do *not* use this variable directly; instead call getInverseMatrix(),
4248          * which will load the value from the View's RenderNode.
4249          */
4250         private Matrix mInverseMatrix;
4251 
4252         /**
4253          * The opacity of the View. This is a value from 0 to 1, where 0 means
4254          * completely transparent and 1 means completely opaque.
4255          */
4256         @ViewDebug.ExportedProperty
4257         private float mAlpha = 1f;
4258 
4259         /**
4260          * The opacity of the view as manipulated by the Fade transition. This is a
4261          * property only used by transitions, which is composited with the other alpha
4262          * values to calculate the final visual alpha value.
4263          */
4264         float mTransitionAlpha = 1f;
4265     }
4266 
4267     /** @hide */
4268     @UnsupportedAppUsage
4269     public TransformationInfo mTransformationInfo;
4270 
4271     /**
4272      * Current clip bounds. to which all drawing of this view are constrained.
4273      */
4274     @ViewDebug.ExportedProperty(category = "drawing")
4275     Rect mClipBounds = null;
4276 
4277     private boolean mLastIsOpaque;
4278 
4279     /**
4280      * The distance in pixels from the left edge of this view's parent
4281      * to the left edge of this view.
4282      * {@hide}
4283      */
4284     @ViewDebug.ExportedProperty(category = "layout")
4285     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4286     protected int mLeft;
4287     /**
4288      * The distance in pixels from the left edge of this view's parent
4289      * to the right edge of this view.
4290      * {@hide}
4291      */
4292     @ViewDebug.ExportedProperty(category = "layout")
4293     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4294     protected int mRight;
4295     /**
4296      * The distance in pixels from the top edge of this view's parent
4297      * to the top edge of this view.
4298      * {@hide}
4299      */
4300     @ViewDebug.ExportedProperty(category = "layout")
4301     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4302     protected int mTop;
4303     /**
4304      * The distance in pixels from the top edge of this view's parent
4305      * to the bottom edge of this view.
4306      * {@hide}
4307      */
4308     @ViewDebug.ExportedProperty(category = "layout")
4309     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4310     protected int mBottom;
4311 
4312     /**
4313      * The offset, in pixels, by which the content of this view is scrolled
4314      * horizontally.
4315      * Please use {@link View#getScrollX()} and {@link View#setScrollX(int)} instead of
4316      * accessing these directly.
4317      * {@hide}
4318      */
4319     @ViewDebug.ExportedProperty(category = "scrolling")
4320     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4321     protected int mScrollX;
4322     /**
4323      * The offset, in pixels, by which the content of this view is scrolled
4324      * vertically.
4325      * Please use {@link View#getScrollY()} and {@link View#setScrollY(int)} instead of
4326      * accessing these directly.
4327      * {@hide}
4328      */
4329     @ViewDebug.ExportedProperty(category = "scrolling")
4330     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4331     protected int mScrollY;
4332 
4333     /**
4334      * The final computed left padding in pixels that is used for drawing. This is the distance in
4335      * pixels between the left edge of this view and the left edge of its content.
4336      * {@hide}
4337      */
4338     @ViewDebug.ExportedProperty(category = "padding")
4339     @UnsupportedAppUsage
4340     protected int mPaddingLeft = 0;
4341     /**
4342      * The final computed right padding in pixels that is used for drawing. This is the distance in
4343      * pixels between the right edge of this view and the right edge of its content.
4344      * {@hide}
4345      */
4346     @ViewDebug.ExportedProperty(category = "padding")
4347     @UnsupportedAppUsage
4348     protected int mPaddingRight = 0;
4349     /**
4350      * The final computed top padding in pixels that is used for drawing. This is the distance in
4351      * pixels between the top edge of this view and the top edge of its content.
4352      * {@hide}
4353      */
4354     @ViewDebug.ExportedProperty(category = "padding")
4355     @UnsupportedAppUsage
4356     protected int mPaddingTop;
4357     /**
4358      * The final computed bottom padding in pixels that is used for drawing. This is the distance in
4359      * pixels between the bottom edge of this view and the bottom edge of its content.
4360      * {@hide}
4361      */
4362     @ViewDebug.ExportedProperty(category = "padding")
4363     @UnsupportedAppUsage
4364     protected int mPaddingBottom;
4365 
4366     /**
4367      * The layout insets in pixels, that is the distance in pixels between the
4368      * visible edges of this view its bounds.
4369      */
4370     private Insets mLayoutInsets;
4371 
4372     /**
4373      * Briefly describes the view and is primarily used for accessibility support.
4374      */
4375     private CharSequence mContentDescription;
4376 
4377     /**
4378      * If this view represents a distinct part of the window, it can have a title that labels the
4379      * area.
4380      */
4381     private CharSequence mAccessibilityPaneTitle;
4382 
4383     /**
4384      * Specifies the id of a view for which this view serves as a label for
4385      * accessibility purposes.
4386      */
4387     private int mLabelForId = View.NO_ID;
4388 
4389     /**
4390      * Predicate for matching labeled view id with its label for
4391      * accessibility purposes.
4392      */
4393     private MatchLabelForPredicate mMatchLabelForPredicate;
4394 
4395     /**
4396      * Specifies a view before which this one is visited in accessibility traversal.
4397      */
4398     private int mAccessibilityTraversalBeforeId = NO_ID;
4399 
4400     /**
4401      * Specifies a view after which this one is visited in accessibility traversal.
4402      */
4403     private int mAccessibilityTraversalAfterId = NO_ID;
4404 
4405     /**
4406      * Predicate for matching a view by its id.
4407      */
4408     private MatchIdPredicate mMatchIdPredicate;
4409 
4410     /**
4411      * The right padding after RTL resolution, but before taking account of scroll bars.
4412      *
4413      * @hide
4414      */
4415     @ViewDebug.ExportedProperty(category = "padding")
4416     protected int mUserPaddingRight;
4417 
4418     /**
4419      * The resolved bottom padding before taking account of scroll bars.
4420      *
4421      * @hide
4422      */
4423     @ViewDebug.ExportedProperty(category = "padding")
4424     protected int mUserPaddingBottom;
4425 
4426     /**
4427      * The left padding after RTL resolution, but before taking account of scroll bars.
4428      *
4429      * @hide
4430      */
4431     @ViewDebug.ExportedProperty(category = "padding")
4432     protected int mUserPaddingLeft;
4433 
4434     /**
4435      * Cache the paddingStart set by the user to append to the scrollbar's size.
4436      *
4437      */
4438     @ViewDebug.ExportedProperty(category = "padding")
4439     int mUserPaddingStart;
4440 
4441     /**
4442      * Cache the paddingEnd set by the user to append to the scrollbar's size.
4443      *
4444      */
4445     @ViewDebug.ExportedProperty(category = "padding")
4446     int mUserPaddingEnd;
4447 
4448     /**
4449      * The left padding as set by a setter method, a background's padding, or via XML property
4450      * resolution. This value is the padding before LTR resolution or taking account of scrollbars.
4451      *
4452      * @hide
4453      */
4454     int mUserPaddingLeftInitial;
4455 
4456     /**
4457      * The right padding as set by a setter method, a background's padding, or via XML property
4458      * resolution. This value is the padding before LTR resolution or taking account of scrollbars.
4459      *
4460      * @hide
4461      */
4462     int mUserPaddingRightInitial;
4463 
4464     /**
4465      * Default undefined padding
4466      */
4467     private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
4468 
4469     /**
4470      * Cache if a left padding has been defined explicitly via padding, horizontal padding,
4471      * or leftPadding in XML, or by setPadding(...) or setRelativePadding(...)
4472      */
4473     private boolean mLeftPaddingDefined = false;
4474 
4475     /**
4476      * Cache if a right padding has been defined explicitly via padding, horizontal padding,
4477      * or rightPadding in XML, or by setPadding(...) or setRelativePadding(...)
4478      */
4479     private boolean mRightPaddingDefined = false;
4480 
4481     /**
4482      * @hide
4483      */
4484     int mOldWidthMeasureSpec = Integer.MIN_VALUE;
4485     /**
4486      * @hide
4487      */
4488     int mOldHeightMeasureSpec = Integer.MIN_VALUE;
4489 
4490     private LongSparseLongArray mMeasureCache;
4491 
4492     @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
4493     @UnsupportedAppUsage
4494     private Drawable mBackground;
4495     private TintInfo mBackgroundTint;
4496 
4497     @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
4498     private ForegroundInfo mForegroundInfo;
4499 
4500     private Drawable mScrollIndicatorDrawable;
4501 
4502     /**
4503      * RenderNode used for backgrounds.
4504      * <p>
4505      * When non-null and valid, this is expected to contain an up-to-date copy
4506      * of the background drawable. It is cleared on temporary detach, and reset
4507      * on cleanup.
4508      */
4509     private RenderNode mBackgroundRenderNode;
4510 
4511     @UnsupportedAppUsage
4512     private int mBackgroundResource;
4513     private boolean mBackgroundSizeChanged;
4514 
4515     /** The default focus highlight.
4516      * @see #mDefaultFocusHighlightEnabled
4517      * @see Drawable#hasFocusStateSpecified()
4518      */
4519     private Drawable mDefaultFocusHighlight;
4520     private Drawable mDefaultFocusHighlightCache;
4521     private boolean mDefaultFocusHighlightSizeChanged;
4522     /**
4523      * True if the default focus highlight is needed on the target device.
4524      */
4525     private static boolean sUseDefaultFocusHighlight;
4526 
4527     /**
4528      * True if zero-sized views can be focused.
4529      */
4530     private static boolean sCanFocusZeroSized;
4531 
4532     /**
4533      * Always assign focus if a focusable View is available.
4534      */
4535     private static boolean sAlwaysAssignFocus;
4536 
4537     private String mTransitionName;
4538 
4539     static class TintInfo {
4540         ColorStateList mTintList;
4541         BlendMode mBlendMode;
4542         boolean mHasTintMode;
4543         boolean mHasTintList;
4544     }
4545 
4546     private static class ForegroundInfo {
4547         private Drawable mDrawable;
4548         private TintInfo mTintInfo;
4549         private int mGravity = Gravity.FILL;
4550         private boolean mInsidePadding = true;
4551         private boolean mBoundsChanged = true;
4552         private final Rect mSelfBounds = new Rect();
4553         private final Rect mOverlayBounds = new Rect();
4554     }
4555 
4556     static class ListenerInfo {
4557 
4558         @UnsupportedAppUsage
ListenerInfo()4559         ListenerInfo() {
4560         }
4561 
4562         /**
4563          * Listener used to dispatch focus change events.
4564          * This field should be made private, so it is hidden from the SDK.
4565          * {@hide}
4566          */
4567         @UnsupportedAppUsage
4568         protected OnFocusChangeListener mOnFocusChangeListener;
4569 
4570         /**
4571          * Listeners for layout change events.
4572          */
4573         private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
4574 
4575         protected OnScrollChangeListener mOnScrollChangeListener;
4576 
4577         /**
4578          * Listeners for attach events.
4579          */
4580         private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
4581 
4582         /**
4583          * Listener used to dispatch click events.
4584          * This field should be made private, so it is hidden from the SDK.
4585          * {@hide}
4586          */
4587         @UnsupportedAppUsage
4588         public OnClickListener mOnClickListener;
4589 
4590         /**
4591          * Listener used to dispatch long click events.
4592          * This field should be made private, so it is hidden from the SDK.
4593          * {@hide}
4594          */
4595         @UnsupportedAppUsage
4596         protected OnLongClickListener mOnLongClickListener;
4597 
4598         /**
4599          * Listener used to dispatch context click events. This field should be made private, so it
4600          * is hidden from the SDK.
4601          * {@hide}
4602          */
4603         protected OnContextClickListener mOnContextClickListener;
4604 
4605         /**
4606          * Listener used to build the context menu.
4607          * This field should be made private, so it is hidden from the SDK.
4608          * {@hide}
4609          */
4610         @UnsupportedAppUsage
4611         protected OnCreateContextMenuListener mOnCreateContextMenuListener;
4612 
4613         @UnsupportedAppUsage
4614         private OnKeyListener mOnKeyListener;
4615 
4616         @UnsupportedAppUsage
4617         private OnTouchListener mOnTouchListener;
4618 
4619         @UnsupportedAppUsage
4620         private OnHoverListener mOnHoverListener;
4621 
4622         @UnsupportedAppUsage
4623         private OnGenericMotionListener mOnGenericMotionListener;
4624 
4625         @UnsupportedAppUsage
4626         private OnDragListener mOnDragListener;
4627 
4628         private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
4629 
4630         OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
4631 
4632         OnCapturedPointerListener mOnCapturedPointerListener;
4633 
4634         private ArrayList<OnUnhandledKeyEventListener> mUnhandledKeyListeners;
4635 
4636         private WindowInsetsAnimationListener mWindowInsetsAnimationListener;
4637 
4638         /**
4639          * This lives here since it's only valid for interactive views.
4640          */
4641         private List<Rect> mSystemGestureExclusionRects;
4642 
4643         /**
4644          * Used to track {@link #mSystemGestureExclusionRects}
4645          */
4646         public RenderNode.PositionUpdateListener mPositionUpdateListener;
4647     }
4648 
4649     @UnsupportedAppUsage
4650     ListenerInfo mListenerInfo;
4651 
4652     private static class TooltipInfo {
4653         /**
4654          * Text to be displayed in a tooltip popup.
4655          */
4656         @Nullable
4657         CharSequence mTooltipText;
4658 
4659         /**
4660          * View-relative position of the tooltip anchor point.
4661          */
4662         int mAnchorX;
4663         int mAnchorY;
4664 
4665         /**
4666          * The tooltip popup.
4667          */
4668         @Nullable
4669         TooltipPopup mTooltipPopup;
4670 
4671         /**
4672          * Set to true if the tooltip was shown as a result of a long click.
4673          */
4674         boolean mTooltipFromLongClick;
4675 
4676         /**
4677          * Keep these Runnables so that they can be used to reschedule.
4678          */
4679         Runnable mShowTooltipRunnable;
4680         Runnable mHideTooltipRunnable;
4681 
4682         /**
4683          * Hover move is ignored if it is within this distance in pixels from the previous one.
4684          */
4685         int mHoverSlop;
4686 
4687         /**
4688          * Update the anchor position if it significantly (that is by at least mHoverSlop)
4689          * different from the previously stored position. Ignoring insignificant changes
4690          * filters out the jitter which is typical for such input sources as stylus.
4691          *
4692          * @return True if the position has been updated.
4693          */
updateAnchorPos(MotionEvent event)4694         private boolean updateAnchorPos(MotionEvent event) {
4695             final int newAnchorX = (int) event.getX();
4696             final int newAnchorY = (int) event.getY();
4697             if (Math.abs(newAnchorX - mAnchorX) <= mHoverSlop
4698                     && Math.abs(newAnchorY - mAnchorY) <= mHoverSlop) {
4699                 return false;
4700             }
4701             mAnchorX = newAnchorX;
4702             mAnchorY = newAnchorY;
4703             return true;
4704         }
4705 
4706         /**
4707          *  Clear the anchor position to ensure that the next change is considered significant.
4708          */
clearAnchorPos()4709         private void clearAnchorPos() {
4710             mAnchorX = Integer.MAX_VALUE;
4711             mAnchorY = Integer.MAX_VALUE;
4712         }
4713     }
4714 
4715     TooltipInfo mTooltipInfo;
4716 
4717     // Temporary values used to hold (x,y) coordinates when delegating from the
4718     // two-arg performLongClick() method to the legacy no-arg version.
4719     private float mLongClickX = Float.NaN;
4720     private float mLongClickY = Float.NaN;
4721 
4722     /**
4723      * The application environment this view lives in.
4724      * This field should be made private, so it is hidden from the SDK.
4725      * {@hide}
4726      */
4727     @ViewDebug.ExportedProperty(deepExport = true)
4728     @UnsupportedAppUsage
4729     protected Context mContext;
4730 
4731     @UnsupportedAppUsage
4732     private final Resources mResources;
4733 
4734     @UnsupportedAppUsage
4735     private ScrollabilityCache mScrollCache;
4736 
4737     private int[] mDrawableState = null;
4738 
4739     ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
4740 
4741     /**
4742      * Animator that automatically runs based on state changes.
4743      */
4744     private StateListAnimator mStateListAnimator;
4745 
4746     /**
4747      * When this view has focus and the next focus is {@link #FOCUS_LEFT},
4748      * the user may specify which view to go to next.
4749      */
4750     private int mNextFocusLeftId = View.NO_ID;
4751 
4752     /**
4753      * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
4754      * the user may specify which view to go to next.
4755      */
4756     private int mNextFocusRightId = View.NO_ID;
4757 
4758     /**
4759      * When this view has focus and the next focus is {@link #FOCUS_UP},
4760      * the user may specify which view to go to next.
4761      */
4762     private int mNextFocusUpId = View.NO_ID;
4763 
4764     /**
4765      * When this view has focus and the next focus is {@link #FOCUS_DOWN},
4766      * the user may specify which view to go to next.
4767      */
4768     private int mNextFocusDownId = View.NO_ID;
4769 
4770     /**
4771      * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
4772      * the user may specify which view to go to next.
4773      */
4774     int mNextFocusForwardId = View.NO_ID;
4775 
4776     /**
4777      * User-specified next keyboard navigation cluster in the {@link #FOCUS_FORWARD} direction.
4778      *
4779      * @see #findUserSetNextKeyboardNavigationCluster(View, int)
4780      */
4781     int mNextClusterForwardId = View.NO_ID;
4782 
4783     /**
4784      * Whether this View should use a default focus highlight when it gets focused but doesn't
4785      * have {@link android.R.attr#state_focused} defined in its background.
4786      */
4787     boolean mDefaultFocusHighlightEnabled = true;
4788 
4789     private CheckForLongPress mPendingCheckForLongPress;
4790     @UnsupportedAppUsage
4791     private CheckForTap mPendingCheckForTap = null;
4792     private PerformClick mPerformClick;
4793     private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
4794 
4795     private UnsetPressedState mUnsetPressedState;
4796 
4797     /**
4798      * Whether the long press's action has been invoked.  The tap's action is invoked on the
4799      * up event while a long press is invoked as soon as the long press duration is reached, so
4800      * a long press could be performed before the tap is checked, in which case the tap's action
4801      * should not be invoked.
4802      */
4803     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
4804     private boolean mHasPerformedLongPress;
4805 
4806     /**
4807      * Whether a context click button is currently pressed down. This is true when the stylus is
4808      * touching the screen and the primary button has been pressed, or if a mouse's right button is
4809      * pressed. This is false once the button is released or if the stylus has been lifted.
4810      */
4811     private boolean mInContextButtonPress;
4812 
4813     /**
4814      * Whether the next up event should be ignored for the purposes of gesture recognition. This is
4815      * true after a stylus button press has occured, when the next up event should not be recognized
4816      * as a tap.
4817      */
4818     private boolean mIgnoreNextUpEvent;
4819 
4820     /**
4821      * The minimum height of the view. We'll try our best to have the height
4822      * of this view to at least this amount.
4823      */
4824     @ViewDebug.ExportedProperty(category = "measurement")
4825     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4826     private int mMinHeight;
4827 
4828     /**
4829      * The minimum width of the view. We'll try our best to have the width
4830      * of this view to at least this amount.
4831      */
4832     @ViewDebug.ExportedProperty(category = "measurement")
4833     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4834     private int mMinWidth;
4835 
4836     /**
4837      * The delegate to handle touch events that are physically in this view
4838      * but should be handled by another view.
4839      */
4840     private TouchDelegate mTouchDelegate = null;
4841 
4842     /**
4843      * While touch exploration is in use, set to true when hovering across boundaries and
4844      * inside the touch area of the delegate at receiving {@link MotionEvent#ACTION_HOVER_ENTER}
4845      * or {@link MotionEvent#ACTION_HOVER_MOVE}. False when leaving boundaries or receiving a
4846      * {@link MotionEvent#ACTION_HOVER_EXIT}.
4847      * Note that children of view group are excluded in the touch area.
4848      * @see #dispatchTouchExplorationHoverEvent
4849      */
4850     private boolean mHoveringTouchDelegate = false;
4851 
4852     /**
4853      * Solid color to use as a background when creating the drawing cache. Enables
4854      * the cache to use 16 bit bitmaps instead of 32 bit.
4855      */
4856     private int mDrawingCacheBackgroundColor = 0;
4857 
4858     /**
4859      * Special tree observer used when mAttachInfo is null.
4860      */
4861     private ViewTreeObserver mFloatingTreeObserver;
4862 
4863     /**
4864      * Cache the touch slop from the context that created the view.
4865      */
4866     private int mTouchSlop;
4867 
4868     /**
4869      * Object that handles automatic animation of view properties.
4870      */
4871     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
4872     private ViewPropertyAnimator mAnimator = null;
4873 
4874     /**
4875      * List of registered FrameMetricsObservers.
4876      */
4877     private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
4878 
4879     /**
4880      * Flag indicating that a drag can cross window boundaries.  When
4881      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
4882      * with this flag set, all visible applications with targetSdkVersion >=
4883      * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
4884      * in the drag operation and receive the dragged content.
4885      *
4886      * <p>If this is the only flag set, then the drag recipient will only have access to text data
4887      * and intents contained in the {@link ClipData} object. Access to URIs contained in the
4888      * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p>
4889      */
4890     public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
4891 
4892     /**
4893      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
4894      * request read access to the content URI(s) contained in the {@link ClipData} object.
4895      * @see android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION
4896      */
4897     public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
4898 
4899     /**
4900      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
4901      * request write access to the content URI(s) contained in the {@link ClipData} object.
4902      * @see android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION
4903      */
4904     public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
4905 
4906     /**
4907      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
4908      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
4909      * reboots until explicitly revoked with
4910      * {@link android.content.Context#revokeUriPermission(Uri, int)} Context.revokeUriPermission}.
4911      * @see android.content.Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION
4912      */
4913     public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
4914             Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
4915 
4916     /**
4917      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
4918      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
4919      * match against the original granted URI.
4920      * @see android.content.Intent#FLAG_GRANT_PREFIX_URI_PERMISSION
4921      */
4922     public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
4923             Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
4924 
4925     /**
4926      * Flag indicating that the drag shadow will be opaque.  When
4927      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
4928      * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
4929      */
4930     public static final int DRAG_FLAG_OPAQUE = 1 << 9;
4931 
4932     /**
4933      * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
4934      */
4935     private float mVerticalScrollFactor;
4936 
4937     /**
4938      * Position of the vertical scroll bar.
4939      */
4940     @UnsupportedAppUsage
4941     private int mVerticalScrollbarPosition;
4942 
4943     /**
4944      * Position the scroll bar at the default position as determined by the system.
4945      */
4946     public static final int SCROLLBAR_POSITION_DEFAULT = 0;
4947 
4948     /**
4949      * Position the scroll bar along the left edge.
4950      */
4951     public static final int SCROLLBAR_POSITION_LEFT = 1;
4952 
4953     /**
4954      * Position the scroll bar along the right edge.
4955      */
4956     public static final int SCROLLBAR_POSITION_RIGHT = 2;
4957 
4958     /**
4959      * Indicates that the view does not have a layer.
4960      *
4961      * @see #getLayerType()
4962      * @see #setLayerType(int, android.graphics.Paint)
4963      * @see #LAYER_TYPE_SOFTWARE
4964      * @see #LAYER_TYPE_HARDWARE
4965      */
4966     public static final int LAYER_TYPE_NONE = 0;
4967 
4968     /**
4969      * <p>Indicates that the view has a software layer. A software layer is backed
4970      * by a bitmap and causes the view to be rendered using Android's software
4971      * rendering pipeline, even if hardware acceleration is enabled.</p>
4972      *
4973      * <p>Software layers have various usages:</p>
4974      * <p>When the application is not using hardware acceleration, a software layer
4975      * is useful to apply a specific color filter and/or blending mode and/or
4976      * translucency to a view and all its children.</p>
4977      * <p>When the application is using hardware acceleration, a software layer
4978      * is useful to render drawing primitives not supported by the hardware
4979      * accelerated pipeline. It can also be used to cache a complex view tree
4980      * into a texture and reduce the complexity of drawing operations. For instance,
4981      * when animating a complex view tree with a translation, a software layer can
4982      * be used to render the view tree only once.</p>
4983      * <p>Software layers should be avoided when the affected view tree updates
4984      * often. Every update will require to re-render the software layer, which can
4985      * potentially be slow (particularly when hardware acceleration is turned on
4986      * since the layer will have to be uploaded into a hardware texture after every
4987      * update.)</p>
4988      *
4989      * @see #getLayerType()
4990      * @see #setLayerType(int, android.graphics.Paint)
4991      * @see #LAYER_TYPE_NONE
4992      * @see #LAYER_TYPE_HARDWARE
4993      */
4994     public static final int LAYER_TYPE_SOFTWARE = 1;
4995 
4996     /**
4997      * <p>Indicates that the view has a hardware layer. A hardware layer is backed
4998      * by a hardware specific texture (generally Frame Buffer Objects or FBO on
4999      * OpenGL hardware) and causes the view to be rendered using Android's hardware
5000      * rendering pipeline, but only if hardware acceleration is turned on for the
5001      * view hierarchy. When hardware acceleration is turned off, hardware layers
5002      * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
5003      *
5004      * <p>A hardware layer is useful to apply a specific color filter and/or
5005      * blending mode and/or translucency to a view and all its children.</p>
5006      * <p>A hardware layer can be used to cache a complex view tree into a
5007      * texture and reduce the complexity of drawing operations. For instance,
5008      * when animating a complex view tree with a translation, a hardware layer can
5009      * be used to render the view tree only once.</p>
5010      * <p>A hardware layer can also be used to increase the rendering quality when
5011      * rotation transformations are applied on a view. It can also be used to
5012      * prevent potential clipping issues when applying 3D transforms on a view.</p>
5013      *
5014      * @see #getLayerType()
5015      * @see #setLayerType(int, android.graphics.Paint)
5016      * @see #LAYER_TYPE_NONE
5017      * @see #LAYER_TYPE_SOFTWARE
5018      */
5019     public static final int LAYER_TYPE_HARDWARE = 2;
5020 
5021     /** @hide */
5022     @IntDef(prefix = { "LAYER_TYPE_" }, value = {
5023             LAYER_TYPE_NONE,
5024             LAYER_TYPE_SOFTWARE,
5025             LAYER_TYPE_HARDWARE
5026     })
5027     @Retention(RetentionPolicy.SOURCE)
5028     public @interface LayerType {}
5029 
5030     @ViewDebug.ExportedProperty(category = "drawing", mapping = {
5031             @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
5032             @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
5033             @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
5034     })
5035     int mLayerType = LAYER_TYPE_NONE;
5036     Paint mLayerPaint;
5037 
5038     /**
5039      * Set to true when drawing cache is enabled and cannot be created.
5040      *
5041      * @hide
5042      */
5043     @UnsupportedAppUsage
5044     public boolean mCachingFailed;
5045     @UnsupportedAppUsage
5046     private Bitmap mDrawingCache;
5047     @UnsupportedAppUsage
5048     private Bitmap mUnscaledDrawingCache;
5049 
5050     /**
5051      * RenderNode holding View properties, potentially holding a DisplayList of View content.
5052      * <p>
5053      * When non-null and valid, this is expected to contain an up-to-date copy
5054      * of the View content. Its DisplayList content is cleared on temporary detach and reset on
5055      * cleanup.
5056      */
5057     @UnsupportedAppUsage
5058     final RenderNode mRenderNode;
5059 
5060     /**
5061      * Set to true when the view is sending hover accessibility events because it
5062      * is the innermost hovered view.
5063      */
5064     private boolean mSendingHoverAccessibilityEvents;
5065 
5066     /**
5067      * Delegate for injecting accessibility functionality.
5068      */
5069     @UnsupportedAppUsage
5070     AccessibilityDelegate mAccessibilityDelegate;
5071 
5072     /**
5073      * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
5074      * and add/remove objects to/from the overlay directly through the Overlay methods.
5075      */
5076     ViewOverlay mOverlay;
5077 
5078     /**
5079      * The currently active parent view for receiving delegated nested scrolling events.
5080      * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
5081      * by {@link #stopNestedScroll()} at the same point where we clear
5082      * requestDisallowInterceptTouchEvent.
5083      */
5084     private ViewParent mNestedScrollingParent;
5085 
5086     /**
5087      * Consistency verifier for debugging purposes.
5088      * @hide
5089      */
5090     protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
5091             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
5092                     new InputEventConsistencyVerifier(this, 0) : null;
5093 
5094     private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
5095 
5096     private int[] mTempNestedScrollConsumed;
5097 
5098     /**
5099      * An overlay is going to draw this View instead of being drawn as part of this
5100      * View's parent. mGhostView is the View in the Overlay that must be invalidated
5101      * when this view is invalidated.
5102      */
5103     GhostView mGhostView;
5104 
5105     /**
5106      * Holds pairs of adjacent attribute data: attribute name followed by its value.
5107      * @hide
5108      */
5109     @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
5110     public String[] mAttributes;
5111 
5112     /**
5113      * Maps a Resource id to its name.
5114      */
5115     private static SparseArray<String> mAttributeMap;
5116 
5117     /**
5118      * Queue of pending runnables. Used to postpone calls to post() until this
5119      * view is attached and has a handler.
5120      */
5121     private HandlerActionQueue mRunQueue;
5122 
5123     /**
5124      * The pointer icon when the mouse hovers on this view. The default is null.
5125      */
5126     private PointerIcon mPointerIcon;
5127 
5128     /**
5129      * @hide
5130      */
5131     @UnsupportedAppUsage
5132     String mStartActivityRequestWho;
5133 
5134     @Nullable
5135     private RoundScrollbarRenderer mRoundScrollbarRenderer;
5136 
5137     /** Used to delay visibility updates sent to the autofill manager */
5138     private Handler mVisibilityChangeForAutofillHandler;
5139 
5140     /**
5141      * Used when app developers explicitly set the {@link ContentCaptureSession} associated with the
5142      * view (through {@link #setContentCaptureSession(ContentCaptureSession)}.
5143      */
5144     @Nullable
5145     private ContentCaptureSession mContentCaptureSession;
5146 
5147     @LayoutRes
5148     private int mSourceLayoutId = ID_NULL;
5149 
5150     @Nullable
5151     private SparseIntArray mAttributeSourceResId;
5152 
5153     @Nullable
5154     private SparseArray<int[]> mAttributeResolutionStacks;
5155 
5156     @StyleRes
5157     private int mExplicitStyle;
5158 
5159     /**
5160      * Cached reference to the {@link ContentCaptureSession}, is reset on {@link #invalidate()}.
5161      */
5162     private ContentCaptureSession mCachedContentCaptureSession;
5163 
5164     /**
5165      * Simple constructor to use when creating a view from code.
5166      *
5167      * @param context The Context the view is running in, through which it can
5168      *        access the current theme, resources, etc.
5169      */
View(Context context)5170     public View(Context context) {
5171         mContext = context;
5172         mResources = context != null ? context.getResources() : null;
5173         mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | FOCUSABLE_AUTO;
5174         // Set some flags defaults
5175         mPrivateFlags2 =
5176                 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
5177                 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
5178                 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
5179                 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
5180                 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
5181                 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
5182         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
5183         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
5184         mUserPaddingStart = UNDEFINED_PADDING;
5185         mUserPaddingEnd = UNDEFINED_PADDING;
5186         mRenderNode = RenderNode.create(getClass().getName(), new ViewAnimationHostBridge(this));
5187 
5188         if (!sCompatibilityDone && context != null) {
5189             final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
5190 
5191             // Older apps may need this compatibility hack for measurement.
5192             sUseBrokenMakeMeasureSpec = targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1;
5193 
5194             // Older apps expect onMeasure() to always be called on a layout pass, regardless
5195             // of whether a layout was requested on that View.
5196             sIgnoreMeasureCache = targetSdkVersion < Build.VERSION_CODES.KITKAT;
5197 
5198             Canvas.sCompatibilityRestore = targetSdkVersion < Build.VERSION_CODES.M;
5199             Canvas.sCompatibilitySetBitmap = targetSdkVersion < Build.VERSION_CODES.O;
5200             Canvas.setCompatibilityVersion(targetSdkVersion);
5201 
5202             // In M and newer, our widgets can pass a "hint" value in the size
5203             // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
5204             // know what the expected parent size is going to be, so e.g. list items can size
5205             // themselves at 1/3 the size of their container. It breaks older apps though,
5206             // specifically apps that use some popular open source libraries.
5207             sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < Build.VERSION_CODES.M;
5208 
5209             // Old versions of the platform would give different results from
5210             // LinearLayout measurement passes using EXACTLY and non-EXACTLY
5211             // modes, so we always need to run an additional EXACTLY pass.
5212             sAlwaysRemeasureExactly = targetSdkVersion <= Build.VERSION_CODES.M;
5213 
5214             // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
5215             // On N+, we throw, but that breaks compatibility with apps that use these methods.
5216             sTextureViewIgnoresDrawableSetters = targetSdkVersion <= Build.VERSION_CODES.M;
5217 
5218             // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
5219             // in apps so we target check it to avoid breaking existing apps.
5220             sPreserveMarginParamsInLayoutParamConversion =
5221                     targetSdkVersion >= Build.VERSION_CODES.N;
5222 
5223             sCascadedDragDrop = targetSdkVersion < Build.VERSION_CODES.N;
5224 
5225             sHasFocusableExcludeAutoFocusable = targetSdkVersion < Build.VERSION_CODES.O;
5226 
5227             sAutoFocusableOffUIThreadWontNotifyParents = targetSdkVersion < Build.VERSION_CODES.O;
5228 
5229             sUseDefaultFocusHighlight = context.getResources().getBoolean(
5230                     com.android.internal.R.bool.config_useDefaultFocusHighlight);
5231 
5232             sThrowOnInvalidFloatProperties = targetSdkVersion >= Build.VERSION_CODES.P;
5233 
5234             sCanFocusZeroSized = targetSdkVersion < Build.VERSION_CODES.P;
5235 
5236             sAlwaysAssignFocus = targetSdkVersion < Build.VERSION_CODES.P;
5237 
5238             sAcceptZeroSizeDragShadow = targetSdkVersion < Build.VERSION_CODES.P;
5239 
5240             sBrokenInsetsDispatch = ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_FULL
5241                     || targetSdkVersion < Build.VERSION_CODES.Q;
5242 
5243             sBrokenWindowBackground = targetSdkVersion < Build.VERSION_CODES.Q;
5244 
5245             sCompatibilityDone = true;
5246         }
5247     }
5248 
5249     /**
5250      * Constructor that is called when inflating a view from XML. This is called
5251      * when a view is being constructed from an XML file, supplying attributes
5252      * that were specified in the XML file. This version uses a default style of
5253      * 0, so the only attribute values applied are those in the Context's Theme
5254      * and the given AttributeSet.
5255      *
5256      * <p>
5257      * The method onFinishInflate() will be called after all children have been
5258      * added.
5259      *
5260      * @param context The Context the view is running in, through which it can
5261      *        access the current theme, resources, etc.
5262      * @param attrs The attributes of the XML tag that is inflating the view.
5263      * @see #View(Context, AttributeSet, int)
5264      */
5265     public View(Context context, @Nullable AttributeSet attrs) {
5266         this(context, attrs, 0);
5267     }
5268 
5269     /**
5270      * Perform inflation from XML and apply a class-specific base style from a
5271      * theme attribute. This constructor of View allows subclasses to use their
5272      * own base style when they are inflating. For example, a Button class's
5273      * constructor would call this version of the super class constructor and
5274      * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
5275      * allows the theme's button style to modify all of the base view attributes
5276      * (in particular its background) as well as the Button class's attributes.
5277      *
5278      * @param context The Context the view is running in, through which it can
5279      *        access the current theme, resources, etc.
5280      * @param attrs The attributes of the XML tag that is inflating the view.
5281      * @param defStyleAttr An attribute in the current theme that contains a
5282      *        reference to a style resource that supplies default values for
5283      *        the view. Can be 0 to not look for defaults.
5284      * @see #View(Context, AttributeSet)
5285      */
5286     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
5287         this(context, attrs, defStyleAttr, 0);
5288     }
5289 
5290     /**
5291      * Perform inflation from XML and apply a class-specific base style from a
5292      * theme attribute or style resource. This constructor of View allows
5293      * subclasses to use their own base style when they are inflating.
5294      * <p>
5295      * When determining the final value of a particular attribute, there are
5296      * four inputs that come into play:
5297      * <ol>
5298      * <li>Any attribute values in the given AttributeSet.
5299      * <li>The style resource specified in the AttributeSet (named "style").
5300      * <li>The default style specified by <var>defStyleAttr</var>.
5301      * <li>The default style specified by <var>defStyleRes</var>.
5302      * <li>The base values in this theme.
5303      * </ol>
5304      * <p>
5305      * Each of these inputs is considered in-order, with the first listed taking
5306      * precedence over the following ones. In other words, if in the
5307      * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
5308      * , then the button's text will <em>always</em> be black, regardless of
5309      * what is specified in any of the styles.
5310      *
5311      * @param context The Context the view is running in, through which it can
5312      *        access the current theme, resources, etc.
5313      * @param attrs The attributes of the XML tag that is inflating the view.
5314      * @param defStyleAttr An attribute in the current theme that contains a
5315      *        reference to a style resource that supplies default values for
5316      *        the view. Can be 0 to not look for defaults.
5317      * @param defStyleRes A resource identifier of a style resource that
5318      *        supplies default values for the view, used only if
5319      *        defStyleAttr is 0 or can not be found in the theme. Can be 0
5320      *        to not look for defaults.
5321      * @see #View(Context, AttributeSet, int)
5322      */
5323     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
5324         this(context);
5325 
5326         mSourceLayoutId = Resources.getAttributeSetSourceResId(attrs);
5327 
5328         final TypedArray a = context.obtainStyledAttributes(
5329                 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
5330 
5331         retrieveExplicitStyle(context.getTheme(), attrs);
5332         saveAttributeDataForStyleable(context, com.android.internal.R.styleable.View, attrs, a,
5333                 defStyleAttr, defStyleRes);
5334 
5335         if (sDebugViewAttributes) {
5336             saveAttributeData(attrs, a);
5337         }
5338 
5339         Drawable background = null;
5340 
5341         int leftPadding = -1;
5342         int topPadding = -1;
5343         int rightPadding = -1;
5344         int bottomPadding = -1;
5345         int startPadding = UNDEFINED_PADDING;
5346         int endPadding = UNDEFINED_PADDING;
5347 
5348         int padding = -1;
5349         int paddingHorizontal = -1;
5350         int paddingVertical = -1;
5351 
5352         int viewFlagValues = 0;
5353         int viewFlagMasks = 0;
5354 
5355         boolean setScrollContainer = false;
5356 
5357         int x = 0;
5358         int y = 0;
5359 
5360         float tx = 0;
5361         float ty = 0;
5362         float tz = 0;
5363         float elevation = 0;
5364         float rotation = 0;
5365         float rotationX = 0;
5366         float rotationY = 0;
5367         float sx = 1f;
5368         float sy = 1f;
5369         boolean transformSet = false;
5370 
5371         int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
5372         int overScrollMode = mOverScrollMode;
5373         boolean initializeScrollbars = false;
5374         boolean initializeScrollIndicators = false;
5375 
5376         boolean startPaddingDefined = false;
5377         boolean endPaddingDefined = false;
5378         boolean leftPaddingDefined = false;
5379         boolean rightPaddingDefined = false;
5380 
5381         final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
5382 
5383         // Set default values.
5384         viewFlagValues |= FOCUSABLE_AUTO;
5385         viewFlagMasks |= FOCUSABLE_AUTO;
5386 
5387         final int N = a.getIndexCount();
5388         for (int i = 0; i < N; i++) {
5389             int attr = a.getIndex(i);
5390             switch (attr) {
5391                 case com.android.internal.R.styleable.View_background:
5392                     background = a.getDrawable(attr);
5393                     break;
5394                 case com.android.internal.R.styleable.View_padding:
5395                     padding = a.getDimensionPixelSize(attr, -1);
5396                     mUserPaddingLeftInitial = padding;
5397                     mUserPaddingRightInitial = padding;
5398                     leftPaddingDefined = true;
5399                     rightPaddingDefined = true;
5400                     break;
5401                 case com.android.internal.R.styleable.View_paddingHorizontal:
5402                     paddingHorizontal = a.getDimensionPixelSize(attr, -1);
5403                     mUserPaddingLeftInitial = paddingHorizontal;
5404                     mUserPaddingRightInitial = paddingHorizontal;
5405                     leftPaddingDefined = true;
5406                     rightPaddingDefined = true;
5407                     break;
5408                 case com.android.internal.R.styleable.View_paddingVertical:
5409                     paddingVertical = a.getDimensionPixelSize(attr, -1);
5410                     break;
5411                 case com.android.internal.R.styleable.View_paddingLeft:
5412                     leftPadding = a.getDimensionPixelSize(attr, -1);
5413                     mUserPaddingLeftInitial = leftPadding;
5414                     leftPaddingDefined = true;
5415                     break;
5416                 case com.android.internal.R.styleable.View_paddingTop:
5417                     topPadding = a.getDimensionPixelSize(attr, -1);
5418                     break;
5419                 case com.android.internal.R.styleable.View_paddingRight:
5420                     rightPadding = a.getDimensionPixelSize(attr, -1);
5421                     mUserPaddingRightInitial = rightPadding;
5422                     rightPaddingDefined = true;
5423                     break;
5424                 case com.android.internal.R.styleable.View_paddingBottom:
5425                     bottomPadding = a.getDimensionPixelSize(attr, -1);
5426                     break;
5427                 case com.android.internal.R.styleable.View_paddingStart:
5428                     startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
5429                     startPaddingDefined = (startPadding != UNDEFINED_PADDING);
5430                     break;
5431                 case com.android.internal.R.styleable.View_paddingEnd:
5432                     endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
5433                     endPaddingDefined = (endPadding != UNDEFINED_PADDING);
5434                     break;
5435                 case com.android.internal.R.styleable.View_scrollX:
5436                     x = a.getDimensionPixelOffset(attr, 0);
5437                     break;
5438                 case com.android.internal.R.styleable.View_scrollY:
5439                     y = a.getDimensionPixelOffset(attr, 0);
5440                     break;
5441                 case com.android.internal.R.styleable.View_alpha:
5442                     setAlpha(a.getFloat(attr, 1f));
5443                     break;
5444                 case com.android.internal.R.styleable.View_transformPivotX:
5445                     setPivotX(a.getDimension(attr, 0));
5446                     break;
5447                 case com.android.internal.R.styleable.View_transformPivotY:
5448                     setPivotY(a.getDimension(attr, 0));
5449                     break;
5450                 case com.android.internal.R.styleable.View_translationX:
5451                     tx = a.getDimension(attr, 0);
5452                     transformSet = true;
5453                     break;
5454                 case com.android.internal.R.styleable.View_translationY:
5455                     ty = a.getDimension(attr, 0);
5456                     transformSet = true;
5457                     break;
5458                 case com.android.internal.R.styleable.View_translationZ:
5459                     tz = a.getDimension(attr, 0);
5460                     transformSet = true;
5461                     break;
5462                 case com.android.internal.R.styleable.View_elevation:
5463                     elevation = a.getDimension(attr, 0);
5464                     transformSet = true;
5465                     break;
5466                 case com.android.internal.R.styleable.View_rotation:
5467                     rotation = a.getFloat(attr, 0);
5468                     transformSet = true;
5469                     break;
5470                 case com.android.internal.R.styleable.View_rotationX:
5471                     rotationX = a.getFloat(attr, 0);
5472                     transformSet = true;
5473                     break;
5474                 case com.android.internal.R.styleable.View_rotationY:
5475                     rotationY = a.getFloat(attr, 0);
5476                     transformSet = true;
5477                     break;
5478                 case com.android.internal.R.styleable.View_scaleX:
5479                     sx = a.getFloat(attr, 1f);
5480                     transformSet = true;
5481                     break;
5482                 case com.android.internal.R.styleable.View_scaleY:
5483                     sy = a.getFloat(attr, 1f);
5484                     transformSet = true;
5485                     break;
5486                 case com.android.internal.R.styleable.View_id:
5487                     mID = a.getResourceId(attr, NO_ID);
5488                     break;
5489                 case com.android.internal.R.styleable.View_tag:
5490                     mTag = a.getText(attr);
5491                     break;
5492                 case com.android.internal.R.styleable.View_fitsSystemWindows:
5493                     if (a.getBoolean(attr, false)) {
5494                         viewFlagValues |= FITS_SYSTEM_WINDOWS;
5495                         viewFlagMasks |= FITS_SYSTEM_WINDOWS;
5496                     }
5497                     break;
5498                 case com.android.internal.R.styleable.View_focusable:
5499                     viewFlagValues = (viewFlagValues & ~FOCUSABLE_MASK) | getFocusableAttribute(a);
5500                     if ((viewFlagValues & FOCUSABLE_AUTO) == 0) {
5501                         viewFlagMasks |= FOCUSABLE_MASK;
5502                     }
5503                     break;
5504                 case com.android.internal.R.styleable.View_focusableInTouchMode:
5505                     if (a.getBoolean(attr, false)) {
5506                         // unset auto focus since focusableInTouchMode implies explicit focusable
5507                         viewFlagValues &= ~FOCUSABLE_AUTO;
5508                         viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
5509                         viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
5510                     }
5511                     break;
5512                 case com.android.internal.R.styleable.View_clickable:
5513                     if (a.getBoolean(attr, false)) {
5514                         viewFlagValues |= CLICKABLE;
5515                         viewFlagMasks |= CLICKABLE;
5516                     }
5517                     break;
5518                 case com.android.internal.R.styleable.View_longClickable:
5519                     if (a.getBoolean(attr, false)) {
5520                         viewFlagValues |= LONG_CLICKABLE;
5521                         viewFlagMasks |= LONG_CLICKABLE;
5522                     }
5523                     break;
5524                 case com.android.internal.R.styleable.View_contextClickable:
5525                     if (a.getBoolean(attr, false)) {
5526                         viewFlagValues |= CONTEXT_CLICKABLE;
5527                         viewFlagMasks |= CONTEXT_CLICKABLE;
5528                     }
5529                     break;
5530                 case com.android.internal.R.styleable.View_saveEnabled:
5531                     if (!a.getBoolean(attr, true)) {
5532                         viewFlagValues |= SAVE_DISABLED;
5533                         viewFlagMasks |= SAVE_DISABLED_MASK;
5534                     }
5535                     break;
5536                 case com.android.internal.R.styleable.View_duplicateParentState:
5537                     if (a.getBoolean(attr, false)) {
5538                         viewFlagValues |= DUPLICATE_PARENT_STATE;
5539                         viewFlagMasks |= DUPLICATE_PARENT_STATE;
5540                     }
5541                     break;
5542                 case com.android.internal.R.styleable.View_visibility:
5543                     final int visibility = a.getInt(attr, 0);
5544                     if (visibility != 0) {
5545                         viewFlagValues |= VISIBILITY_FLAGS[visibility];
5546                         viewFlagMasks |= VISIBILITY_MASK;
5547                     }
5548                     break;
5549                 case com.android.internal.R.styleable.View_layoutDirection:
5550                     // Clear any layout direction flags (included resolved bits) already set
5551                     mPrivateFlags2 &=
5552                             ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
5553                     // Set the layout direction flags depending on the value of the attribute
5554                     final int layoutDirection = a.getInt(attr, -1);
5555                     final int value = (layoutDirection != -1) ?
5556                             LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
5557                     mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
5558                     break;
5559                 case com.android.internal.R.styleable.View_drawingCacheQuality:
5560                     final int cacheQuality = a.getInt(attr, 0);
5561                     if (cacheQuality != 0) {
5562                         viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
5563                         viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
5564                     }
5565                     break;
5566                 case com.android.internal.R.styleable.View_contentDescription:
5567                     setContentDescription(a.getString(attr));
5568                     break;
5569                 case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
5570                     setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
5571                     break;
5572                 case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
5573                     setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
5574                     break;
5575                 case com.android.internal.R.styleable.View_labelFor:
5576                     setLabelFor(a.getResourceId(attr, NO_ID));
5577                     break;
5578                 case com.android.internal.R.styleable.View_soundEffectsEnabled:
5579                     if (!a.getBoolean(attr, true)) {
5580                         viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
5581                         viewFlagMasks |= SOUND_EFFECTS_ENABLED;
5582                     }
5583                     break;
5584                 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
5585                     if (!a.getBoolean(attr, true)) {
5586                         viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
5587                         viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
5588                     }
5589                     break;
5590                 case R.styleable.View_scrollbars:
5591                     final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
5592                     if (scrollbars != SCROLLBARS_NONE) {
5593                         viewFlagValues |= scrollbars;
5594                         viewFlagMasks |= SCROLLBARS_MASK;
5595                         initializeScrollbars = true;
5596                     }
5597                     break;
5598                 //noinspection deprecation
5599                 case R.styleable.View_fadingEdge:
5600                     if (targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
5601                         // Ignore the attribute starting with ICS
5602                         break;
5603                     }
5604                     // With builds < ICS, fall through and apply fading edges
5605                 case R.styleable.View_requiresFadingEdge:
5606                     final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
5607                     if (fadingEdge != FADING_EDGE_NONE) {
5608                         viewFlagValues |= fadingEdge;
5609                         viewFlagMasks |= FADING_EDGE_MASK;
5610                         initializeFadingEdgeInternal(a);
5611                     }
5612                     break;
5613                 case R.styleable.View_scrollbarStyle:
5614                     scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
5615                     if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
5616                         viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
5617                         viewFlagMasks |= SCROLLBARS_STYLE_MASK;
5618                     }
5619                     break;
5620                 case R.styleable.View_isScrollContainer:
5621                     setScrollContainer = true;
5622                     if (a.getBoolean(attr, false)) {
5623                         setScrollContainer(true);
5624                     }
5625                     break;
5626                 case com.android.internal.R.styleable.View_keepScreenOn:
5627                     if (a.getBoolean(attr, false)) {
5628                         viewFlagValues |= KEEP_SCREEN_ON;
5629                         viewFlagMasks |= KEEP_SCREEN_ON;
5630                     }
5631                     break;
5632                 case R.styleable.View_filterTouchesWhenObscured:
5633                     if (a.getBoolean(attr, false)) {
5634                         viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
5635                         viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
5636                     }
5637                     break;
5638                 case R.styleable.View_nextFocusLeft:
5639                     mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
5640                     break;
5641                 case R.styleable.View_nextFocusRight:
5642                     mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
5643                     break;
5644                 case R.styleable.View_nextFocusUp:
5645                     mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
5646                     break;
5647                 case R.styleable.View_nextFocusDown:
5648                     mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
5649                     break;
5650                 case R.styleable.View_nextFocusForward:
5651                     mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
5652                     break;
5653                 case R.styleable.View_nextClusterForward:
5654                     mNextClusterForwardId = a.getResourceId(attr, View.NO_ID);
5655                     break;
5656                 case R.styleable.View_minWidth:
5657                     mMinWidth = a.getDimensionPixelSize(attr, 0);
5658                     break;
5659                 case R.styleable.View_minHeight:
5660                     mMinHeight = a.getDimensionPixelSize(attr, 0);
5661                     break;
5662                 case R.styleable.View_onClick:
5663                     if (context.isRestricted()) {
5664                         throw new IllegalStateException("The android:onClick attribute cannot "
5665                                 + "be used within a restricted context");
5666                     }
5667 
5668                     final String handlerName = a.getString(attr);
5669                     if (handlerName != null) {
5670                         setOnClickListener(new DeclaredOnClickListener(this, handlerName));
5671                     }
5672                     break;
5673                 case R.styleable.View_overScrollMode:
5674                     overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
5675                     break;
5676                 case R.styleable.View_verticalScrollbarPosition:
5677                     mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
5678                     break;
5679                 case R.styleable.View_layerType:
5680                     setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
5681                     break;
5682                 case R.styleable.View_textDirection:
5683                     // Clear any text direction flag already set
5684                     mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
5685                     // Set the text direction flags depending on the value of the attribute
5686                     final int textDirection = a.getInt(attr, -1);
5687                     if (textDirection != -1) {
5688                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
5689                     }
5690                     break;
5691                 case R.styleable.View_textAlignment:
5692                     // Clear any text alignment flag already set
5693                     mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
5694                     // Set the text alignment flag depending on the value of the attribute
5695                     final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
5696                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
5697                     break;
5698                 case R.styleable.View_importantForAccessibility:
5699                     setImportantForAccessibility(a.getInt(attr,
5700                             IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
5701                     break;
5702                 case R.styleable.View_accessibilityLiveRegion:
5703                     setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
5704                     break;
5705                 case R.styleable.View_transitionName:
5706                     setTransitionName(a.getString(attr));
5707                     break;
5708                 case R.styleable.View_nestedScrollingEnabled:
5709                     setNestedScrollingEnabled(a.getBoolean(attr, false));
5710                     break;
5711                 case R.styleable.View_stateListAnimator:
5712                     setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
5713                             a.getResourceId(attr, 0)));
5714                     break;
5715                 case R.styleable.View_backgroundTint:
5716                     // This will get applied later during setBackground().
5717                     if (mBackgroundTint == null) {
5718                         mBackgroundTint = new TintInfo();
5719                     }
5720                     mBackgroundTint.mTintList = a.getColorStateList(
5721                             R.styleable.View_backgroundTint);
5722                     mBackgroundTint.mHasTintList = true;
5723                     break;
5724                 case R.styleable.View_backgroundTintMode:
5725                     // This will get applied later during setBackground().
5726                     if (mBackgroundTint == null) {
5727                         mBackgroundTint = new TintInfo();
5728                     }
5729                     mBackgroundTint.mBlendMode = Drawable.parseBlendMode(a.getInt(
5730                             R.styleable.View_backgroundTintMode, -1), null);
5731                     mBackgroundTint.mHasTintMode = true;
5732                     break;
5733                 case R.styleable.View_outlineProvider:
5734                     setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
5735                             PROVIDER_BACKGROUND));
5736                     break;
5737                 case R.styleable.View_foreground:
5738                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5739                         setForeground(a.getDrawable(attr));
5740                     }
5741                     break;
5742                 case R.styleable.View_foregroundGravity:
5743                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5744                         setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
5745                     }
5746                     break;
5747                 case R.styleable.View_foregroundTintMode:
5748                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5749                         setForegroundTintBlendMode(
5750                                 Drawable.parseBlendMode(a.getInt(attr, -1),
5751                                         null));
5752                     }
5753                     break;
5754                 case R.styleable.View_foregroundTint:
5755                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5756                         setForegroundTintList(a.getColorStateList(attr));
5757                     }
5758                     break;
5759                 case R.styleable.View_foregroundInsidePadding:
5760                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5761                         if (mForegroundInfo == null) {
5762                             mForegroundInfo = new ForegroundInfo();
5763                         }
5764                         mForegroundInfo.mInsidePadding = a.getBoolean(attr,
5765                                 mForegroundInfo.mInsidePadding);
5766                     }
5767                     break;
5768                 case R.styleable.View_scrollIndicators:
5769                     final int scrollIndicators =
5770                             (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
5771                                     & SCROLL_INDICATORS_PFLAG3_MASK;
5772                     if (scrollIndicators != 0) {
5773                         mPrivateFlags3 |= scrollIndicators;
5774                         initializeScrollIndicators = true;
5775                     }
5776                     break;
5777                 case R.styleable.View_pointerIcon:
5778                     final int resourceId = a.getResourceId(attr, 0);
5779                     if (resourceId != 0) {
5780                         setPointerIcon(PointerIcon.load(
5781                                 context.getResources(), resourceId));
5782                     } else {
5783                         final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
5784                         if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
5785                             setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
5786                         }
5787                     }
5788                     break;
5789                 case R.styleable.View_forceHasOverlappingRendering:
5790                     if (a.peekValue(attr) != null) {
5791                         forceHasOverlappingRendering(a.getBoolean(attr, true));
5792                     }
5793                     break;
5794                 case R.styleable.View_tooltipText:
5795                     setTooltipText(a.getText(attr));
5796                     break;
5797                 case R.styleable.View_keyboardNavigationCluster:
5798                     if (a.peekValue(attr) != null) {
5799                         setKeyboardNavigationCluster(a.getBoolean(attr, true));
5800                     }
5801                     break;
5802                 case R.styleable.View_focusedByDefault:
5803                     if (a.peekValue(attr) != null) {
5804                         setFocusedByDefault(a.getBoolean(attr, true));
5805                     }
5806                     break;
5807                 case R.styleable.View_autofillHints:
5808                     if (a.peekValue(attr) != null) {
5809                         CharSequence[] rawHints = null;
5810                         String rawString = null;
5811 
5812                         if (a.getType(attr) == TypedValue.TYPE_REFERENCE) {
5813                             int resId = a.getResourceId(attr, 0);
5814 
5815                             try {
5816                                 rawHints = a.getTextArray(attr);
5817                             } catch (Resources.NotFoundException e) {
5818                                 rawString = getResources().getString(resId);
5819                             }
5820                         } else {
5821                             rawString = a.getString(attr);
5822                         }
5823 
5824                         if (rawHints == null) {
5825                             if (rawString == null) {
5826                                 throw new IllegalArgumentException(
5827                                         "Could not resolve autofillHints");
5828                             } else {
5829                                 rawHints = rawString.split(",");
5830                             }
5831                         }
5832 
5833                         String[] hints = new String[rawHints.length];
5834 
5835                         int numHints = rawHints.length;
5836                         for (int rawHintNum = 0; rawHintNum < numHints; rawHintNum++) {
5837                             hints[rawHintNum] = rawHints[rawHintNum].toString().trim();
5838                         }
5839                         setAutofillHints(hints);
5840                     }
5841                     break;
5842                 case R.styleable.View_importantForAutofill:
5843                     if (a.peekValue(attr) != null) {
5844                         setImportantForAutofill(a.getInt(attr, IMPORTANT_FOR_AUTOFILL_AUTO));
5845                     }
5846                     break;
5847                 case R.styleable.View_defaultFocusHighlightEnabled:
5848                     if (a.peekValue(attr) != null) {
5849                         setDefaultFocusHighlightEnabled(a.getBoolean(attr, true));
5850                     }
5851                     break;
5852                 case R.styleable.View_screenReaderFocusable:
5853                     if (a.peekValue(attr) != null) {
5854                         setScreenReaderFocusable(a.getBoolean(attr, false));
5855                     }
5856                     break;
5857                 case R.styleable.View_accessibilityPaneTitle:
5858                     if (a.peekValue(attr) != null) {
5859                         setAccessibilityPaneTitle(a.getString(attr));
5860                     }
5861                     break;
5862                 case R.styleable.View_outlineSpotShadowColor:
5863                     setOutlineSpotShadowColor(a.getColor(attr, Color.BLACK));
5864                     break;
5865                 case R.styleable.View_outlineAmbientShadowColor:
5866                     setOutlineAmbientShadowColor(a.getColor(attr, Color.BLACK));
5867                     break;
5868                 case com.android.internal.R.styleable.View_accessibilityHeading:
5869                     setAccessibilityHeading(a.getBoolean(attr, false));
5870                     break;
5871                 case R.styleable.View_forceDarkAllowed:
5872                     mRenderNode.setForceDarkAllowed(a.getBoolean(attr, true));
5873                     break;
5874             }
5875         }
5876 
5877         setOverScrollMode(overScrollMode);
5878 
5879         // Cache start/end user padding as we cannot fully resolve padding here (we don't have yet
5880         // the resolved layout direction). Those cached values will be used later during padding
5881         // resolution.
5882         mUserPaddingStart = startPadding;
5883         mUserPaddingEnd = endPadding;
5884 
5885         if (background != null) {
5886             setBackground(background);
5887         }
5888 
5889         // setBackground above will record that padding is currently provided by the background.
5890         // If we have padding specified via xml, record that here instead and use it.
5891         mLeftPaddingDefined = leftPaddingDefined;
5892         mRightPaddingDefined = rightPaddingDefined;
5893 
5894         // Valid paddingHorizontal/paddingVertical beats leftPadding, rightPadding, topPadding,
5895         // bottomPadding, and padding set by background.  Valid padding beats everything.
5896         if (padding >= 0) {
5897             leftPadding = padding;
5898             topPadding = padding;
5899             rightPadding = padding;
5900             bottomPadding = padding;
5901             mUserPaddingLeftInitial = padding;
5902             mUserPaddingRightInitial = padding;
5903         } else {
5904             if (paddingHorizontal >= 0) {
5905                 leftPadding = paddingHorizontal;
5906                 rightPadding = paddingHorizontal;
5907                 mUserPaddingLeftInitial = paddingHorizontal;
5908                 mUserPaddingRightInitial = paddingHorizontal;
5909             }
5910             if (paddingVertical >= 0) {
5911                 topPadding = paddingVertical;
5912                 bottomPadding = paddingVertical;
5913             }
5914         }
5915 
5916         if (isRtlCompatibilityMode()) {
5917             // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
5918             // left / right padding are used if defined (meaning here nothing to do). If they are not
5919             // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
5920             // start / end and resolve them as left / right (layout direction is not taken into account).
5921             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
5922             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
5923             // defined.
5924             if (!mLeftPaddingDefined && startPaddingDefined) {
5925                 leftPadding = startPadding;
5926             }
5927             mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
5928             if (!mRightPaddingDefined && endPaddingDefined) {
5929                 rightPadding = endPadding;
5930             }
5931             mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
5932         } else {
5933             // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
5934             // values defined. Otherwise, left /right values are used.
5935             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
5936             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
5937             // defined.
5938             final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
5939 
5940             if (mLeftPaddingDefined && !hasRelativePadding) {
5941                 mUserPaddingLeftInitial = leftPadding;
5942             }
5943             if (mRightPaddingDefined && !hasRelativePadding) {
5944                 mUserPaddingRightInitial = rightPadding;
5945             }
5946         }
5947 
5948         // mPaddingTop and mPaddingBottom may have been set by setBackground(Drawable) so must pass
5949         // them on if topPadding or bottomPadding are not valid.
5950         internalSetPadding(
5951                 mUserPaddingLeftInitial,
5952                 topPadding >= 0 ? topPadding : mPaddingTop,
5953                 mUserPaddingRightInitial,
5954                 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
5955 
5956         if (viewFlagMasks != 0) {
5957             setFlags(viewFlagValues, viewFlagMasks);
5958         }
5959 
5960         if (initializeScrollbars) {
5961             initializeScrollbarsInternal(a);
5962         }
5963 
5964         if (initializeScrollIndicators) {
5965             initializeScrollIndicatorsInternal();
5966         }
5967 
5968         a.recycle();
5969 
5970         // Needs to be called after mViewFlags is set
5971         if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
5972             recomputePadding();
5973         }
5974 
5975         if (x != 0 || y != 0) {
5976             scrollTo(x, y);
5977         }
5978 
5979         if (transformSet) {
5980             setTranslationX(tx);
5981             setTranslationY(ty);
5982             setTranslationZ(tz);
5983             setElevation(elevation);
5984             setRotation(rotation);
5985             setRotationX(rotationX);
5986             setRotationY(rotationY);
5987             setScaleX(sx);
5988             setScaleY(sy);
5989         }
5990 
5991         if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
5992             setScrollContainer(true);
5993         }
5994 
5995         computeOpaqueFlags();
5996     }
5997 
5998     /**
5999      * Returns the ordered list of resource ID that are considered when resolving attribute values
6000      * for this {@link View}. The list will include layout resource ID if the View is inflated from
6001      * XML. It will also include a set of explicit styles if specified in XML using
6002      * {@code style="..."}. Finally, it will include the default styles resolved from the theme.
6003      *
6004      * <p>
6005      * <b>Note:</b> this method will only return actual values if the view attribute debugging
6006      * is enabled in Android developer options.
6007      *
6008      * @param attribute Attribute resource ID for which the resolution stack should be returned.
6009      * @return ordered list of resource ID that are considered when resolving attribute values for
6010      * this {@link View}.
6011      */
6012     @NonNull
6013     public int[] getAttributeResolutionStack(@AttrRes int attribute) {
6014         if (!sDebugViewAttributes
6015                 || mAttributeResolutionStacks == null
6016                 || mAttributeResolutionStacks.get(attribute) == null) {
6017             return new int[0];
6018         }
6019         int[] attributeResolutionStack = mAttributeResolutionStacks.get(attribute);
6020         int stackSize = attributeResolutionStack.length;
6021         if (mSourceLayoutId != ID_NULL) {
6022             stackSize++;
6023         }
6024 
6025         int currentIndex = 0;
6026         int[] stack = new int[stackSize];
6027 
6028         if (mSourceLayoutId != ID_NULL) {
6029             stack[currentIndex] = mSourceLayoutId;
6030             currentIndex++;
6031         }
6032         for (int i = 0; i < attributeResolutionStack.length; i++) {
6033             stack[currentIndex] = attributeResolutionStack[i];
6034             currentIndex++;
6035         }
6036         return stack;
6037     }
6038 
6039     /**
6040      * Returns the mapping of attribute resource ID to source resource ID where the attribute value
6041      * was set. Source resource ID can either be a layout resource ID, if the value was set in XML
6042      * within the View tag, or a style resource ID, if the attribute was set in a style. The source
6043      * resource value will be one of the resource IDs from {@link #getAttributeSourceResourceMap()}.
6044      *
6045      * <p>
6046      * <b>Note:</b> this method will only return actual values if the view attribute debugging
6047      * is enabled in Android developer options.
6048      *
6049      * @return mapping of attribute resource ID to source resource ID where the attribute value
6050      * was set.
6051      */
6052     @NonNull
6053     public Map<Integer, Integer> getAttributeSourceResourceMap() {
6054         HashMap<Integer, Integer> map = new HashMap<>();
6055         if (!sDebugViewAttributes || mAttributeSourceResId == null) {
6056             return map;
6057         }
6058         for (int i = 0; i < mAttributeSourceResId.size(); i++) {
6059             map.put(mAttributeSourceResId.keyAt(i), mAttributeSourceResId.valueAt(i));
6060         }
6061         return map;
6062     }
6063 
6064     /**
6065      * Returns the resource ID for the style specified using {@code style="..."} in the
6066      * {@link AttributeSet}'s backing XML element or {@link Resources#ID_NULL} otherwise if not
6067      * specified or otherwise not applicable.
6068      * <p>
6069      * Each {@link View} can have an explicit style specified in the layout file.
6070      * This style is used first during the {@link View} attribute resolution, then if an attribute
6071      * is not defined there the resource system looks at default style and theme as fallbacks.
6072      *
6073      * <p>
6074      * <b>Note:</b> this method will only return actual values if the view attribute debugging
6075      * is enabled in Android developer options.
6076      *
6077      * @return The resource ID for the style specified using {@code style="..."} in the
6078      *      {@link AttributeSet}'s backing XML element or {@link Resources#ID_NULL} otherwise
6079      *      if not specified or otherwise not applicable.
6080      */
6081     @StyleRes
6082     public int getExplicitStyle() {
6083         if (!sDebugViewAttributes) {
6084             return ID_NULL;
6085         }
6086         return mExplicitStyle;
6087     }
6088 
6089     /**
6090      * An implementation of OnClickListener that attempts to lazily load a
6091      * named click handling method from a parent or ancestor context.
6092      */
6093     private static class DeclaredOnClickListener implements OnClickListener {
6094         private final View mHostView;
6095         private final String mMethodName;
6096 
6097         private Method mResolvedMethod;
6098         private Context mResolvedContext;
6099 
6100         public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
6101             mHostView = hostView;
6102             mMethodName = methodName;
6103         }
6104 
6105         @Override
6106         public void onClick(@NonNull View v) {
6107             if (mResolvedMethod == null) {
6108                 resolveMethod(mHostView.getContext(), mMethodName);
6109             }
6110 
6111             try {
6112                 mResolvedMethod.invoke(mResolvedContext, v);
6113             } catch (IllegalAccessException e) {
6114                 throw new IllegalStateException(
6115                         "Could not execute non-public method for android:onClick", e);
6116             } catch (InvocationTargetException e) {
6117                 throw new IllegalStateException(
6118                         "Could not execute method for android:onClick", e);
6119             }
6120         }
6121 
6122         @NonNull
6123         private void resolveMethod(@Nullable Context context, @NonNull String name) {
6124             while (context != null) {
6125                 try {
6126                     if (!context.isRestricted()) {
6127                         final Method method = context.getClass().getMethod(mMethodName, View.class);
6128                         if (method != null) {
6129                             mResolvedMethod = method;
6130                             mResolvedContext = context;
6131                             return;
6132                         }
6133                     }
6134                 } catch (NoSuchMethodException e) {
6135                     // Failed to find method, keep searching up the hierarchy.
6136                 }
6137 
6138                 if (context instanceof ContextWrapper) {
6139                     context = ((ContextWrapper) context).getBaseContext();
6140                 } else {
6141                     // Can't search up the hierarchy, null out and fail.
6142                     context = null;
6143                 }
6144             }
6145 
6146             final int id = mHostView.getId();
6147             final String idText = id == NO_ID ? "" : " with id '"
6148                     + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
6149             throw new IllegalStateException("Could not find method " + mMethodName
6150                     + "(View) in a parent or ancestor Context for android:onClick "
6151                     + "attribute defined on view " + mHostView.getClass() + idText);
6152         }
6153     }
6154 
6155     /**
6156      * Non-public constructor for use in testing
6157      */
6158     @UnsupportedAppUsage
6159     View() {
6160         mResources = null;
6161         mRenderNode = RenderNode.create(getClass().getName(), new ViewAnimationHostBridge(this));
6162     }
6163 
6164     final boolean debugDraw() {
6165         return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
6166     }
6167 
6168     private static SparseArray<String> getAttributeMap() {
6169         if (mAttributeMap == null) {
6170             mAttributeMap = new SparseArray<>();
6171         }
6172         return mAttributeMap;
6173     }
6174 
6175     private void retrieveExplicitStyle(@NonNull Resources.Theme theme,
6176             @Nullable AttributeSet attrs) {
6177         if (!sDebugViewAttributes) {
6178             return;
6179         }
6180         mExplicitStyle = theme.getExplicitStyle(attrs);
6181     }
6182 
6183     /**
6184      * Stores debugging information about attributes. This should be called in a constructor by
6185      * every custom {@link View} that uses a custom styleable. If the custom view does not call it,
6186      * then the custom attributes used by this view will not be visible in layout inspection tools.
6187      *
6188      *  @param context Context under which this view is created.
6189      * @param styleable A reference to styleable array R.styleable.Foo
6190      * @param attrs AttributeSet used to construct this view.
6191      * @param t Resolved {@link TypedArray} returned by a call to
6192      *        {@link Resources#obtainAttributes(AttributeSet, int[])}.
6193      * @param defStyleAttr Default style attribute passed into the view constructor.
6194      * @param defStyleRes Default style resource passed into the view constructor.
6195      */
6196     public final void saveAttributeDataForStyleable(@NonNull Context context,
6197             @NonNull int[] styleable, @Nullable AttributeSet attrs, @NonNull TypedArray t,
6198             int defStyleAttr, int defStyleRes) {
6199         if (!sDebugViewAttributes) {
6200             return;
6201         }
6202 
6203         int[] attributeResolutionStack = context.getTheme().getAttributeResolutionStack(
6204                 defStyleAttr, defStyleRes, mExplicitStyle);
6205 
6206         if (mAttributeResolutionStacks == null) {
6207             mAttributeResolutionStacks = new SparseArray<>();
6208         }
6209 
6210         if (mAttributeSourceResId == null) {
6211             mAttributeSourceResId = new SparseIntArray();
6212         }
6213 
6214         final int indexCount = t.getIndexCount();
6215         for (int j = 0; j < indexCount; ++j) {
6216             final int index = t.getIndex(j);
6217             mAttributeSourceResId.append(styleable[index], t.getSourceResourceId(index, 0));
6218             mAttributeResolutionStacks.append(styleable[index], attributeResolutionStack);
6219         }
6220     }
6221 
6222     private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
6223         final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
6224         final int indexCount = t.getIndexCount();
6225         final String[] attributes = new String[(attrsCount + indexCount) * 2];
6226 
6227         int i = 0;
6228 
6229         // Store raw XML attributes.
6230         for (int j = 0; j < attrsCount; ++j) {
6231             attributes[i] = attrs.getAttributeName(j);
6232             attributes[i + 1] = attrs.getAttributeValue(j);
6233             i += 2;
6234         }
6235 
6236         // Store resolved styleable attributes.
6237         final Resources res = t.getResources();
6238         final SparseArray<String> attributeMap = getAttributeMap();
6239         for (int j = 0; j < indexCount; ++j) {
6240             final int index = t.getIndex(j);
6241             if (!t.hasValueOrEmpty(index)) {
6242                 // Value is undefined. Skip it.
6243                 continue;
6244             }
6245 
6246             final int resourceId = t.getResourceId(index, 0);
6247             if (resourceId == 0) {
6248                 // Value is not a reference. Skip it.
6249                 continue;
6250             }
6251 
6252             String resourceName = attributeMap.get(resourceId);
6253             if (resourceName == null) {
6254                 try {
6255                     resourceName = res.getResourceName(resourceId);
6256                 } catch (Resources.NotFoundException e) {
6257                     resourceName = "0x" + Integer.toHexString(resourceId);
6258                 }
6259                 attributeMap.put(resourceId, resourceName);
6260             }
6261 
6262             attributes[i] = resourceName;
6263             attributes[i + 1] = t.getString(index);
6264             i += 2;
6265         }
6266 
6267         // Trim to fit contents.
6268         final String[] trimmed = new String[i];
6269         System.arraycopy(attributes, 0, trimmed, 0, i);
6270         mAttributes = trimmed;
6271     }
6272 
6273     @Override
6274     public String toString() {
6275         StringBuilder out = new StringBuilder(128);
6276         out.append(getClass().getName());
6277         out.append('{');
6278         out.append(Integer.toHexString(System.identityHashCode(this)));
6279         out.append(' ');
6280         switch (mViewFlags&VISIBILITY_MASK) {
6281             case VISIBLE: out.append('V'); break;
6282             case INVISIBLE: out.append('I'); break;
6283             case GONE: out.append('G'); break;
6284             default: out.append('.'); break;
6285         }
6286         out.append((mViewFlags & FOCUSABLE) == FOCUSABLE ? 'F' : '.');
6287         out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
6288         out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
6289         out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
6290         out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
6291         out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
6292         out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
6293         out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
6294         out.append(' ');
6295         out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
6296         out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
6297         out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
6298         if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
6299             out.append('p');
6300         } else {
6301             out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
6302         }
6303         out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
6304         out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
6305         out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
6306         out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
6307         out.append(' ');
6308         out.append(mLeft);
6309         out.append(',');
6310         out.append(mTop);
6311         out.append('-');
6312         out.append(mRight);
6313         out.append(',');
6314         out.append(mBottom);
6315         final int id = getId();
6316         if (id != NO_ID) {
6317             out.append(" #");
6318             out.append(Integer.toHexString(id));
6319             final Resources r = mResources;
6320             if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
6321                 try {
6322                     String pkgname;
6323                     switch (id&0xff000000) {
6324                         case 0x7f000000:
6325                             pkgname="app";
6326                             break;
6327                         case 0x01000000:
6328                             pkgname="android";
6329                             break;
6330                         default:
6331                             pkgname = r.getResourcePackageName(id);
6332                             break;
6333                     }
6334                     String typename = r.getResourceTypeName(id);
6335                     String entryname = r.getResourceEntryName(id);
6336                     out.append(" ");
6337                     out.append(pkgname);
6338                     out.append(":");
6339                     out.append(typename);
6340                     out.append("/");
6341                     out.append(entryname);
6342                 } catch (Resources.NotFoundException e) {
6343                 }
6344             }
6345         }
6346         if (mAutofillId != null) {
6347             out.append(" aid="); out.append(mAutofillId);
6348         }
6349         out.append("}");
6350         return out.toString();
6351     }
6352 
6353     /**
6354      * <p>
6355      * Initializes the fading edges from a given set of styled attributes. This
6356      * method should be called by subclasses that need fading edges and when an
6357      * instance of these subclasses is created programmatically rather than
6358      * being inflated from XML. This method is automatically called when the XML
6359      * is inflated.
6360      * </p>
6361      *
6362      * @param a the styled attributes set to initialize the fading edges from
6363      *
6364      * @removed
6365      */
6366     protected void initializeFadingEdge(TypedArray a) {
6367         // This method probably shouldn't have been included in the SDK to begin with.
6368         // It relies on 'a' having been initialized using an attribute filter array that is
6369         // not publicly available to the SDK. The old method has been renamed
6370         // to initializeFadingEdgeInternal and hidden for framework use only;
6371         // this one initializes using defaults to make it safe to call for apps.
6372 
6373         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
6374 
6375         initializeFadingEdgeInternal(arr);
6376 
6377         arr.recycle();
6378     }
6379 
6380     /**
6381      * <p>
6382      * Initializes the fading edges from a given set of styled attributes. This
6383      * method should be called by subclasses that need fading edges and when an
6384      * instance of these subclasses is created programmatically rather than
6385      * being inflated from XML. This method is automatically called when the XML
6386      * is inflated.
6387      * </p>
6388      *
6389      * @param a the styled attributes set to initialize the fading edges from
6390      * @hide This is the real method; the public one is shimmed to be safe to call from apps.
6391      */
6392     protected void initializeFadingEdgeInternal(TypedArray a) {
6393         initScrollCache();
6394 
6395         mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
6396                 R.styleable.View_fadingEdgeLength,
6397                 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
6398     }
6399 
6400     /**
6401      * Returns the size of the vertical faded edges used to indicate that more
6402      * content in this view is visible.
6403      *
6404      * @return The size in pixels of the vertical faded edge or 0 if vertical
6405      *         faded edges are not enabled for this view.
6406      * @attr ref android.R.styleable#View_fadingEdgeLength
6407      */
6408     public int getVerticalFadingEdgeLength() {
6409         if (isVerticalFadingEdgeEnabled()) {
6410             ScrollabilityCache cache = mScrollCache;
6411             if (cache != null) {
6412                 return cache.fadingEdgeLength;
6413             }
6414         }
6415         return 0;
6416     }
6417 
6418     /**
6419      * Set the size of the faded edge used to indicate that more content in this
6420      * view is available.  Will not change whether the fading edge is enabled; use
6421      * {@link #setVerticalFadingEdgeEnabled(boolean)} or
6422      * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
6423      * for the vertical or horizontal fading edges.
6424      *
6425      * @param length The size in pixels of the faded edge used to indicate that more
6426      *        content in this view is visible.
6427      */
6428     public void setFadingEdgeLength(int length) {
6429         initScrollCache();
6430         mScrollCache.fadingEdgeLength = length;
6431     }
6432 
6433     /**
6434      * Returns the size of the horizontal faded edges used to indicate that more
6435      * content in this view is visible.
6436      *
6437      * @return The size in pixels of the horizontal faded edge or 0 if horizontal
6438      *         faded edges are not enabled for this view.
6439      * @attr ref android.R.styleable#View_fadingEdgeLength
6440      */
6441     public int getHorizontalFadingEdgeLength() {
6442         if (isHorizontalFadingEdgeEnabled()) {
6443             ScrollabilityCache cache = mScrollCache;
6444             if (cache != null) {
6445                 return cache.fadingEdgeLength;
6446             }
6447         }
6448         return 0;
6449     }
6450 
6451     /**
6452      * Returns the width of the vertical scrollbar.
6453      *
6454      * @return The width in pixels of the vertical scrollbar or 0 if there
6455      *         is no vertical scrollbar.
6456      */
6457     public int getVerticalScrollbarWidth() {
6458         ScrollabilityCache cache = mScrollCache;
6459         if (cache != null) {
6460             ScrollBarDrawable scrollBar = cache.scrollBar;
6461             if (scrollBar != null) {
6462                 int size = scrollBar.getSize(true);
6463                 if (size <= 0) {
6464                     size = cache.scrollBarSize;
6465                 }
6466                 return size;
6467             }
6468             return 0;
6469         }
6470         return 0;
6471     }
6472 
6473     /**
6474      * Returns the height of the horizontal scrollbar.
6475      *
6476      * @return The height in pixels of the horizontal scrollbar or 0 if
6477      *         there is no horizontal scrollbar.
6478      */
6479     protected int getHorizontalScrollbarHeight() {
6480         ScrollabilityCache cache = mScrollCache;
6481         if (cache != null) {
6482             ScrollBarDrawable scrollBar = cache.scrollBar;
6483             if (scrollBar != null) {
6484                 int size = scrollBar.getSize(false);
6485                 if (size <= 0) {
6486                     size = cache.scrollBarSize;
6487                 }
6488                 return size;
6489             }
6490             return 0;
6491         }
6492         return 0;
6493     }
6494 
6495     /**
6496      * <p>
6497      * Initializes the scrollbars from a given set of styled attributes. This
6498      * method should be called by subclasses that need scrollbars and when an
6499      * instance of these subclasses is created programmatically rather than
6500      * being inflated from XML. This method is automatically called when the XML
6501      * is inflated.
6502      * </p>
6503      *
6504      * @param a the styled attributes set to initialize the scrollbars from
6505      *
6506      * @removed
6507      */
6508     protected void initializeScrollbars(TypedArray a) {
6509         // It's not safe to use this method from apps. The parameter 'a' must have been obtained
6510         // using the View filter array which is not available to the SDK. As such, internal
6511         // framework usage now uses initializeScrollbarsInternal and we grab a default
6512         // TypedArray with the right filter instead here.
6513         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
6514 
6515         initializeScrollbarsInternal(arr);
6516 
6517         // We ignored the method parameter. Recycle the one we actually did use.
6518         arr.recycle();
6519     }
6520 
6521     private void initializeScrollBarDrawable() {
6522         initScrollCache();
6523 
6524         if (mScrollCache.scrollBar == null) {
6525             mScrollCache.scrollBar = new ScrollBarDrawable();
6526             mScrollCache.scrollBar.setState(getDrawableState());
6527             mScrollCache.scrollBar.setCallback(this);
6528         }
6529     }
6530 
6531     /**
6532      * <p>
6533      * Initializes the scrollbars from a given set of styled attributes. This
6534      * method should be called by subclasses that need scrollbars and when an
6535      * instance of these subclasses is created programmatically rather than
6536      * being inflated from XML. This method is automatically called when the XML
6537      * is inflated.
6538      * </p>
6539      *
6540      * @param a the styled attributes set to initialize the scrollbars from
6541      * @hide
6542      */
6543     @UnsupportedAppUsage
6544     protected void initializeScrollbarsInternal(TypedArray a) {
6545         initScrollCache();
6546 
6547         final ScrollabilityCache scrollabilityCache = mScrollCache;
6548 
6549         if (scrollabilityCache.scrollBar == null) {
6550             scrollabilityCache.scrollBar = new ScrollBarDrawable();
6551             scrollabilityCache.scrollBar.setState(getDrawableState());
6552             scrollabilityCache.scrollBar.setCallback(this);
6553         }
6554 
6555         final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
6556 
6557         if (!fadeScrollbars) {
6558             scrollabilityCache.state = ScrollabilityCache.ON;
6559         }
6560         scrollabilityCache.fadeScrollBars = fadeScrollbars;
6561 
6562 
6563         scrollabilityCache.scrollBarFadeDuration = a.getInt(
6564                 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
6565                         .getScrollBarFadeDuration());
6566         scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
6567                 R.styleable.View_scrollbarDefaultDelayBeforeFade,
6568                 ViewConfiguration.getScrollDefaultDelay());
6569 
6570 
6571         scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
6572                 com.android.internal.R.styleable.View_scrollbarSize,
6573                 ViewConfiguration.get(mContext).getScaledScrollBarSize());
6574 
6575         Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
6576         scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
6577 
6578         Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
6579         if (thumb != null) {
6580             scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
6581         }
6582 
6583         boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
6584                 false);
6585         if (alwaysDraw) {
6586             scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
6587         }
6588 
6589         track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
6590         scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
6591 
6592         thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
6593         if (thumb != null) {
6594             scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
6595         }
6596 
6597         alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
6598                 false);
6599         if (alwaysDraw) {
6600             scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
6601         }
6602 
6603         // Apply layout direction to the new Drawables if needed
6604         final int layoutDirection = getLayoutDirection();
6605         if (track != null) {
6606             track.setLayoutDirection(layoutDirection);
6607         }
6608         if (thumb != null) {
6609             thumb.setLayoutDirection(layoutDirection);
6610         }
6611 
6612         // Re-apply user/background padding so that scrollbar(s) get added
6613         resolvePadding();
6614     }
6615 
6616     /**
6617      * Defines the vertical scrollbar thumb drawable
6618      * @attr ref android.R.styleable#View_scrollbarThumbVertical
6619      *
6620      * @see #awakenScrollBars(int)
6621      * @see #isVerticalScrollBarEnabled()
6622      * @see #setVerticalScrollBarEnabled(boolean)
6623      */
6624     public void setVerticalScrollbarThumbDrawable(@Nullable Drawable drawable) {
6625         initializeScrollBarDrawable();
6626         mScrollCache.scrollBar.setVerticalThumbDrawable(drawable);
6627     }
6628 
6629     /**
6630      * Defines the vertical scrollbar track drawable
6631      * @attr ref android.R.styleable#View_scrollbarTrackVertical
6632      *
6633      * @see #awakenScrollBars(int)
6634      * @see #isVerticalScrollBarEnabled()
6635      * @see #setVerticalScrollBarEnabled(boolean)
6636      */
6637     public void setVerticalScrollbarTrackDrawable(@Nullable Drawable drawable) {
6638         initializeScrollBarDrawable();
6639         mScrollCache.scrollBar.setVerticalTrackDrawable(drawable);
6640     }
6641 
6642     /**
6643      * Defines the horizontal thumb drawable
6644      * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
6645      *
6646      * @see #awakenScrollBars(int)
6647      * @see #isHorizontalScrollBarEnabled()
6648      * @see #setHorizontalScrollBarEnabled(boolean)
6649      */
6650     public void setHorizontalScrollbarThumbDrawable(@Nullable Drawable drawable) {
6651         initializeScrollBarDrawable();
6652         mScrollCache.scrollBar.setHorizontalThumbDrawable(drawable);
6653     }
6654 
6655     /**
6656      * Defines the horizontal track drawable
6657      * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
6658      *
6659      * @see #awakenScrollBars(int)
6660      * @see #isHorizontalScrollBarEnabled()
6661      * @see #setHorizontalScrollBarEnabled(boolean)
6662      */
6663     public void setHorizontalScrollbarTrackDrawable(@Nullable Drawable drawable) {
6664         initializeScrollBarDrawable();
6665         mScrollCache.scrollBar.setHorizontalTrackDrawable(drawable);
6666     }
6667 
6668     /**
6669      * Returns the currently configured Drawable for the thumb of the vertical scroll bar if it
6670      * exists, null otherwise.
6671      *
6672      * @see #awakenScrollBars(int)
6673      * @see #isVerticalScrollBarEnabled()
6674      * @see #setVerticalScrollBarEnabled(boolean)
6675      */
6676     public @Nullable Drawable getVerticalScrollbarThumbDrawable() {
6677         return mScrollCache != null ? mScrollCache.scrollBar.getVerticalThumbDrawable() : null;
6678     }
6679 
6680     /**
6681      * Returns the currently configured Drawable for the track of the vertical scroll bar if it
6682      * exists, null otherwise.
6683      *
6684      * @see #awakenScrollBars(int)
6685      * @see #isVerticalScrollBarEnabled()
6686      * @see #setVerticalScrollBarEnabled(boolean)
6687      */
6688     public @Nullable Drawable getVerticalScrollbarTrackDrawable() {
6689         return mScrollCache != null ? mScrollCache.scrollBar.getVerticalTrackDrawable() : null;
6690     }
6691 
6692     /**
6693      * Returns the currently configured Drawable for the thumb of the horizontal scroll bar if it
6694      * exists, null otherwise.
6695      *
6696      * @see #awakenScrollBars(int)
6697      * @see #isHorizontalScrollBarEnabled()
6698      * @see #setHorizontalScrollBarEnabled(boolean)
6699      */
6700     public @Nullable Drawable getHorizontalScrollbarThumbDrawable() {
6701         return mScrollCache != null ? mScrollCache.scrollBar.getHorizontalThumbDrawable() : null;
6702     }
6703 
6704     /**
6705      * Returns the currently configured Drawable for the track of the horizontal scroll bar if it
6706      * exists, null otherwise.
6707      *
6708      * @see #awakenScrollBars(int)
6709      * @see #isHorizontalScrollBarEnabled()
6710      * @see #setHorizontalScrollBarEnabled(boolean)
6711      */
6712     public @Nullable Drawable getHorizontalScrollbarTrackDrawable() {
6713         return mScrollCache != null ? mScrollCache.scrollBar.getHorizontalTrackDrawable() : null;
6714     }
6715 
6716     private void initializeScrollIndicatorsInternal() {
6717         // Some day maybe we'll break this into top/left/start/etc. and let the
6718         // client control it. Until then, you can have any scroll indicator you
6719         // want as long as it's a 1dp foreground-colored rectangle.
6720         if (mScrollIndicatorDrawable == null) {
6721             mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
6722         }
6723     }
6724 
6725     /**
6726      * <p>
6727      * Initalizes the scrollability cache if necessary.
6728      * </p>
6729      */
6730     private void initScrollCache() {
6731         if (mScrollCache == null) {
6732             mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
6733         }
6734     }
6735 
6736     @UnsupportedAppUsage
6737     private ScrollabilityCache getScrollCache() {
6738         initScrollCache();
6739         return mScrollCache;
6740     }
6741 
6742     /**
6743      * Set the position of the vertical scroll bar. Should be one of
6744      * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
6745      * {@link #SCROLLBAR_POSITION_RIGHT}.
6746      *
6747      * @param position Where the vertical scroll bar should be positioned.
6748      */
6749     public void setVerticalScrollbarPosition(int position) {
6750         if (mVerticalScrollbarPosition != position) {
6751             mVerticalScrollbarPosition = position;
6752             computeOpaqueFlags();
6753             resolvePadding();
6754         }
6755     }
6756 
6757     /**
6758      * @return The position where the vertical scroll bar will show, if applicable.
6759      * @see #setVerticalScrollbarPosition(int)
6760      */
6761     public int getVerticalScrollbarPosition() {
6762         return mVerticalScrollbarPosition;
6763     }
6764 
6765     boolean isOnScrollbar(float x, float y) {
6766         if (mScrollCache == null) {
6767             return false;
6768         }
6769         x += getScrollX();
6770         y += getScrollY();
6771         final boolean canScrollVertically =
6772                 computeVerticalScrollRange() > computeVerticalScrollExtent();
6773         if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden() && canScrollVertically) {
6774             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
6775             getVerticalScrollBarBounds(null, touchBounds);
6776             if (touchBounds.contains((int) x, (int) y)) {
6777                 return true;
6778             }
6779         }
6780         final boolean canScrollHorizontally =
6781                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
6782         if (isHorizontalScrollBarEnabled() && canScrollHorizontally) {
6783             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
6784             getHorizontalScrollBarBounds(null, touchBounds);
6785             if (touchBounds.contains((int) x, (int) y)) {
6786                 return true;
6787             }
6788         }
6789         return false;
6790     }
6791 
6792     @UnsupportedAppUsage
6793     boolean isOnScrollbarThumb(float x, float y) {
6794         return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
6795     }
6796 
6797     private boolean isOnVerticalScrollbarThumb(float x, float y) {
6798         if (mScrollCache == null || !isVerticalScrollBarEnabled() || isVerticalScrollBarHidden()) {
6799             return false;
6800         }
6801         final int range = computeVerticalScrollRange();
6802         final int extent = computeVerticalScrollExtent();
6803         if (range > extent) {
6804             x += getScrollX();
6805             y += getScrollY();
6806             final Rect bounds = mScrollCache.mScrollBarBounds;
6807             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
6808             getVerticalScrollBarBounds(bounds, touchBounds);
6809             final int offset = computeVerticalScrollOffset();
6810             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
6811                     extent, range);
6812             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
6813                     extent, range, offset);
6814             final int thumbTop = bounds.top + thumbOffset;
6815             final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
6816             if (x >= touchBounds.left && x <= touchBounds.right
6817                     && y >= thumbTop - adjust && y <= thumbTop + thumbLength + adjust) {
6818                 return true;
6819             }
6820         }
6821         return false;
6822     }
6823 
6824     private boolean isOnHorizontalScrollbarThumb(float x, float y) {
6825         if (mScrollCache == null || !isHorizontalScrollBarEnabled()) {
6826             return false;
6827         }
6828         final int range = computeHorizontalScrollRange();
6829         final int extent = computeHorizontalScrollExtent();
6830         if (range > extent) {
6831             x += getScrollX();
6832             y += getScrollY();
6833             final Rect bounds = mScrollCache.mScrollBarBounds;
6834             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
6835             getHorizontalScrollBarBounds(bounds, touchBounds);
6836             final int offset = computeHorizontalScrollOffset();
6837 
6838             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
6839                     extent, range);
6840             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
6841                     extent, range, offset);
6842             final int thumbLeft = bounds.left + thumbOffset;
6843             final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
6844             if (x >= thumbLeft - adjust && x <= thumbLeft + thumbLength + adjust
6845                     && y >= touchBounds.top && y <= touchBounds.bottom) {
6846                 return true;
6847             }
6848         }
6849         return false;
6850     }
6851 
6852     @UnsupportedAppUsage
6853     boolean isDraggingScrollBar() {
6854         return mScrollCache != null
6855                 && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
6856     }
6857 
6858     /**
6859      * Sets the state of all scroll indicators.
6860      * <p>
6861      * See {@link #setScrollIndicators(int, int)} for usage information.
6862      *
6863      * @param indicators a bitmask of indicators that should be enabled, or
6864      *                   {@code 0} to disable all indicators
6865      * @see #setScrollIndicators(int, int)
6866      * @see #getScrollIndicators()
6867      * @attr ref android.R.styleable#View_scrollIndicators
6868      */
6869     public void setScrollIndicators(@ScrollIndicators int indicators) {
6870         setScrollIndicators(indicators,
6871                 SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
6872     }
6873 
6874     /**
6875      * Sets the state of the scroll indicators specified by the mask. To change
6876      * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
6877      * <p>
6878      * When a scroll indicator is enabled, it will be displayed if the view
6879      * can scroll in the direction of the indicator.
6880      * <p>
6881      * Multiple indicator types may be enabled or disabled by passing the
6882      * logical OR of the desired types. If multiple types are specified, they
6883      * will all be set to the same enabled state.
6884      * <p>
6885      * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
6886      *
6887      * @param indicators the indicator direction, or the logical OR of multiple
6888      *             indicator directions. One or more of:
6889      *             <ul>
6890      *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
6891      *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
6892      *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
6893      *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
6894      *               <li>{@link #SCROLL_INDICATOR_START}</li>
6895      *               <li>{@link #SCROLL_INDICATOR_END}</li>
6896      *             </ul>
6897      * @see #setScrollIndicators(int)
6898      * @see #getScrollIndicators()
6899      * @attr ref android.R.styleable#View_scrollIndicators
6900      */
6901     public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
6902         // Shift and sanitize mask.
6903         mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
6904         mask &= SCROLL_INDICATORS_PFLAG3_MASK;
6905 
6906         // Shift and mask indicators.
6907         indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
6908         indicators &= mask;
6909 
6910         // Merge with non-masked flags.
6911         final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
6912 
6913         if (mPrivateFlags3 != updatedFlags) {
6914             mPrivateFlags3 = updatedFlags;
6915 
6916             if (indicators != 0) {
6917                 initializeScrollIndicatorsInternal();
6918             }
6919             invalidate();
6920         }
6921     }
6922 
6923     /**
6924      * Returns a bitmask representing the enabled scroll indicators.
6925      * <p>
6926      * For example, if the top and left scroll indicators are enabled and all
6927      * other indicators are disabled, the return value will be
6928      * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
6929      * <p>
6930      * To check whether the bottom scroll indicator is enabled, use the value
6931      * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
6932      *
6933      * @return a bitmask representing the enabled scroll indicators
6934      */
6935     @InspectableProperty(flagMapping = {
6936             @FlagEntry(target = SCROLL_INDICATORS_NONE, mask = 0xffff_ffff, name = "none"),
6937             @FlagEntry(target = SCROLL_INDICATOR_TOP, name = "top"),
6938             @FlagEntry(target = SCROLL_INDICATOR_BOTTOM, name = "bottom"),
6939             @FlagEntry(target = SCROLL_INDICATOR_LEFT, name = "left"),
6940             @FlagEntry(target = SCROLL_INDICATOR_RIGHT, name = "right"),
6941             @FlagEntry(target = SCROLL_INDICATOR_START, name = "start"),
6942             @FlagEntry(target = SCROLL_INDICATOR_END, name = "end")
6943     })
6944     @ScrollIndicators
6945     public int getScrollIndicators() {
6946         return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
6947                 >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
6948     }
6949 
6950     @UnsupportedAppUsage
6951     ListenerInfo getListenerInfo() {
6952         if (mListenerInfo != null) {
6953             return mListenerInfo;
6954         }
6955         mListenerInfo = new ListenerInfo();
6956         return mListenerInfo;
6957     }
6958 
6959     /**
6960      * Register a callback to be invoked when the scroll X or Y positions of
6961      * this view change.
6962      * <p>
6963      * <b>Note:</b> Some views handle scrolling independently from View and may
6964      * have their own separate listeners for scroll-type events. For example,
6965      * {@link android.widget.ListView ListView} allows clients to register an
6966      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
6967      * to listen for changes in list scroll position.
6968      *
6969      * @param l The listener to notify when the scroll X or Y position changes.
6970      * @see android.view.View#getScrollX()
6971      * @see android.view.View#getScrollY()
6972      */
6973     public void setOnScrollChangeListener(OnScrollChangeListener l) {
6974         getListenerInfo().mOnScrollChangeListener = l;
6975     }
6976 
6977     /**
6978      * Register a callback to be invoked when focus of this view changed.
6979      *
6980      * @param l The callback that will run.
6981      */
6982     public void setOnFocusChangeListener(OnFocusChangeListener l) {
6983         getListenerInfo().mOnFocusChangeListener = l;
6984     }
6985 
6986     /**
6987      * Add a listener that will be called when the bounds of the view change due to
6988      * layout processing.
6989      *
6990      * @param listener The listener that will be called when layout bounds change.
6991      */
6992     public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
6993         ListenerInfo li = getListenerInfo();
6994         if (li.mOnLayoutChangeListeners == null) {
6995             li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
6996         }
6997         if (!li.mOnLayoutChangeListeners.contains(listener)) {
6998             li.mOnLayoutChangeListeners.add(listener);
6999         }
7000     }
7001 
7002     /**
7003      * Remove a listener for layout changes.
7004      *
7005      * @param listener The listener for layout bounds change.
7006      */
7007     public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
7008         ListenerInfo li = mListenerInfo;
7009         if (li == null || li.mOnLayoutChangeListeners == null) {
7010             return;
7011         }
7012         li.mOnLayoutChangeListeners.remove(listener);
7013     }
7014 
7015     /**
7016      * Add a listener for attach state changes.
7017      *
7018      * This listener will be called whenever this view is attached or detached
7019      * from a window. Remove the listener using
7020      * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
7021      *
7022      * @param listener Listener to attach
7023      * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
7024      */
7025     public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
7026         ListenerInfo li = getListenerInfo();
7027         if (li.mOnAttachStateChangeListeners == null) {
7028             li.mOnAttachStateChangeListeners
7029                     = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
7030         }
7031         li.mOnAttachStateChangeListeners.add(listener);
7032     }
7033 
7034     /**
7035      * Remove a listener for attach state changes. The listener will receive no further
7036      * notification of window attach/detach events.
7037      *
7038      * @param listener Listener to remove
7039      * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
7040      */
7041     public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
7042         ListenerInfo li = mListenerInfo;
7043         if (li == null || li.mOnAttachStateChangeListeners == null) {
7044             return;
7045         }
7046         li.mOnAttachStateChangeListeners.remove(listener);
7047     }
7048 
7049     /**
7050      * Returns the focus-change callback registered for this view.
7051      *
7052      * @return The callback, or null if one is not registered.
7053      */
7054     public OnFocusChangeListener getOnFocusChangeListener() {
7055         ListenerInfo li = mListenerInfo;
7056         return li != null ? li.mOnFocusChangeListener : null;
7057     }
7058 
7059     /**
7060      * Register a callback to be invoked when this view is clicked. If this view is not
7061      * clickable, it becomes clickable.
7062      *
7063      * @param l The callback that will run
7064      *
7065      * @see #setClickable(boolean)
7066      */
7067     public void setOnClickListener(@Nullable OnClickListener l) {
7068         if (!isClickable()) {
7069             setClickable(true);
7070         }
7071         getListenerInfo().mOnClickListener = l;
7072     }
7073 
7074     /**
7075      * Return whether this view has an attached OnClickListener.  Returns
7076      * true if there is a listener, false if there is none.
7077      */
7078     public boolean hasOnClickListeners() {
7079         ListenerInfo li = mListenerInfo;
7080         return (li != null && li.mOnClickListener != null);
7081     }
7082 
7083     /**
7084      * Register a callback to be invoked when this view is clicked and held. If this view is not
7085      * long clickable, it becomes long clickable.
7086      *
7087      * @param l The callback that will run
7088      *
7089      * @see #setLongClickable(boolean)
7090      */
7091     public void setOnLongClickListener(@Nullable OnLongClickListener l) {
7092         if (!isLongClickable()) {
7093             setLongClickable(true);
7094         }
7095         getListenerInfo().mOnLongClickListener = l;
7096     }
7097 
7098     /**
7099      * Register a callback to be invoked when this view is context clicked. If the view is not
7100      * context clickable, it becomes context clickable.
7101      *
7102      * @param l The callback that will run
7103      * @see #setContextClickable(boolean)
7104      */
7105     public void setOnContextClickListener(@Nullable OnContextClickListener l) {
7106         if (!isContextClickable()) {
7107             setContextClickable(true);
7108         }
7109         getListenerInfo().mOnContextClickListener = l;
7110     }
7111 
7112     /**
7113      * Register a callback to be invoked when the context menu for this view is
7114      * being built. If this view is not long clickable, it becomes long clickable.
7115      *
7116      * @param l The callback that will run
7117      *
7118      */
7119     public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
7120         if (!isLongClickable()) {
7121             setLongClickable(true);
7122         }
7123         getListenerInfo().mOnCreateContextMenuListener = l;
7124     }
7125 
7126     /**
7127      * Set an observer to collect stats for each frame rendered for this view.
7128      *
7129      * @hide
7130      */
7131     public void addFrameMetricsListener(Window window,
7132             Window.OnFrameMetricsAvailableListener listener,
7133             Handler handler) {
7134         if (mAttachInfo != null) {
7135             if (mAttachInfo.mThreadedRenderer != null) {
7136                 if (mFrameMetricsObservers == null) {
7137                     mFrameMetricsObservers = new ArrayList<>();
7138                 }
7139 
7140                 FrameMetricsObserver fmo = new FrameMetricsObserver(window,
7141                         handler.getLooper(), listener);
7142                 mFrameMetricsObservers.add(fmo);
7143                 mAttachInfo.mThreadedRenderer.addFrameMetricsObserver(fmo);
7144             } else {
7145                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
7146             }
7147         } else {
7148             if (mFrameMetricsObservers == null) {
7149                 mFrameMetricsObservers = new ArrayList<>();
7150             }
7151 
7152             FrameMetricsObserver fmo = new FrameMetricsObserver(window,
7153                     handler.getLooper(), listener);
7154             mFrameMetricsObservers.add(fmo);
7155         }
7156     }
7157 
7158     /**
7159      * Remove observer configured to collect frame stats for this view.
7160      *
7161      * @hide
7162      */
7163     public void removeFrameMetricsListener(
7164             Window.OnFrameMetricsAvailableListener listener) {
7165         ThreadedRenderer renderer = getThreadedRenderer();
7166         FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
7167         if (fmo == null) {
7168             throw new IllegalArgumentException(
7169                     "attempt to remove OnFrameMetricsAvailableListener that was never added");
7170         }
7171 
7172         if (mFrameMetricsObservers != null) {
7173             mFrameMetricsObservers.remove(fmo);
7174             if (renderer != null) {
7175                 renderer.removeFrameMetricsObserver(fmo);
7176             }
7177         }
7178     }
7179 
7180     private void registerPendingFrameMetricsObservers() {
7181         if (mFrameMetricsObservers != null) {
7182             ThreadedRenderer renderer = getThreadedRenderer();
7183             if (renderer != null) {
7184                 for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
7185                     renderer.addFrameMetricsObserver(fmo);
7186                 }
7187             } else {
7188                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
7189             }
7190         }
7191     }
7192 
7193     private FrameMetricsObserver findFrameMetricsObserver(
7194             Window.OnFrameMetricsAvailableListener listener) {
7195         if (mFrameMetricsObservers != null) {
7196             for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
7197                 FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
7198                 if (observer.mListener == listener) {
7199                     return observer;
7200                 }
7201             }
7202         }
7203 
7204         return null;
7205     }
7206 
7207     /** @hide */
7208     public void setNotifyAutofillManagerOnClick(boolean notify) {
7209         if (notify) {
7210             mPrivateFlags |= PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
7211         } else {
7212             mPrivateFlags &= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
7213         }
7214     }
7215 
7216     private void notifyAutofillManagerOnClick() {
7217         if ((mPrivateFlags & PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK) != 0) {
7218             try {
7219                 getAutofillManager().notifyViewClicked(this);
7220             } finally {
7221                 // Set it to already called so it's not called twice when called by
7222                 // performClickInternal()
7223                 mPrivateFlags &= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
7224             }
7225         }
7226     }
7227 
7228     /**
7229      * Entry point for {@link #performClick()} - other methods on View should call it instead of
7230      * {@code performClick()} directly to make sure the autofill manager is notified when
7231      * necessary (as subclasses could extend {@code performClick()} without calling the parent's
7232      * method).
7233      */
7234     private boolean performClickInternal() {
7235         // Must notify autofill manager before performing the click actions to avoid scenarios where
7236         // the app has a click listener that changes the state of views the autofill service might
7237         // be interested on.
7238         notifyAutofillManagerOnClick();
7239 
7240         return performClick();
7241     }
7242 
7243     /**
7244      * Call this view's OnClickListener, if it is defined.  Performs all normal
7245      * actions associated with clicking: reporting accessibility event, playing
7246      * a sound, etc.
7247      *
7248      * @return True there was an assigned OnClickListener that was called, false
7249      *         otherwise is returned.
7250      */
7251     // NOTE: other methods on View should not call this method directly, but performClickInternal()
7252     // instead, to guarantee that the autofill manager is notified when necessary (as subclasses
7253     // could extend this method without calling super.performClick()).
7254     public boolean performClick() {
7255         // We still need to call this method to handle the cases where performClick() was called
7256         // externally, instead of through performClickInternal()
7257         notifyAutofillManagerOnClick();
7258 
7259         final boolean result;
7260         final ListenerInfo li = mListenerInfo;
7261         if (li != null && li.mOnClickListener != null) {
7262             playSoundEffect(SoundEffectConstants.CLICK);
7263             li.mOnClickListener.onClick(this);
7264             result = true;
7265         } else {
7266             result = false;
7267         }
7268 
7269         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
7270 
7271         notifyEnterOrExitForAutoFillIfNeeded(true);
7272 
7273         return result;
7274     }
7275 
7276     /**
7277      * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
7278      * this only calls the listener, and does not do any associated clicking
7279      * actions like reporting an accessibility event.
7280      *
7281      * @return True there was an assigned OnClickListener that was called, false
7282      *         otherwise is returned.
7283      */
7284     public boolean callOnClick() {
7285         ListenerInfo li = mListenerInfo;
7286         if (li != null && li.mOnClickListener != null) {
7287             li.mOnClickListener.onClick(this);
7288             return true;
7289         }
7290         return false;
7291     }
7292 
7293     /**
7294      * Calls this view's OnLongClickListener, if it is defined. Invokes the
7295      * context menu if the OnLongClickListener did not consume the event.
7296      *
7297      * @return {@code true} if one of the above receivers consumed the event,
7298      *         {@code false} otherwise
7299      */
7300     public boolean performLongClick() {
7301         return performLongClickInternal(mLongClickX, mLongClickY);
7302     }
7303 
7304     /**
7305      * Calls this view's OnLongClickListener, if it is defined. Invokes the
7306      * context menu if the OnLongClickListener did not consume the event,
7307      * anchoring it to an (x,y) coordinate.
7308      *
7309      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
7310      *          to disable anchoring
7311      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
7312      *          to disable anchoring
7313      * @return {@code true} if one of the above receivers consumed the event,
7314      *         {@code false} otherwise
7315      */
7316     public boolean performLongClick(float x, float y) {
7317         mLongClickX = x;
7318         mLongClickY = y;
7319         final boolean handled = performLongClick();
7320         mLongClickX = Float.NaN;
7321         mLongClickY = Float.NaN;
7322         return handled;
7323     }
7324 
7325     /**
7326      * Calls this view's OnLongClickListener, if it is defined. Invokes the
7327      * context menu if the OnLongClickListener did not consume the event,
7328      * optionally anchoring it to an (x,y) coordinate.
7329      *
7330      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
7331      *          to disable anchoring
7332      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
7333      *          to disable anchoring
7334      * @return {@code true} if one of the above receivers consumed the event,
7335      *         {@code false} otherwise
7336      */
7337     private boolean performLongClickInternal(float x, float y) {
7338         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
7339 
7340         boolean handled = false;
7341         final ListenerInfo li = mListenerInfo;
7342         if (li != null && li.mOnLongClickListener != null) {
7343             handled = li.mOnLongClickListener.onLongClick(View.this);
7344         }
7345         if (!handled) {
7346             final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
7347             handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
7348         }
7349         if ((mViewFlags & TOOLTIP) == TOOLTIP) {
7350             if (!handled) {
7351                 handled = showLongClickTooltip((int) x, (int) y);
7352             }
7353         }
7354         if (handled) {
7355             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
7356         }
7357         return handled;
7358     }
7359 
7360     /**
7361      * Call this view's OnContextClickListener, if it is defined.
7362      *
7363      * @param x the x coordinate of the context click
7364      * @param y the y coordinate of the context click
7365      * @return True if there was an assigned OnContextClickListener that consumed the event, false
7366      *         otherwise.
7367      */
7368     public boolean performContextClick(float x, float y) {
7369         return performContextClick();
7370     }
7371 
7372     /**
7373      * Call this view's OnContextClickListener, if it is defined.
7374      *
7375      * @return True if there was an assigned OnContextClickListener that consumed the event, false
7376      *         otherwise.
7377      */
7378     public boolean performContextClick() {
7379         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
7380 
7381         boolean handled = false;
7382         ListenerInfo li = mListenerInfo;
7383         if (li != null && li.mOnContextClickListener != null) {
7384             handled = li.mOnContextClickListener.onContextClick(View.this);
7385         }
7386         if (handled) {
7387             performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
7388         }
7389         return handled;
7390     }
7391 
7392     /**
7393      * Performs button-related actions during a touch down event.
7394      *
7395      * @param event The event.
7396      * @return True if the down was consumed.
7397      *
7398      * @hide
7399      */
7400     protected boolean performButtonActionOnTouchDown(MotionEvent event) {
7401         if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
7402             (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
7403             showContextMenu(event.getX(), event.getY());
7404             mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
7405             return true;
7406         }
7407         return false;
7408     }
7409 
7410     /**
7411      * Shows the context menu for this view.
7412      *
7413      * @return {@code true} if the context menu was shown, {@code false}
7414      *         otherwise
7415      * @see #showContextMenu(float, float)
7416      */
7417     public boolean showContextMenu() {
7418         return getParent().showContextMenuForChild(this);
7419     }
7420 
7421     /**
7422      * Shows the context menu for this view anchored to the specified
7423      * view-relative coordinate.
7424      *
7425      * @param x the X coordinate in pixels relative to the view to which the
7426      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
7427      * @param y the Y coordinate in pixels relative to the view to which the
7428      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
7429      * @return {@code true} if the context menu was shown, {@code false}
7430      *         otherwise
7431      */
7432     public boolean showContextMenu(float x, float y) {
7433         return getParent().showContextMenuForChild(this, x, y);
7434     }
7435 
7436     /**
7437      * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
7438      *
7439      * @param callback Callback that will control the lifecycle of the action mode
7440      * @return The new action mode if it is started, null otherwise
7441      *
7442      * @see ActionMode
7443      * @see #startActionMode(android.view.ActionMode.Callback, int)
7444      */
7445     public ActionMode startActionMode(ActionMode.Callback callback) {
7446         return startActionMode(callback, ActionMode.TYPE_PRIMARY);
7447     }
7448 
7449     /**
7450      * Start an action mode with the given type.
7451      *
7452      * @param callback Callback that will control the lifecycle of the action mode
7453      * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
7454      * @return The new action mode if it is started, null otherwise
7455      *
7456      * @see ActionMode
7457      */
7458     public ActionMode startActionMode(ActionMode.Callback callback, int type) {
7459         ViewParent parent = getParent();
7460         if (parent == null) return null;
7461         try {
7462             return parent.startActionModeForChild(this, callback, type);
7463         } catch (AbstractMethodError ame) {
7464             // Older implementations of custom views might not implement this.
7465             return parent.startActionModeForChild(this, callback);
7466         }
7467     }
7468 
7469     /**
7470      * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
7471      * Context, creating a unique View identifier to retrieve the result.
7472      *
7473      * @param intent The Intent to be started.
7474      * @param requestCode The request code to use.
7475      * @hide
7476      */
7477     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
7478     public void startActivityForResult(Intent intent, int requestCode) {
7479         mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
7480         getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
7481     }
7482 
7483     /**
7484      * If this View corresponds to the calling who, dispatches the activity result.
7485      * @param who The identifier for the targeted View to receive the result.
7486      * @param requestCode The integer request code originally supplied to
7487      *                    startActivityForResult(), allowing you to identify who this
7488      *                    result came from.
7489      * @param resultCode The integer result code returned by the child activity
7490      *                   through its setResult().
7491      * @param data An Intent, which can return result data to the caller
7492      *               (various data can be attached to Intent "extras").
7493      * @return {@code true} if the activity result was dispatched.
7494      * @hide
7495      */
7496     public boolean dispatchActivityResult(
7497             String who, int requestCode, int resultCode, Intent data) {
7498         if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
7499             onActivityResult(requestCode, resultCode, data);
7500             mStartActivityRequestWho = null;
7501             return true;
7502         }
7503         return false;
7504     }
7505 
7506     /**
7507      * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
7508      *
7509      * @param requestCode The integer request code originally supplied to
7510      *                    startActivityForResult(), allowing you to identify who this
7511      *                    result came from.
7512      * @param resultCode The integer result code returned by the child activity
7513      *                   through its setResult().
7514      * @param data An Intent, which can return result data to the caller
7515      *               (various data can be attached to Intent "extras").
7516      * @hide
7517      */
7518     public void onActivityResult(int requestCode, int resultCode, Intent data) {
7519         // Do nothing.
7520     }
7521 
7522     /**
7523      * Register a callback to be invoked when a hardware key is pressed in this view.
7524      * Key presses in software input methods will generally not trigger the methods of
7525      * this listener.
7526      * @param l the key listener to attach to this view
7527      */
7528     public void setOnKeyListener(OnKeyListener l) {
7529         getListenerInfo().mOnKeyListener = l;
7530     }
7531 
7532     /**
7533      * Register a callback to be invoked when a touch event is sent to this view.
7534      * @param l the touch listener to attach to this view
7535      */
7536     public void setOnTouchListener(OnTouchListener l) {
7537         getListenerInfo().mOnTouchListener = l;
7538     }
7539 
7540     /**
7541      * Register a callback to be invoked when a generic motion event is sent to this view.
7542      * @param l the generic motion listener to attach to this view
7543      */
7544     public void setOnGenericMotionListener(OnGenericMotionListener l) {
7545         getListenerInfo().mOnGenericMotionListener = l;
7546     }
7547 
7548     /**
7549      * Register a callback to be invoked when a hover event is sent to this view.
7550      * @param l the hover listener to attach to this view
7551      */
7552     public void setOnHoverListener(OnHoverListener l) {
7553         getListenerInfo().mOnHoverListener = l;
7554     }
7555 
7556     /**
7557      * Register a drag event listener callback object for this View. The parameter is
7558      * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
7559      * View, the system calls the
7560      * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
7561      * @param l An implementation of {@link android.view.View.OnDragListener}.
7562      */
7563     public void setOnDragListener(OnDragListener l) {
7564         getListenerInfo().mOnDragListener = l;
7565     }
7566 
7567     /**
7568      * Give this view focus. This will cause
7569      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
7570      *
7571      * Note: this does not check whether this {@link View} should get focus, it just
7572      * gives it focus no matter what.  It should only be called internally by framework
7573      * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
7574      *
7575      * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
7576      *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
7577      *        focus moved when requestFocus() is called. It may not always
7578      *        apply, in which case use the default View.FOCUS_DOWN.
7579      * @param previouslyFocusedRect The rectangle of the view that had focus
7580      *        prior in this View's coordinate system.
7581      */
7582     void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
7583         if (DBG) {
7584             System.out.println(this + " requestFocus()");
7585         }
7586 
7587         if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
7588             mPrivateFlags |= PFLAG_FOCUSED;
7589 
7590             View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
7591 
7592             if (mParent != null) {
7593                 mParent.requestChildFocus(this, this);
7594                 updateFocusedInCluster(oldFocus, direction);
7595             }
7596 
7597             if (mAttachInfo != null) {
7598                 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
7599             }
7600 
7601             onFocusChanged(true, direction, previouslyFocusedRect);
7602             refreshDrawableState();
7603         }
7604     }
7605 
7606     /**
7607      * Sets this view's preference for reveal behavior when it gains focus.
7608      *
7609      * <p>When set to true, this is a signal to ancestor views in the hierarchy that
7610      * this view would prefer to be brought fully into view when it gains focus.
7611      * For example, a text field that a user is meant to type into. Other views such
7612      * as scrolling containers may prefer to opt-out of this behavior.</p>
7613      *
7614      * <p>The default value for views is true, though subclasses may change this
7615      * based on their preferred behavior.</p>
7616      *
7617      * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
7618      *
7619      * @see #getRevealOnFocusHint()
7620      */
7621     public final void setRevealOnFocusHint(boolean revealOnFocus) {
7622         if (revealOnFocus) {
7623             mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
7624         } else {
7625             mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
7626         }
7627     }
7628 
7629     /**
7630      * Returns this view's preference for reveal behavior when it gains focus.
7631      *
7632      * <p>When this method returns true for a child view requesting focus, ancestor
7633      * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
7634      * should make a best effort to make the newly focused child fully visible to the user.
7635      * When it returns false, ancestor views should preferably not disrupt scroll positioning or
7636      * other properties affecting visibility to the user as part of the focus change.</p>
7637      *
7638      * @return true if this view would prefer to become fully visible when it gains focus,
7639      *         false if it would prefer not to disrupt scroll positioning
7640      *
7641      * @see #setRevealOnFocusHint(boolean)
7642      */
7643     public final boolean getRevealOnFocusHint() {
7644         return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
7645     }
7646 
7647     /**
7648      * Populates <code>outRect</code> with the hotspot bounds. By default,
7649      * the hotspot bounds are identical to the screen bounds.
7650      *
7651      * @param outRect rect to populate with hotspot bounds
7652      * @hide Only for internal use by views and widgets.
7653      */
7654     public void getHotspotBounds(Rect outRect) {
7655         final Drawable background = getBackground();
7656         if (background != null) {
7657             background.getHotspotBounds(outRect);
7658         } else {
7659             getBoundsOnScreen(outRect);
7660         }
7661     }
7662 
7663     /**
7664      * Request that a rectangle of this view be visible on the screen,
7665      * scrolling if necessary just enough.
7666      *
7667      * <p>A View should call this if it maintains some notion of which part
7668      * of its content is interesting.  For example, a text editing view
7669      * should call this when its cursor moves.
7670      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
7671      * It should not be affected by which part of the View is currently visible or its scroll
7672      * position.
7673      *
7674      * @param rectangle The rectangle in the View's content coordinate space
7675      * @return Whether any parent scrolled.
7676      */
7677     public boolean requestRectangleOnScreen(Rect rectangle) {
7678         return requestRectangleOnScreen(rectangle, false);
7679     }
7680 
7681     /**
7682      * Request that a rectangle of this view be visible on the screen,
7683      * scrolling if necessary just enough.
7684      *
7685      * <p>A View should call this if it maintains some notion of which part
7686      * of its content is interesting.  For example, a text editing view
7687      * should call this when its cursor moves.
7688      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
7689      * It should not be affected by which part of the View is currently visible or its scroll
7690      * position.
7691      * <p>When <code>immediate</code> is set to true, scrolling will not be
7692      * animated.
7693      *
7694      * @param rectangle The rectangle in the View's content coordinate space
7695      * @param immediate True to forbid animated scrolling, false otherwise
7696      * @return Whether any parent scrolled.
7697      */
7698     public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
7699         if (mParent == null) {
7700             return false;
7701         }
7702 
7703         View child = this;
7704 
7705         RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
7706         position.set(rectangle);
7707 
7708         ViewParent parent = mParent;
7709         boolean scrolled = false;
7710         while (parent != null) {
7711             rectangle.set((int) position.left, (int) position.top,
7712                     (int) position.right, (int) position.bottom);
7713 
7714             scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
7715 
7716             if (!(parent instanceof View)) {
7717                 break;
7718             }
7719 
7720             // move it from child's content coordinate space to parent's content coordinate space
7721             position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
7722 
7723             child = (View) parent;
7724             parent = child.getParent();
7725         }
7726 
7727         return scrolled;
7728     }
7729 
7730     /**
7731      * Called when this view wants to give up focus. If focus is cleared
7732      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
7733      * <p>
7734      * <strong>Note:</strong> When not in touch-mode, the framework will try to give focus
7735      * to the first focusable View from the top after focus is cleared. Hence, if this
7736      * View is the first from the top that can take focus, then all callbacks
7737      * related to clearing focus will be invoked after which the framework will
7738      * give focus to this view.
7739      * </p>
7740      */
7741     public void clearFocus() {
7742         if (DBG) {
7743             System.out.println(this + " clearFocus()");
7744         }
7745 
7746         final boolean refocus = sAlwaysAssignFocus || !isInTouchMode();
7747         clearFocusInternal(null, true, refocus);
7748     }
7749 
7750     /**
7751      * Clears focus from the view, optionally propagating the change up through
7752      * the parent hierarchy and requesting that the root view place new focus.
7753      *
7754      * @param propagate whether to propagate the change up through the parent
7755      *            hierarchy
7756      * @param refocus when propagate is true, specifies whether to request the
7757      *            root view place new focus
7758      */
7759     void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
7760         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
7761             mPrivateFlags &= ~PFLAG_FOCUSED;
7762             clearParentsWantFocus();
7763 
7764             if (propagate && mParent != null) {
7765                 mParent.clearChildFocus(this);
7766             }
7767 
7768             onFocusChanged(false, 0, null);
7769             refreshDrawableState();
7770 
7771             if (propagate && (!refocus || !rootViewRequestFocus())) {
7772                 notifyGlobalFocusCleared(this);
7773             }
7774         }
7775     }
7776 
7777     void notifyGlobalFocusCleared(View oldFocus) {
7778         if (oldFocus != null && mAttachInfo != null) {
7779             mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
7780         }
7781     }
7782 
7783     boolean rootViewRequestFocus() {
7784         final View root = getRootView();
7785         return root != null && root.requestFocus();
7786     }
7787 
7788     /**
7789      * Called internally by the view system when a new view is getting focus.
7790      * This is what clears the old focus.
7791      * <p>
7792      * <b>NOTE:</b> The parent view's focused child must be updated manually
7793      * after calling this method. Otherwise, the view hierarchy may be left in
7794      * an inconstent state.
7795      */
7796     void unFocus(View focused) {
7797         if (DBG) {
7798             System.out.println(this + " unFocus()");
7799         }
7800 
7801         clearFocusInternal(focused, false, false);
7802     }
7803 
7804     /**
7805      * Returns true if this view has focus itself, or is the ancestor of the
7806      * view that has focus.
7807      *
7808      * @return True if this view has or contains focus, false otherwise.
7809      */
7810     @ViewDebug.ExportedProperty(category = "focus")
7811     public boolean hasFocus() {
7812         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
7813     }
7814 
7815     /**
7816      * Returns true if this view is focusable or if it contains a reachable View
7817      * for which {@link #hasFocusable()} returns {@code true}. A "reachable hasFocusable()"
7818      * is a view whose parents do not block descendants focus.
7819      * Only {@link #VISIBLE} views are considered focusable.
7820      *
7821      * <p>As of {@link Build.VERSION_CODES#O} views that are determined to be focusable
7822      * through {@link #FOCUSABLE_AUTO} will also cause this method to return {@code true}.
7823      * Apps that declare a {@link android.content.pm.ApplicationInfo#targetSdkVersion} of
7824      * earlier than {@link Build.VERSION_CODES#O} will continue to see this method return
7825      * {@code false} for views not explicitly marked as focusable.
7826      * Use {@link #hasExplicitFocusable()} if you require the pre-{@link Build.VERSION_CODES#O}
7827      * behavior.</p>
7828      *
7829      * @return {@code true} if the view is focusable or if the view contains a focusable
7830      *         view, {@code false} otherwise
7831      *
7832      * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
7833      * @see ViewGroup#getTouchscreenBlocksFocus()
7834      * @see #hasExplicitFocusable()
7835      */
7836     public boolean hasFocusable() {
7837         return hasFocusable(!sHasFocusableExcludeAutoFocusable, false);
7838     }
7839 
7840     /**
7841      * Returns true if this view is focusable or if it contains a reachable View
7842      * for which {@link #hasExplicitFocusable()} returns {@code true}.
7843      * A "reachable hasExplicitFocusable()" is a view whose parents do not block descendants focus.
7844      * Only {@link #VISIBLE} views for which {@link #getFocusable()} would return
7845      * {@link #FOCUSABLE} are considered focusable.
7846      *
7847      * <p>This method preserves the pre-{@link Build.VERSION_CODES#O} behavior of
7848      * {@link #hasFocusable()} in that only views explicitly set focusable will cause
7849      * this method to return true. A view set to {@link #FOCUSABLE_AUTO} that resolves
7850      * to focusable will not.</p>
7851      *
7852      * @return {@code true} if the view is focusable or if the view contains a focusable
7853      *         view, {@code false} otherwise
7854      *
7855      * @see #hasFocusable()
7856      */
7857     public boolean hasExplicitFocusable() {
7858         return hasFocusable(false, true);
7859     }
7860 
7861     boolean hasFocusable(boolean allowAutoFocus, boolean dispatchExplicit) {
7862         if (!isFocusableInTouchMode()) {
7863             for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
7864                 final ViewGroup g = (ViewGroup) p;
7865                 if (g.shouldBlockFocusForTouchscreen()) {
7866                     return false;
7867                 }
7868             }
7869         }
7870 
7871         // Invisible, gone, or disabled views are never focusable.
7872         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE
7873                 || (mViewFlags & ENABLED_MASK) != ENABLED) {
7874             return false;
7875         }
7876 
7877         // Only use effective focusable value when allowed.
7878         if ((allowAutoFocus || getFocusable() != FOCUSABLE_AUTO) && isFocusable()) {
7879             return true;
7880         }
7881 
7882         return false;
7883     }
7884 
7885     /**
7886      * Called by the view system when the focus state of this view changes.
7887      * When the focus change event is caused by directional navigation, direction
7888      * and previouslyFocusedRect provide insight into where the focus is coming from.
7889      * When overriding, be sure to call up through to the super class so that
7890      * the standard focus handling will occur.
7891      *
7892      * @param gainFocus True if the View has focus; false otherwise.
7893      * @param direction The direction focus has moved when requestFocus()
7894      *                  is called to give this view focus. Values are
7895      *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
7896      *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
7897      *                  It may not always apply, in which case use the default.
7898      * @param previouslyFocusedRect The rectangle, in this view's coordinate
7899      *        system, of the previously focused view.  If applicable, this will be
7900      *        passed in as finer grained information about where the focus is coming
7901      *        from (in addition to direction).  Will be <code>null</code> otherwise.
7902      */
7903     @CallSuper
7904     protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
7905             @Nullable Rect previouslyFocusedRect) {
7906         if (gainFocus) {
7907             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
7908         } else {
7909             notifyViewAccessibilityStateChangedIfNeeded(
7910                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7911         }
7912 
7913         // Here we check whether we still need the default focus highlight, and switch it on/off.
7914         switchDefaultFocusHighlight();
7915 
7916         if (!gainFocus) {
7917             if (isPressed()) {
7918                 setPressed(false);
7919             }
7920             if (mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
7921                 notifyFocusChangeToInputMethodManager(false /* hasFocus */);
7922             }
7923             onFocusLost();
7924         } else if (mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
7925             notifyFocusChangeToInputMethodManager(true /* hasFocus */);
7926         }
7927 
7928         invalidate(true);
7929         ListenerInfo li = mListenerInfo;
7930         if (li != null && li.mOnFocusChangeListener != null) {
7931             li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
7932         }
7933 
7934         if (mAttachInfo != null) {
7935             mAttachInfo.mKeyDispatchState.reset(this);
7936         }
7937 
7938         notifyEnterOrExitForAutoFillIfNeeded(gainFocus);
7939     }
7940 
7941     /**
7942      * Notify {@link InputMethodManager} about the focus change of the {@link View}.
7943      *
7944      * <p>Does nothing when {@link InputMethodManager} is not available.</p>
7945      *
7946      * @param hasFocus {@code true} when the {@link View} is being focused.
7947      */
7948     private void notifyFocusChangeToInputMethodManager(boolean hasFocus) {
7949         final InputMethodManager imm =
7950                 getContext().getSystemService(InputMethodManager.class);
7951         if (imm == null) {
7952             return;
7953         }
7954         if (hasFocus) {
7955             imm.focusIn(this);
7956         } else {
7957             imm.focusOut(this);
7958         }
7959     }
7960 
7961     /** @hide */
7962     public void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {
7963         if (canNotifyAutofillEnterExitEvent()) {
7964             AutofillManager afm = getAutofillManager();
7965             if (afm != null) {
7966                 if (enter && isFocused()) {
7967                     // We have not been laid out yet, hence cannot evaluate
7968                     // whether this view is visible to the user, we will do
7969                     // the evaluation once layout is complete.
7970                     if (!isLaidOut()) {
7971                         mPrivateFlags3 |= PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
7972                     } else if (isVisibleToUser()) {
7973                         // TODO This is a potential problem that View gets focus before it's visible
7974                         // to User. Ideally View should handle the event when isVisibleToUser()
7975                         // becomes true where it should issue notifyViewEntered().
7976                         afm.notifyViewEntered(this);
7977                     }
7978                 } else if (!enter && !isFocused()) {
7979                     afm.notifyViewExited(this);
7980                 }
7981             }
7982         }
7983     }
7984 
7985     /**
7986      * Visually distinct portion of a window with window-like semantics are considered panes for
7987      * accessibility purposes. One example is the content view of a fragment that is replaced.
7988      * In order for accessibility services to understand a pane's window-like behavior, panes
7989      * should have descriptive titles. Views with pane titles produce {@link AccessibilityEvent}s
7990      * when they appear, disappear, or change title.
7991      *
7992      * @param accessibilityPaneTitle The pane's title. Setting to {@code null} indicates that this
7993      *                               View is not a pane.
7994      *
7995      * {@see AccessibilityNodeInfo#setPaneTitle(CharSequence)}
7996      *
7997      * @attr ref android.R.styleable#View_accessibilityPaneTitle
7998      */
7999     public void setAccessibilityPaneTitle(@Nullable CharSequence accessibilityPaneTitle) {
8000         if (!TextUtils.equals(accessibilityPaneTitle, mAccessibilityPaneTitle)) {
8001             mAccessibilityPaneTitle = accessibilityPaneTitle;
8002             notifyViewAccessibilityStateChangedIfNeeded(
8003                     AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_TITLE);
8004         }
8005     }
8006 
8007     /**
8008      * Get the title of the pane for purposes of accessibility.
8009      *
8010      * @return The current pane title.
8011      *
8012      * {@see #setAccessibilityPaneTitle}.
8013      *
8014      * @attr ref android.R.styleable#View_accessibilityPaneTitle
8015      */
8016     @InspectableProperty
8017     @Nullable
8018     public CharSequence getAccessibilityPaneTitle() {
8019         return mAccessibilityPaneTitle;
8020     }
8021 
8022     private boolean isAccessibilityPane() {
8023         return mAccessibilityPaneTitle != null;
8024     }
8025 
8026     /**
8027      * Sends an accessibility event of the given type. If accessibility is
8028      * not enabled this method has no effect. The default implementation calls
8029      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
8030      * to populate information about the event source (this View), then calls
8031      * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
8032      * populate the text content of the event source including its descendants,
8033      * and last calls
8034      * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
8035      * on its parent to request sending of the event to interested parties.
8036      * <p>
8037      * If an {@link AccessibilityDelegate} has been specified via calling
8038      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8039      * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
8040      * responsible for handling this call.
8041      * </p>
8042      *
8043      * @param eventType The type of the event to send, as defined by several types from
8044      * {@link android.view.accessibility.AccessibilityEvent}, such as
8045      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
8046      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
8047      *
8048      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
8049      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
8050      * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
8051      * @see AccessibilityDelegate
8052      */
8053     public void sendAccessibilityEvent(int eventType) {
8054         if (mAccessibilityDelegate != null) {
8055             mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
8056         } else {
8057             sendAccessibilityEventInternal(eventType);
8058         }
8059     }
8060 
8061     /**
8062      * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
8063      * {@link AccessibilityEvent} to suggest that an accessibility service announce the
8064      * specified text to its users.
8065      * <p>
8066      * Note: The event generated with this API carries no semantic meaning, and is appropriate only
8067      * in exceptional situations. Apps can generally achieve correct behavior for accessibility by
8068      * accurately supplying the semantics of their UI.
8069      * They should not need to specify what exactly is announced to users.
8070      *
8071      * @param text The announcement text.
8072      */
8073     public void announceForAccessibility(CharSequence text) {
8074         if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
8075             AccessibilityEvent event = AccessibilityEvent.obtain(
8076                     AccessibilityEvent.TYPE_ANNOUNCEMENT);
8077             onInitializeAccessibilityEvent(event);
8078             event.getText().add(text);
8079             event.setContentDescription(null);
8080             mParent.requestSendAccessibilityEvent(this, event);
8081         }
8082     }
8083 
8084     /**
8085      * @see #sendAccessibilityEvent(int)
8086      *
8087      * Note: Called from the default {@link AccessibilityDelegate}.
8088      *
8089      * @hide
8090      */
8091     public void sendAccessibilityEventInternal(int eventType) {
8092         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
8093             sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
8094         }
8095     }
8096 
8097     /**
8098      * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
8099      * takes as an argument an empty {@link AccessibilityEvent} and does not
8100      * perform a check whether accessibility is enabled.
8101      * <p>
8102      * If an {@link AccessibilityDelegate} has been specified via calling
8103      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8104      * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
8105      * is responsible for handling this call.
8106      * </p>
8107      *
8108      * @param event The event to send.
8109      *
8110      * @see #sendAccessibilityEvent(int)
8111      */
8112     public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
8113         if (mAccessibilityDelegate != null) {
8114             mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
8115         } else {
8116             sendAccessibilityEventUncheckedInternal(event);
8117         }
8118     }
8119 
8120     /**
8121      * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
8122      *
8123      * Note: Called from the default {@link AccessibilityDelegate}.
8124      *
8125      * @hide
8126      */
8127     public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
8128         // Panes disappearing are relevant even if though the view is no longer visible.
8129         boolean isWindowStateChanged =
8130                 (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
8131         boolean isWindowDisappearedEvent = isWindowStateChanged && ((event.getContentChangeTypes()
8132                 & AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED) != 0);
8133         if (!isShown() && !isWindowDisappearedEvent) {
8134             return;
8135         }
8136         onInitializeAccessibilityEvent(event);
8137         // Only a subset of accessibility events populates text content.
8138         if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
8139             dispatchPopulateAccessibilityEvent(event);
8140         }
8141         // In the beginning we called #isShown(), so we know that getParent() is not null.
8142         ViewParent parent = getParent();
8143         if (parent != null) {
8144             getParent().requestSendAccessibilityEvent(this, event);
8145         }
8146     }
8147 
8148     /**
8149      * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
8150      * to its children for adding their text content to the event. Note that the
8151      * event text is populated in a separate dispatch path since we add to the
8152      * event not only the text of the source but also the text of all its descendants.
8153      * A typical implementation will call
8154      * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
8155      * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
8156      * on each child. Override this method if custom population of the event text
8157      * content is required.
8158      * <p>
8159      * If an {@link AccessibilityDelegate} has been specified via calling
8160      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8161      * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
8162      * is responsible for handling this call.
8163      * </p>
8164      * <p>
8165      * <em>Note:</em> Accessibility events of certain types are not dispatched for
8166      * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
8167      * </p>
8168      *
8169      * @param event The event.
8170      *
8171      * @return True if the event population was completed.
8172      */
8173     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
8174         if (mAccessibilityDelegate != null) {
8175             return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
8176         } else {
8177             return dispatchPopulateAccessibilityEventInternal(event);
8178         }
8179     }
8180 
8181     /**
8182      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
8183      *
8184      * Note: Called from the default {@link AccessibilityDelegate}.
8185      *
8186      * @hide
8187      */
8188     public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
8189         onPopulateAccessibilityEvent(event);
8190         return false;
8191     }
8192 
8193     /**
8194      * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
8195      * giving a chance to this View to populate the accessibility event with its
8196      * text content. While this method is free to modify event
8197      * attributes other than text content, doing so should normally be performed in
8198      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
8199      * <p>
8200      * Example: Adding formatted date string to an accessibility event in addition
8201      *          to the text added by the super implementation:
8202      * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
8203      *     super.onPopulateAccessibilityEvent(event);
8204      *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
8205      *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
8206      *         mCurrentDate.getTimeInMillis(), flags);
8207      *     event.getText().add(selectedDateUtterance);
8208      * }</pre>
8209      * <p>
8210      * If an {@link AccessibilityDelegate} has been specified via calling
8211      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8212      * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
8213      * is responsible for handling this call.
8214      * </p>
8215      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
8216      * information to the event, in case the default implementation has basic information to add.
8217      * </p>
8218      *
8219      * @param event The accessibility event which to populate.
8220      *
8221      * @see #sendAccessibilityEvent(int)
8222      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
8223      */
8224     @CallSuper
8225     public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
8226         if (mAccessibilityDelegate != null) {
8227             mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
8228         } else {
8229             onPopulateAccessibilityEventInternal(event);
8230         }
8231     }
8232 
8233     /**
8234      * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
8235      *
8236      * Note: Called from the default {@link AccessibilityDelegate}.
8237      *
8238      * @hide
8239      */
8240     public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
8241         if ((event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED)
8242                 && isAccessibilityPane()) {
8243             event.getText().add(getAccessibilityPaneTitle());
8244         }
8245     }
8246 
8247     /**
8248      * Initializes an {@link AccessibilityEvent} with information about
8249      * this View which is the event source. In other words, the source of
8250      * an accessibility event is the view whose state change triggered firing
8251      * the event.
8252      * <p>
8253      * Example: Setting the password property of an event in addition
8254      *          to properties set by the super implementation:
8255      * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
8256      *     super.onInitializeAccessibilityEvent(event);
8257      *     event.setPassword(true);
8258      * }</pre>
8259      * <p>
8260      * If an {@link AccessibilityDelegate} has been specified via calling
8261      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8262      * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
8263      * is responsible for handling this call.
8264      * </p>
8265      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
8266      * information to the event, in case the default implementation has basic information to add.
8267      * </p>
8268      * @param event The event to initialize.
8269      *
8270      * @see #sendAccessibilityEvent(int)
8271      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
8272      */
8273     @CallSuper
8274     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
8275         if (mAccessibilityDelegate != null) {
8276             mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
8277         } else {
8278             onInitializeAccessibilityEventInternal(event);
8279         }
8280     }
8281 
8282     /**
8283      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
8284      *
8285      * Note: Called from the default {@link AccessibilityDelegate}.
8286      *
8287      * @hide
8288      */
8289     @UnsupportedAppUsage
8290     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
8291         event.setSource(this);
8292         event.setClassName(getAccessibilityClassName());
8293         event.setPackageName(getContext().getPackageName());
8294         event.setEnabled(isEnabled());
8295         event.setContentDescription(mContentDescription);
8296 
8297         switch (event.getEventType()) {
8298             case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
8299                 ArrayList<View> focusablesTempList = (mAttachInfo != null)
8300                         ? mAttachInfo.mTempArrayList : new ArrayList<View>();
8301                 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
8302                 event.setItemCount(focusablesTempList.size());
8303                 event.setCurrentItemIndex(focusablesTempList.indexOf(this));
8304                 if (mAttachInfo != null) {
8305                     focusablesTempList.clear();
8306                 }
8307             } break;
8308             case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
8309                 CharSequence text = getIterableTextForAccessibility();
8310                 if (text != null && text.length() > 0) {
8311                     event.setFromIndex(getAccessibilitySelectionStart());
8312                     event.setToIndex(getAccessibilitySelectionEnd());
8313                     event.setItemCount(text.length());
8314                 }
8315             } break;
8316         }
8317     }
8318 
8319     /**
8320      * Returns an {@link AccessibilityNodeInfo} representing this view from the
8321      * point of view of an {@link android.accessibilityservice.AccessibilityService}.
8322      * This method is responsible for obtaining an accessibility node info from a
8323      * pool of reusable instances and calling
8324      * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
8325      * initialize the former.
8326      * <p>
8327      * Note: The client is responsible for recycling the obtained instance by calling
8328      *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
8329      * </p>
8330      *
8331      * @return A populated {@link AccessibilityNodeInfo}.
8332      *
8333      * @see AccessibilityNodeInfo
8334      */
8335     public AccessibilityNodeInfo createAccessibilityNodeInfo() {
8336         if (mAccessibilityDelegate != null) {
8337             return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
8338         } else {
8339             return createAccessibilityNodeInfoInternal();
8340         }
8341     }
8342 
8343     /**
8344      * @see #createAccessibilityNodeInfo()
8345      *
8346      * @hide
8347      */
8348     public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
8349         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
8350         if (provider != null) {
8351             return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
8352         } else {
8353             AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
8354             onInitializeAccessibilityNodeInfo(info);
8355             return info;
8356         }
8357     }
8358 
8359     /**
8360      * Initializes an {@link AccessibilityNodeInfo} with information about this view.
8361      * The base implementation sets:
8362      * <ul>
8363      *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
8364      *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
8365      *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
8366      *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
8367      *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
8368      *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
8369      *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
8370      *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
8371      *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
8372      *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
8373      *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
8374      *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
8375      *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
8376      * </ul>
8377      * <p>
8378      * Subclasses should override this method, call the super implementation,
8379      * and set additional attributes.
8380      * </p>
8381      * <p>
8382      * If an {@link AccessibilityDelegate} has been specified via calling
8383      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8384      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
8385      * is responsible for handling this call.
8386      * </p>
8387      *
8388      * @param info The instance to initialize.
8389      */
8390     @CallSuper
8391     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
8392         if (mAccessibilityDelegate != null) {
8393             mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
8394         } else {
8395             onInitializeAccessibilityNodeInfoInternal(info);
8396         }
8397     }
8398 
8399     /**
8400      * Gets the location of this view in screen coordinates.
8401      *
8402      * @param outRect The output location
8403      * @hide
8404      */
8405     @UnsupportedAppUsage
8406     public void getBoundsOnScreen(Rect outRect) {
8407         getBoundsOnScreen(outRect, false);
8408     }
8409 
8410     /**
8411      * Gets the location of this view in screen coordinates.
8412      *
8413      * @param outRect The output location
8414      * @param clipToParent Whether to clip child bounds to the parent ones.
8415      * @hide
8416      */
8417     @UnsupportedAppUsage
8418     public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
8419         if (mAttachInfo == null) {
8420             return;
8421         }
8422 
8423         RectF position = mAttachInfo.mTmpTransformRect;
8424         position.set(0, 0, mRight - mLeft, mBottom - mTop);
8425         mapRectFromViewToScreenCoords(position, clipToParent);
8426         outRect.set(Math.round(position.left), Math.round(position.top),
8427                 Math.round(position.right), Math.round(position.bottom));
8428     }
8429 
8430     /**
8431      * Map a rectangle from view-relative coordinates to screen-relative coordinates
8432      *
8433      * @param rect The rectangle to be mapped
8434      * @param clipToParent Whether to clip child bounds to the parent ones.
8435      * @hide
8436      */
8437     public void mapRectFromViewToScreenCoords(RectF rect, boolean clipToParent) {
8438         if (!hasIdentityMatrix()) {
8439             getMatrix().mapRect(rect);
8440         }
8441 
8442         rect.offset(mLeft, mTop);
8443 
8444         ViewParent parent = mParent;
8445         while (parent instanceof View) {
8446             View parentView = (View) parent;
8447 
8448             rect.offset(-parentView.mScrollX, -parentView.mScrollY);
8449 
8450             if (clipToParent) {
8451                 rect.left = Math.max(rect.left, 0);
8452                 rect.top = Math.max(rect.top, 0);
8453                 rect.right = Math.min(rect.right, parentView.getWidth());
8454                 rect.bottom = Math.min(rect.bottom, parentView.getHeight());
8455             }
8456 
8457             if (!parentView.hasIdentityMatrix()) {
8458                 parentView.getMatrix().mapRect(rect);
8459             }
8460 
8461             rect.offset(parentView.mLeft, parentView.mTop);
8462 
8463             parent = parentView.mParent;
8464         }
8465 
8466         if (parent instanceof ViewRootImpl) {
8467             ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
8468             rect.offset(0, -viewRootImpl.mCurScrollY);
8469         }
8470 
8471         rect.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
8472     }
8473 
8474     /**
8475      * Return the class name of this object to be used for accessibility purposes.
8476      * Subclasses should only override this if they are implementing something that
8477      * should be seen as a completely new class of view when used by accessibility,
8478      * unrelated to the class it is deriving from.  This is used to fill in
8479      * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
8480      */
8481     public CharSequence getAccessibilityClassName() {
8482         return View.class.getName();
8483     }
8484 
8485     /**
8486      * Called when assist structure is being retrieved from a view as part of
8487      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
8488      * @param structure Fill in with structured view data.  The default implementation
8489      * fills in all data that can be inferred from the view itself.
8490      */
8491     public void onProvideStructure(ViewStructure structure) {
8492         onProvideStructure(structure, VIEW_STRUCTURE_FOR_ASSIST, /* flags= */ 0);
8493     }
8494 
8495     /**
8496      * Populates a {@link ViewStructure} to fullfil an autofill request.
8497      *
8498      * <p>The structure should contain at least the following properties:
8499      * <ul>
8500      *   <li>Autofill id ({@link ViewStructure#setAutofillId(AutofillId, int)}).
8501      *   <li>Autofill type ({@link ViewStructure#setAutofillType(int)}).
8502      *   <li>Autofill value ({@link ViewStructure#setAutofillValue(AutofillValue)}).
8503      *   <li>Whether the data is sensitive ({@link ViewStructure#setDataIsSensitive(boolean)}).
8504      * </ul>
8505      *
8506      * <p>It's also recommended to set the following properties - the more properties the structure
8507      * has, the higher the changes of an {@link android.service.autofill.AutofillService} properly
8508      * using the structure:
8509      *
8510      * <ul>
8511      *   <li>Autofill hints ({@link ViewStructure#setAutofillHints(String[])}).
8512      *   <li>Autofill options ({@link ViewStructure#setAutofillOptions(CharSequence[])}) when the
8513      *       view can only be filled with predefined values (typically used when the autofill type
8514      *       is {@link #AUTOFILL_TYPE_LIST}).
8515      *   <li>Resource id ({@link ViewStructure#setId(int, String, String, String)}).
8516      *   <li>Class name ({@link ViewStructure#setClassName(String)}).
8517      *   <li>Content description ({@link ViewStructure#setContentDescription(CharSequence)}).
8518      *   <li>Visual properties such as visibility ({@link ViewStructure#setVisibility(int)}),
8519      *       dimensions ({@link ViewStructure#setDimens(int, int, int, int, int, int)}), and
8520      *       opacity ({@link ViewStructure#setOpaque(boolean)}).
8521      *   <li>For views representing text fields, text properties such as the text itself
8522      *       ({@link ViewStructure#setText(CharSequence)}), text hints
8523      *       ({@link ViewStructure#setHint(CharSequence)}, input type
8524      *       ({@link ViewStructure#setInputType(int)}),
8525      *   <li>For views representing HTML nodes, its web domain
8526      *       ({@link ViewStructure#setWebDomain(String)}) and HTML properties
8527      *       (({@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}).
8528      * </ul>
8529      *
8530      * <p>The default implementation of this method already sets most of these properties based on
8531      * related {@link View} methods (for example, the autofill id is set using
8532      * {@link #getAutofillId()}, the autofill type set using {@link #getAutofillType()}, etc.),
8533      * and views in the standard Android widgets library also override it to set their
8534      * relevant properties (for example, {@link android.widget.TextView} already sets the text
8535      * properties), so it's recommended to only override this method
8536      * (and call {@code super.onProvideAutofillStructure()}) when:
8537      *
8538      * <ul>
8539      *   <li>The view contents does not include PII (Personally Identifiable Information), so it
8540      *       can call {@link ViewStructure#setDataIsSensitive(boolean)} passing {@code false}.
8541      *   <li>The view can only be autofilled with predefined options, so it can call
8542      *       {@link ViewStructure#setAutofillOptions(CharSequence[])}.
8543      * </ul>
8544      *
8545      * <p><b>Note:</b> The {@code left} and {@code top} values set in
8546      * {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the next
8547      * {@link ViewGroup#isImportantForAutofill()} predecessor view included in the structure.
8548      *
8549      * <p>Views support the Autofill Framework mainly by:
8550      * <ul>
8551      *   <li>Providing the metadata defining what the view means and how it can be autofilled.
8552      *   <li>Notifying the Android System when the view value changed by calling
8553      *       {@link AutofillManager#notifyValueChanged(View)}.
8554      *   <li>Implementing the methods that autofill the view.
8555      * </ul>
8556      * <p>This method is responsible for the former; {@link #autofill(AutofillValue)} is responsible
8557      * for the latter.
8558      *
8559      * @param structure fill in with structured view data for autofill purposes.
8560      * @param flags optional flags.
8561      *
8562      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
8563      */
8564     public void onProvideAutofillStructure(ViewStructure structure, @AutofillFlags int flags) {
8565         onProvideStructure(structure, VIEW_STRUCTURE_FOR_AUTOFILL, flags);
8566     }
8567 
8568     /**
8569      * Populates a {@link ViewStructure} for content capture.
8570      *
8571      * <p>This method is called after a view is that is eligible for content capture
8572      * (for example, if it {@link #isImportantForAutofill()}, an intelligence service is enabled for
8573      * the user, and the activity rendering the view is enabled for content capture) is laid out and
8574      * is visible.
8575      *
8576      * <p>The populated structure is then passed to the service through
8577      * {@link ContentCaptureSession#notifyViewAppeared(ViewStructure)}.
8578      *
8579      * <p><b>Note: </b>views that manage a virtual structure under this view must populate just
8580      * the node representing this view and return right away, then asynchronously report (not
8581      * necessarily in the UI thread) when the children nodes appear, disappear or have their text
8582      * changed by calling
8583      * {@link ContentCaptureSession#notifyViewAppeared(ViewStructure)},
8584      * {@link ContentCaptureSession#notifyViewDisappeared(AutofillId)}, and
8585      * {@link ContentCaptureSession#notifyViewTextChanged(AutofillId, CharSequence)}
8586      * respectively. The structure for the a child must be created using
8587      * {@link ContentCaptureSession#newVirtualViewStructure(AutofillId, long)}, and the
8588      * {@code autofillId} for a child can be obtained either through
8589      * {@code childStructure.getAutofillId()} or
8590      * {@link ContentCaptureSession#newAutofillId(AutofillId, long)}.
8591      *
8592      * <p>When the virtual view hierarchy represents a web page, you should also:
8593      *
8594      * <ul>
8595      *   <li>Call {@link ContentCaptureManager#getContentCaptureConditions()} to infer content
8596      *   capture events should be generate for that URL.
8597      *   <li>Create a new {@link ContentCaptureSession} child for every HTML element that
8598      *   renders a new URL (like an {@code IFRAME}) and use that session to notify events from
8599      *   that subtree.
8600      * </ul>
8601      *
8602      * <p><b>Note: </b>the following methods of the {@code structure} will be ignored:
8603      * <ul>
8604      *   <li>{@link ViewStructure#setChildCount(int)}
8605      *   <li>{@link ViewStructure#addChildCount(int)}
8606      *   <li>{@link ViewStructure#getChildCount()}
8607      *   <li>{@link ViewStructure#newChild(int)}
8608      *   <li>{@link ViewStructure#asyncNewChild(int)}
8609      *   <li>{@link ViewStructure#asyncCommit()}
8610      *   <li>{@link ViewStructure#setWebDomain(String)}
8611      *   <li>{@link ViewStructure#newHtmlInfoBuilder(String)}
8612      *   <li>{@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}
8613      *   <li>{@link ViewStructure#setDataIsSensitive(boolean)}
8614      *   <li>{@link ViewStructure#setAlpha(float)}
8615      *   <li>{@link ViewStructure#setElevation(float)}
8616      *   <li>{@link ViewStructure#setTransformation(Matrix)}
8617      *
8618      * </ul>
8619      *
8620      * @hide
8621      */
8622     @TestApi
8623     public void onProvideContentCaptureStructure(@NonNull ViewStructure structure, int flags) {
8624         onProvideStructure(structure, VIEW_STRUCTURE_FOR_CONTENT_CAPTURE, flags);
8625     }
8626 
8627     /** @hide */
8628     protected void onProvideStructure(@NonNull ViewStructure structure,
8629             @ViewStructureType int viewFor, int flags) {
8630         final int id = mID;
8631         if (id != NO_ID && !isViewIdGenerated(id)) {
8632             String pkg, type, entry;
8633             try {
8634                 final Resources res = getResources();
8635                 entry = res.getResourceEntryName(id);
8636                 type = res.getResourceTypeName(id);
8637                 pkg = res.getResourcePackageName(id);
8638             } catch (Resources.NotFoundException e) {
8639                 entry = type = pkg = null;
8640             }
8641             structure.setId(id, pkg, type, entry);
8642         } else {
8643             structure.setId(id, null, null, null);
8644         }
8645 
8646         if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
8647                 || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
8648             final @AutofillType int autofillType = getAutofillType();
8649             // Don't need to fill autofill info if view does not support it.
8650             // For example, only TextViews that are editable support autofill
8651             if (autofillType != AUTOFILL_TYPE_NONE) {
8652                 structure.setAutofillType(autofillType);
8653                 structure.setAutofillHints(getAutofillHints());
8654                 structure.setAutofillValue(getAutofillValue());
8655             }
8656             structure.setImportantForAutofill(getImportantForAutofill());
8657         }
8658 
8659         int ignoredParentLeft = 0;
8660         int ignoredParentTop = 0;
8661         if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
8662                 && (flags & AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) {
8663             View parentGroup = null;
8664 
8665             ViewParent viewParent = getParent();
8666             if (viewParent instanceof View) {
8667                 parentGroup = (View) viewParent;
8668             }
8669 
8670             while (parentGroup != null && !parentGroup.isImportantForAutofill()) {
8671                 ignoredParentLeft += parentGroup.mLeft;
8672                 ignoredParentTop += parentGroup.mTop;
8673 
8674                 viewParent = parentGroup.getParent();
8675                 if (viewParent instanceof View) {
8676                     parentGroup = (View) viewParent;
8677                 } else {
8678                     break;
8679                 }
8680             }
8681         }
8682 
8683         structure.setDimens(ignoredParentLeft + mLeft, ignoredParentTop + mTop, mScrollX, mScrollY,
8684                 mRight - mLeft, mBottom - mTop);
8685         if (viewFor == VIEW_STRUCTURE_FOR_ASSIST) {
8686             if (!hasIdentityMatrix()) {
8687                 structure.setTransformation(getMatrix());
8688             }
8689             structure.setElevation(getZ());
8690         }
8691         structure.setVisibility(getVisibility());
8692         structure.setEnabled(isEnabled());
8693         if (isClickable()) {
8694             structure.setClickable(true);
8695         }
8696         if (isFocusable()) {
8697             structure.setFocusable(true);
8698         }
8699         if (isFocused()) {
8700             structure.setFocused(true);
8701         }
8702         if (isAccessibilityFocused()) {
8703             structure.setAccessibilityFocused(true);
8704         }
8705         if (isSelected()) {
8706             structure.setSelected(true);
8707         }
8708         if (isActivated()) {
8709             structure.setActivated(true);
8710         }
8711         if (isLongClickable()) {
8712             structure.setLongClickable(true);
8713         }
8714         if (this instanceof Checkable) {
8715             structure.setCheckable(true);
8716             if (((Checkable)this).isChecked()) {
8717                 structure.setChecked(true);
8718             }
8719         }
8720         if (isOpaque()) {
8721             structure.setOpaque(true);
8722         }
8723         if (isContextClickable()) {
8724             structure.setContextClickable(true);
8725         }
8726         structure.setClassName(getAccessibilityClassName().toString());
8727         structure.setContentDescription(getContentDescription());
8728     }
8729 
8730     /**
8731      * Called when assist structure is being retrieved from a view as part of
8732      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
8733      * generate additional virtual structure under this view.  The defaullt implementation
8734      * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
8735      * view's virtual accessibility nodes, if any.  You can override this for a more
8736      * optimal implementation providing this data.
8737      */
8738     public void onProvideVirtualStructure(ViewStructure structure) {
8739         onProvideVirtualStructureCompat(structure, false);
8740     }
8741 
8742     /**
8743      * Fallback implementation to populate a ViewStructure from accessibility state.
8744      *
8745      * @param structure The structure to populate.
8746      * @param forAutofill Whether the structure is needed for autofill.
8747      */
8748     private void onProvideVirtualStructureCompat(ViewStructure structure, boolean forAutofill) {
8749         final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
8750         if (provider != null) {
8751             if (forAutofill && Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
8752                 Log.v(AUTOFILL_LOG_TAG, "onProvideVirtualStructureCompat() for " + this);
8753             }
8754             final AccessibilityNodeInfo info = createAccessibilityNodeInfo();
8755             structure.setChildCount(1);
8756             final ViewStructure root = structure.newChild(0);
8757             populateVirtualStructure(root, provider, info, forAutofill);
8758             info.recycle();
8759         }
8760     }
8761 
8762     /**
8763      * Populates a {@link ViewStructure} containing virtual children to fullfil an autofill
8764      * request.
8765      *
8766      * <p>This method should be used when the view manages a virtual structure under this view. For
8767      * example, a view that draws input fields using {@link #draw(Canvas)}.
8768      *
8769      * <p>When implementing this method, subclasses must follow the rules below:
8770      *
8771      * <ul>
8772      *   <li>Add virtual children by calling the {@link ViewStructure#newChild(int)} or
8773      *       {@link ViewStructure#asyncNewChild(int)} methods, where the {@code id} is an unique id
8774      *       identifying the children in the virtual structure.
8775      *   <li>The children hierarchy can have multiple levels if necessary, but ideally it should
8776      *       exclude intermediate levels that are irrelevant for autofill; that would improve the
8777      *       autofill performance.
8778      *   <li>Also implement {@link #autofill(SparseArray)} to autofill the virtual
8779      *       children.
8780      *   <li>Set the autofill properties of the child structure as defined by
8781      *       {@link #onProvideAutofillStructure(ViewStructure, int)}, using
8782      *       {@link ViewStructure#setAutofillId(AutofillId, int)} to set its autofill id.
8783      *   <li>Call {@link android.view.autofill.AutofillManager#notifyViewEntered(View, int, Rect)}
8784      *       and/or {@link android.view.autofill.AutofillManager#notifyViewExited(View, int)}
8785      *       when the focused virtual child changed.
8786      *   <li>Override {@link #isVisibleToUserForAutofill(int)} to allow the platform to query
8787      *       whether a given virtual view is visible to the user in order to support triggering
8788      *       save when all views of interest go away.
8789      *   <li>Call
8790      *    {@link android.view.autofill.AutofillManager#notifyValueChanged(View, int, AutofillValue)}
8791      *       when the value of a virtual child changed.
8792      *   <li>Call {@link
8793      *    android.view.autofill.AutofillManager#notifyViewVisibilityChanged(View, int, boolean)}
8794      *       when the visibility of a virtual child changed.
8795      *   <li>Call
8796      *    {@link android.view.autofill.AutofillManager#notifyViewClicked(View, int)} when a virtual
8797      *       child is clicked.
8798      *   <li>Call {@link AutofillManager#commit()} when the autofill context of the view structure
8799      *       changed and the current context should be committed (for example, when the user tapped
8800      *       a {@code SUBMIT} button in an HTML page).
8801      *   <li>Call {@link AutofillManager#cancel()} when the autofill context of the view structure
8802      *       changed and the current context should be canceled (for example, when the user tapped
8803      *       a {@code CANCEL} button in an HTML page).
8804      *   <li>Provide ways for users to manually request autofill by calling
8805      *       {@link AutofillManager#requestAutofill(View, int, Rect)}.
8806      *   <li>The {@code left} and {@code top} values set in
8807      *       {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the
8808      *       next {@link ViewGroup#isImportantForAutofill()} predecessor view included in the
8809      *       structure.
8810      * </ul>
8811      *
8812      * <p>Views with virtual children support the Autofill Framework mainly by:
8813      * <ul>
8814      *   <li>Providing the metadata defining what the virtual children mean and how they can be
8815      *       autofilled.
8816      *   <li>Implementing the methods that autofill the virtual children.
8817      * </ul>
8818      * <p>This method is responsible for the former; {@link #autofill(SparseArray)} is responsible
8819      * for the latter.
8820      *
8821      * @param structure fill in with virtual children data for autofill purposes.
8822      * @param flags optional flags.
8823      *
8824      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
8825      */
8826     public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
8827         if (mContext.isAutofillCompatibilityEnabled()) {
8828             onProvideVirtualStructureCompat(structure, true);
8829         }
8830     }
8831 
8832     /**
8833      * Automatically fills the content of this view with the {@code value}.
8834      *
8835      * <p>Views support the Autofill Framework mainly by:
8836      * <ul>
8837      *   <li>Providing the metadata defining what the view means and how it can be autofilled.
8838      *   <li>Implementing the methods that autofill the view.
8839      * </ul>
8840      * <p>{@link #onProvideAutofillStructure(ViewStructure, int)} is responsible for the former,
8841      * this method is responsible for latter.
8842      *
8843      * <p>This method does nothing by default, but when overridden it typically:
8844      * <ol>
8845      *   <li>Checks if the provided value matches the expected type (which is defined by
8846      *       {@link #getAutofillType()}).
8847      *   <li>Checks if the view is editable - if it isn't, it should return right away.
8848      *   <li>Call the proper getter method on {@link AutofillValue} to fetch the actual value.
8849      *   <li>Pass the actual value to the equivalent setter in the view.
8850      * </ol>
8851      *
8852      * <p>For example, a text-field view could implement the method this way:
8853      *
8854      * <pre class="prettyprint">
8855      * &#64;Override
8856      * public void autofill(AutofillValue value) {
8857      *   if (!value.isText() || !this.isEditable()) {
8858      *      return;
8859      *   }
8860      *   CharSequence text = value.getTextValue();
8861      *   if (text != null) {
8862      *     this.setText(text);
8863      *   }
8864      * }
8865      * </pre>
8866      *
8867      * <p>If the value is updated asynchronously, the next call to
8868      * {@link AutofillManager#notifyValueChanged(View)} must happen <b>after</b> the value was
8869      * changed to the autofilled value. If not, the view will not be considered autofilled.
8870      *
8871      * <p><b>Note:</b> After this method is called, the value returned by
8872      * {@link #getAutofillValue()} must be equal to the {@code value} passed to it, otherwise the
8873      * view will not be highlighted as autofilled.
8874      *
8875      * @param value value to be autofilled.
8876      */
8877     public void autofill(@SuppressWarnings("unused") AutofillValue value) {
8878     }
8879 
8880     /**
8881      * Automatically fills the content of the virtual children within this view.
8882      *
8883      * <p>Views with virtual children support the Autofill Framework mainly by:
8884      * <ul>
8885      *   <li>Providing the metadata defining what the virtual children mean and how they can be
8886      *       autofilled.
8887      *   <li>Implementing the methods that autofill the virtual children.
8888      * </ul>
8889      * <p>{@link #onProvideAutofillVirtualStructure(ViewStructure, int)} is responsible for the
8890      * former, this method is responsible for the latter - see {@link #autofill(AutofillValue)} and
8891      * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} for more info about autofill.
8892      *
8893      * <p>If a child value is updated asynchronously, the next call to
8894      * {@link AutofillManager#notifyValueChanged(View, int, AutofillValue)} must happen
8895      * <b>after</b> the value was changed to the autofilled value. If not, the child will not be
8896      * considered autofilled.
8897      *
8898      * <p><b>Note:</b> To indicate that a virtual view was autofilled,
8899      * <code>?android:attr/autofilledHighlight</code> should be drawn over it until the data
8900      * changes.
8901      *
8902      * @param values map of values to be autofilled, keyed by virtual child id.
8903      *
8904      * @attr ref android.R.styleable#Theme_autofilledHighlight
8905      */
8906     public void autofill(@NonNull @SuppressWarnings("unused") SparseArray<AutofillValue> values) {
8907         if (!mContext.isAutofillCompatibilityEnabled()) {
8908             return;
8909         }
8910         final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
8911         if (provider == null) {
8912             return;
8913         }
8914         final int valueCount = values.size();
8915         for (int i = 0; i < valueCount; i++) {
8916             final AutofillValue value = values.valueAt(i);
8917             if (value.isText()) {
8918                 final int virtualId = values.keyAt(i);
8919                 final CharSequence text = value.getTextValue();
8920                 final Bundle arguments = new Bundle();
8921                 arguments.putCharSequence(
8922                         AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text);
8923                 provider.performAction(virtualId, AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
8924             }
8925         }
8926     }
8927 
8928     /**
8929      * Gets the unique, logical identifier of this view in the activity, for autofill purposes.
8930      *
8931      * <p>The autofill id is created on demand, unless it is explicitly set by
8932      * {@link #setAutofillId(AutofillId)}.
8933      *
8934      * <p>See {@link #setAutofillId(AutofillId)} for more info.
8935      *
8936      * @return The View's autofill id.
8937      */
8938     public final AutofillId getAutofillId() {
8939         if (mAutofillId == null) {
8940             // The autofill id needs to be unique, but its value doesn't matter,
8941             // so it's better to reuse the accessibility id to save space.
8942             mAutofillId = new AutofillId(getAutofillViewId());
8943         }
8944         return mAutofillId;
8945     }
8946 
8947     /**
8948      * Sets the unique, logical identifier of this view in the activity, for autofill purposes.
8949      *
8950      * <p>The autofill id is created on demand, and this method should only be called when a view is
8951      * reused after {@link #dispatchProvideAutofillStructure(ViewStructure, int)} is called, as
8952      * that method creates a snapshot of the view that is passed along to the autofill service.
8953      *
8954      * <p>This method is typically used when view subtrees are recycled to represent different
8955      * content* &mdash;in this case, the autofill id can be saved before the view content is swapped
8956      * out, and restored later when it's swapped back in. For example:
8957      *
8958      * <pre>
8959      * EditText reusableView = ...;
8960      * ViewGroup parentView = ...;
8961      * AutofillManager afm = ...;
8962      *
8963      * // Swap out the view and change its contents
8964      * AutofillId oldId = reusableView.getAutofillId();
8965      * CharSequence oldText = reusableView.getText();
8966      * parentView.removeView(reusableView);
8967      * AutofillId newId = afm.getNextAutofillId();
8968      * reusableView.setText("New I am");
8969      * reusableView.setAutofillId(newId);
8970      * parentView.addView(reusableView);
8971      *
8972      * // Later, swap the old content back in
8973      * parentView.removeView(reusableView);
8974      * reusableView.setAutofillId(oldId);
8975      * reusableView.setText(oldText);
8976      * parentView.addView(reusableView);
8977      * </pre>
8978      *
8979      * @param id an autofill ID that is unique in the {@link android.app.Activity} hosting the view,
8980      * or {@code null} to reset it. Usually it's an id previously allocated to another view (and
8981      * obtained through {@link #getAutofillId()}), or a new value obtained through
8982      * {@link AutofillManager#getNextAutofillId()}.
8983      *
8984      * @throws IllegalStateException if the view is already {@link #isAttachedToWindow() attached to
8985      * a window}.
8986      *
8987      * @throws IllegalArgumentException if the id is an autofill id associated with a virtual view.
8988      */
8989     public void setAutofillId(@Nullable AutofillId id) {
8990         // TODO(b/37566627): add unit / CTS test for all possible combinations below
8991         if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
8992             Log.v(AUTOFILL_LOG_TAG, "setAutofill(): from " + mAutofillId + " to " + id);
8993         }
8994         if (isAttachedToWindow()) {
8995             throw new IllegalStateException("Cannot set autofill id when view is attached");
8996         }
8997         if (id != null && !id.isNonVirtual()) {
8998             throw new IllegalStateException("Cannot set autofill id assigned to virtual views");
8999         }
9000         if (id == null && (mPrivateFlags3 & PFLAG3_AUTOFILLID_EXPLICITLY_SET) == 0) {
9001             // Ignore reset because it was never explicitly set before.
9002             return;
9003         }
9004         mAutofillId = id;
9005         if (id != null) {
9006             mAutofillViewId = id.getViewId();
9007             mPrivateFlags3 |= PFLAG3_AUTOFILLID_EXPLICITLY_SET;
9008         } else {
9009             mAutofillViewId = NO_ID;
9010             mPrivateFlags3 &= ~PFLAG3_AUTOFILLID_EXPLICITLY_SET;
9011         }
9012     }
9013 
9014     /**
9015      * Describes the autofill type of this view, so an
9016      * {@link android.service.autofill.AutofillService} can create the proper {@link AutofillValue}
9017      * when autofilling the view.
9018      *
9019      * <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it to properly
9020      * support the Autofill Framework.
9021      *
9022      * @return either {@link #AUTOFILL_TYPE_NONE}, {@link #AUTOFILL_TYPE_TEXT},
9023      * {@link #AUTOFILL_TYPE_LIST}, {@link #AUTOFILL_TYPE_DATE}, or {@link #AUTOFILL_TYPE_TOGGLE}.
9024      *
9025      * @see #onProvideAutofillStructure(ViewStructure, int)
9026      * @see #autofill(AutofillValue)
9027      */
9028     public @AutofillType int getAutofillType() {
9029         return AUTOFILL_TYPE_NONE;
9030     }
9031 
9032     /**
9033      * Gets the hints that help an {@link android.service.autofill.AutofillService} determine how
9034      * to autofill the view with the user's data.
9035      *
9036      * <p>See {@link #setAutofillHints(String...)} for more info about these hints.
9037      *
9038      * @return The hints set via the attribute or {@link #setAutofillHints(String...)}, or
9039      * {@code null} if no hints were set.
9040      *
9041      * @attr ref android.R.styleable#View_autofillHints
9042      */
9043     @ViewDebug.ExportedProperty()
9044     @InspectableProperty
9045     @Nullable public String[] getAutofillHints() {
9046         return mAutofillHints;
9047     }
9048 
9049     /**
9050      * @hide
9051      */
9052     @TestApi
9053     public boolean isAutofilled() {
9054         return (mPrivateFlags3 & PFLAG3_IS_AUTOFILLED) != 0;
9055     }
9056 
9057     /**
9058      * Gets the {@link View}'s current autofill value.
9059      *
9060      * <p>By default returns {@code null}, but subclasses should override it and return an
9061      * appropriate value to properly support the Autofill Framework.
9062      *
9063      * @see #onProvideAutofillStructure(ViewStructure, int)
9064      * @see #autofill(AutofillValue)
9065      */
9066     @Nullable
9067     public AutofillValue getAutofillValue() {
9068         return null;
9069     }
9070 
9071     /**
9072      * Gets the mode for determining whether this view is important for autofill.
9073      *
9074      * <p>See {@link #setImportantForAutofill(int)} and {@link #isImportantForAutofill()} for more
9075      * info about this mode.
9076      *
9077      * @return {@link #IMPORTANT_FOR_AUTOFILL_AUTO} by default, or value passed to
9078      * {@link #setImportantForAutofill(int)}.
9079      *
9080      * @attr ref android.R.styleable#View_importantForAutofill
9081      */
9082     @ViewDebug.ExportedProperty(mapping = {
9083             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_AUTO, to = "auto"),
9084             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES, to = "yes"),
9085             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO, to = "no"),
9086             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
9087                 to = "yesExcludeDescendants"),
9088             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
9089                 to = "noExcludeDescendants")})
9090     @InspectableProperty(enumMapping = {
9091             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_AUTO, name = "auto"),
9092             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_YES, name = "yes"),
9093             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_NO, name = "no"),
9094             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
9095                     name = "yesExcludeDescendants"),
9096             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
9097                     name = "noExcludeDescendants"),
9098     })
9099     public @AutofillImportance int getImportantForAutofill() {
9100         return (mPrivateFlags3
9101                 & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK) >> PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
9102     }
9103 
9104     /**
9105      * Sets the mode for determining whether this view is considered important for autofill.
9106      *
9107      * <p>The platform determines the importance for autofill automatically but you
9108      * can use this method to customize the behavior. For example:
9109      *
9110      * <ol>
9111      *   <li>When the view contents is irrelevant for autofill (for example, a text field used in a
9112      *       "Captcha" challenge), it should be {@link #IMPORTANT_FOR_AUTOFILL_NO}.
9113      *   <li>When both the view and its children are irrelevant for autofill (for example, the root
9114      *       view of an activity containing a spreadhseet editor), it should be
9115      *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
9116      *   <li>When the view content is relevant for autofill but its children aren't (for example,
9117      *       a credit card expiration date represented by a custom view that overrides the proper
9118      *       autofill methods and has 2 children representing the month and year), it should
9119      *       be {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}.
9120      * </ol>
9121      *
9122      * <p><b>Note:</b> Setting the mode as {@link #IMPORTANT_FOR_AUTOFILL_NO} or
9123      * {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS} does not guarantee the view (and its
9124      * children) will be always be considered not important; for example, when the user explicitly
9125      * makes an autofill request, all views are considered important. See
9126      * {@link #isImportantForAutofill()} for more details about how the View's importance for
9127      * autofill is used.
9128      *
9129      * @param mode {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, {@link #IMPORTANT_FOR_AUTOFILL_YES},
9130      * {@link #IMPORTANT_FOR_AUTOFILL_NO}, {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS},
9131      * or {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
9132      *
9133      * @attr ref android.R.styleable#View_importantForAutofill
9134      */
9135     public void setImportantForAutofill(@AutofillImportance int mode) {
9136         mPrivateFlags3 &= ~PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
9137         mPrivateFlags3 |= (mode << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT)
9138                 & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
9139     }
9140 
9141     /**
9142      * Hints the Android System whether the {@link android.app.assist.AssistStructure.ViewNode}
9143      * associated with this view is considered important for autofill purposes.
9144      *
9145      * <p>Generally speaking, a view is important for autofill if:
9146      * <ol>
9147      * <li>The view can be autofilled by an {@link android.service.autofill.AutofillService}.
9148      * <li>The view contents can help an {@link android.service.autofill.AutofillService}
9149      *     determine how other views can be autofilled.
9150      * <ol>
9151      *
9152      * <p>For example, view containers should typically return {@code false} for performance reasons
9153      * (since the important info is provided by their children), but if its properties have relevant
9154      * information (for example, a resource id called {@code credentials}, it should return
9155      * {@code true}. On the other hand, views representing labels or editable fields should
9156      * typically return {@code true}, but in some cases they could return {@code false}
9157      * (for example, if they're part of a "Captcha" mechanism).
9158      *
9159      * <p>The value returned by this method depends on the value returned by
9160      * {@link #getImportantForAutofill()}:
9161      *
9162      * <ol>
9163      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_YES} or
9164      *       {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}, then it returns {@code true}
9165      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_NO} or
9166      *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}, then it returns {@code false}
9167      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, then it uses some simple heuristics
9168      *       that can return {@code true} in some cases (like a container with a resource id),
9169      *       but {@code false} in most.
9170      *   <li>otherwise, it returns {@code false}.
9171      * </ol>
9172      *
9173      * <p>When a view is considered important for autofill:
9174      * <ul>
9175      *   <li>The view might automatically trigger an autofill request when focused on.
9176      *   <li>The contents of the view are included in the {@link ViewStructure} used in an autofill
9177      *       request.
9178      * </ul>
9179      *
9180      * <p>On the other hand, when a view is considered not important for autofill:
9181      * <ul>
9182      *   <li>The view never automatically triggers autofill requests, but it can trigger a manual
9183      *       request through {@link AutofillManager#requestAutofill(View)}.
9184      *   <li>The contents of the view are not included in the {@link ViewStructure} used in an
9185      *       autofill request, unless the request has the
9186      *       {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag.
9187      * </ul>
9188      *
9189      * @return whether the view is considered important for autofill.
9190      *
9191      * @see #setImportantForAutofill(int)
9192      * @see #IMPORTANT_FOR_AUTOFILL_AUTO
9193      * @see #IMPORTANT_FOR_AUTOFILL_YES
9194      * @see #IMPORTANT_FOR_AUTOFILL_NO
9195      * @see #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
9196      * @see #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
9197      * @see AutofillManager#requestAutofill(View)
9198      */
9199     public final boolean isImportantForAutofill() {
9200         // Check parent mode to ensure we're not hidden.
9201         ViewParent parent = mParent;
9202         while (parent instanceof View) {
9203             final int parentImportance = ((View) parent).getImportantForAutofill();
9204             if (parentImportance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
9205                     || parentImportance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS) {
9206                 if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
9207                     Log.v(AUTOFILL_LOG_TAG, "View (" +  this + ") is not important for autofill "
9208                             + "because parent " + parent + "'s importance is " + parentImportance);
9209                 }
9210                 return false;
9211             }
9212             parent = parent.getParent();
9213         }
9214 
9215         final int importance = getImportantForAutofill();
9216 
9217         // First, check the explicit states.
9218         if (importance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
9219                 || importance == IMPORTANT_FOR_AUTOFILL_YES) {
9220             return true;
9221         }
9222         if (importance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
9223                 || importance == IMPORTANT_FOR_AUTOFILL_NO) {
9224             if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
9225                 Log.v(AUTOFILL_LOG_TAG, "View (" +  this + ") is not important for autofill "
9226                         + "because its importance is " + importance);
9227             }
9228             return false;
9229         }
9230 
9231         // Then use some heuristics to handle AUTO.
9232         if (importance != IMPORTANT_FOR_AUTOFILL_AUTO) {
9233             Log.w(AUTOFILL_LOG_TAG, "invalid autofill importance (" + importance + " on view "
9234                     + this);
9235             return false;
9236         }
9237 
9238         // Always include views that have an explicit resource id.
9239         final int id = mID;
9240         if (id != NO_ID && !isViewIdGenerated(id)) {
9241             final Resources res = getResources();
9242             String entry = null;
9243             String pkg = null;
9244             try {
9245                 entry = res.getResourceEntryName(id);
9246                 pkg = res.getResourcePackageName(id);
9247             } catch (Resources.NotFoundException e) {
9248                 // ignore
9249             }
9250             if (entry != null && pkg != null && pkg.equals(mContext.getPackageName())) {
9251                 return true;
9252             }
9253         }
9254 
9255         // If the app developer explicitly set hints for it, it's important.
9256         if (getAutofillHints() != null) {
9257             return true;
9258         }
9259 
9260         // Otherwise, assume it's not important...
9261         return false;
9262     }
9263 
9264     /**
9265      * Gets the mode for determining whether this view is important for content capture.
9266      *
9267      * <p>See {@link #setImportantForContentCapture(int)} and
9268      * {@link #isImportantForContentCapture()} for more info about this mode.
9269      *
9270      * @return {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO} by default, or value passed to
9271      * {@link #setImportantForContentCapture(int)}.
9272      *
9273      * @attr ref android.R.styleable#View_importantForContentCapture
9274      *
9275      * @hide
9276      */
9277     @ViewDebug.ExportedProperty(mapping = {
9278             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_AUTO, to = "auto"),
9279             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_YES, to = "yes"),
9280             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_NO, to = "no"),
9281             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
9282                 to = "yesExcludeDescendants"),
9283             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS,
9284                 to = "noExcludeDescendants")})
9285 //    @InspectableProperty(enumMapping = {
9286 //            @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_AUTO, name = "auto"),
9287 //            @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_YES, name = "yes"),
9288 //            @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_NO, name = "no"),
9289 //            @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
9290 //                    name = "yesExcludeDescendants"),
9291 //            @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS,
9292 //                    name = "noExcludeDescendants"),
9293 //    })
9294     @TestApi
9295     public @ContentCaptureImportance int getImportantForContentCapture() {
9296         // NOTE: the important for content capture values were the first flags added and are set in
9297         // the rightmost position, so we don't need to shift them
9298         return mPrivateFlags4 & PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK;
9299     }
9300 
9301     /**
9302      * Sets the mode for determining whether this view is considered important for content capture.
9303      *
9304      * <p>The platform determines the importance for autofill automatically but you
9305      * can use this method to customize the behavior. Typically, a view that provides text should
9306      * be marked as {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES}.
9307      *
9308      * @param mode {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO},
9309      * {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES}, {@link #IMPORTANT_FOR_CONTENT_CAPTURE_NO},
9310      * {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS},
9311      * or {@link #IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS}.
9312      *
9313      * @attr ref android.R.styleable#View_importantForContentCapture
9314      *
9315      * @hide
9316      */
9317     @TestApi
9318     public void setImportantForContentCapture(@ContentCaptureImportance int mode) {
9319         // Reset first
9320         mPrivateFlags4 &= ~PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK;
9321         // Then set again
9322         // NOTE: the important for content capture values were the first flags added and are set in
9323         // the rightmost position, so we don't need to shift them
9324         mPrivateFlags4 |= (mode & PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK);
9325     }
9326 
9327     /**
9328      * Hints the Android System whether this view is considered important for content capture, based
9329      * on the value explicitly set by {@link #setImportantForContentCapture(int)} and heuristics
9330      * when it's {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO}.
9331      *
9332      * <p>See {@link ContentCaptureManager} for more info about content capture.
9333      *
9334      * @return whether the view is considered important for content capture.
9335      *
9336      * @see #setImportantForContentCapture(int)
9337      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO
9338      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_YES
9339      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_NO
9340      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
9341      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
9342      *
9343      * @hide
9344      */
9345     @TestApi
9346     public final boolean isImportantForContentCapture() {
9347         boolean isImportant;
9348         if ((mPrivateFlags4 & PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED) != 0) {
9349             isImportant = (mPrivateFlags4 & PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE) != 0;
9350             return isImportant;
9351         }
9352 
9353         isImportant = calculateIsImportantForContentCapture();
9354 
9355         mPrivateFlags4 &= ~PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
9356         if (isImportant) {
9357             mPrivateFlags4 |= PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
9358         }
9359         mPrivateFlags4 |= PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED;
9360         return isImportant;
9361     }
9362 
9363     /**
9364      * Calculates whether the flag is important for content capture so it can be used by
9365      * {@link #isImportantForContentCapture()} while the tree is traversed.
9366      */
9367     private boolean calculateIsImportantForContentCapture() {
9368         // Check parent mode to ensure we're important
9369         ViewParent parent = mParent;
9370         while (parent instanceof View) {
9371             final int parentImportance = ((View) parent).getImportantForContentCapture();
9372             if (parentImportance == IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
9373                     || parentImportance == IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS) {
9374                 if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
9375                     Log.v(CONTENT_CAPTURE_LOG_TAG, "View (" +  this + ") is not important for "
9376                             + "content capture because parent " + parent + "'s importance is "
9377                             + parentImportance);
9378                 }
9379                 return false;
9380             }
9381             parent = parent.getParent();
9382         }
9383 
9384         final int importance = getImportantForContentCapture();
9385 
9386         // First, check the explicit states.
9387         if (importance == IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
9388                 || importance == IMPORTANT_FOR_CONTENT_CAPTURE_YES) {
9389             return true;
9390         }
9391         if (importance == IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
9392                 || importance == IMPORTANT_FOR_CONTENT_CAPTURE_NO) {
9393             if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
9394                 Log.v(CONTENT_CAPTURE_LOG_TAG, "View (" +  this + ") is not important for content "
9395                         + "capture because its importance is " + importance);
9396             }
9397             return false;
9398         }
9399 
9400         // Then use some heuristics to handle AUTO.
9401         if (importance != IMPORTANT_FOR_CONTENT_CAPTURE_AUTO) {
9402             Log.w(CONTENT_CAPTURE_LOG_TAG, "invalid content capture importance (" + importance
9403                     + " on view " + this);
9404             return false;
9405         }
9406 
9407         // View group is important if at least one children also is
9408         if (this instanceof ViewGroup) {
9409             final ViewGroup group = (ViewGroup) this;
9410             for (int i = 0; i < group.getChildCount(); i++) {
9411                 final View child = group.getChildAt(i);
9412                 if (child.isImportantForContentCapture()) {
9413                     return true;
9414                 }
9415             }
9416         }
9417 
9418         // If the app developer explicitly set hints or autofill hintsfor it, it's important.
9419         if (getAutofillHints() != null) {
9420             return true;
9421         }
9422 
9423         // Otherwise, assume it's not important...
9424         return false;
9425     }
9426 
9427     /**
9428      * Helper used to notify the {@link ContentCaptureManager} when the view is removed or
9429      * added, based on whether it's laid out and visible, and without knowing if the parent removed
9430      * it from the view hierarchy.
9431      *
9432      * <p>This method is called from many places (visibility changed, view laid out, view attached
9433      * or detached to/from window, etc...) and hence must contain the logic to call the manager, as
9434      * described below:
9435      *
9436      * <ol>
9437      *   <li>It should only be called when content capture is enabled for the view.
9438      *   <li>It must call viewAppeared() before viewDisappeared()
9439      *   <li>viewAppearead() can only be called when the view is visible and laidout
9440      *   <li>It should not call the same event twice.
9441      * </ol>
9442      */
9443     private void notifyAppearedOrDisappearedForContentCaptureIfNeeded(boolean appeared) {
9444         AttachInfo ai = mAttachInfo;
9445         // Skip it while the view is being laided out for the first time
9446         if (ai != null && !ai.mReadyForContentCaptureUpdates) return;
9447 
9448         if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
9449             Trace.traceBegin(Trace.TRACE_TAG_VIEW,
9450                     "notifyContentCapture(" + appeared + ") for " + getClass().getSimpleName());
9451         }
9452         try {
9453             notifyAppearedOrDisappearedForContentCaptureIfNeededNoTrace(appeared);
9454         } finally {
9455             Trace.traceEnd(Trace.TRACE_TAG_VIEW);
9456         }
9457     }
9458 
9459     private void notifyAppearedOrDisappearedForContentCaptureIfNeededNoTrace(boolean appeared) {
9460         AttachInfo ai = mAttachInfo;
9461 
9462         // First check if context has client, so it saves a service lookup when it doesn't
9463         if (mContext.getContentCaptureOptions() == null) return;
9464 
9465         // Then check if it's enabled in the context...
9466         final ContentCaptureManager ccm = ai != null ? ai.getContentCaptureManager(mContext)
9467                 : mContext.getSystemService(ContentCaptureManager.class);
9468         if (ccm == null || !ccm.isContentCaptureEnabled()) return;
9469 
9470         // ... and finally at the view level
9471         // NOTE: isImportantForContentCapture() is more expensive than cm.isContentCaptureEnabled()
9472         if (!isImportantForContentCapture()) return;
9473 
9474         ContentCaptureSession session = getContentCaptureSession();
9475         if (session == null) return;
9476 
9477         if (appeared) {
9478             if (!isLaidOut() || getVisibility() != VISIBLE
9479                     || (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) != 0) {
9480                 if (DEBUG_CONTENT_CAPTURE) {
9481                     Log.v(CONTENT_CAPTURE_LOG_TAG, "Ignoring 'appeared' on " + this + ": laid="
9482                             + isLaidOut() + ", visibleToUser=" + isVisibleToUser()
9483                             + ", visible=" + (getVisibility() == VISIBLE)
9484                             + ": alreadyNotifiedAppeared=" + ((mPrivateFlags4
9485                                     & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) != 0)
9486                             + ", alreadyNotifiedDisappeared=" + ((mPrivateFlags4
9487                                     & PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED) != 0));
9488                 }
9489                 return;
9490             }
9491             setNotifiedContentCaptureAppeared();
9492 
9493             if (ai != null) {
9494                 ai.delayNotifyContentCaptureEvent(session, this, appeared);
9495             } else {
9496                 if (DEBUG_CONTENT_CAPTURE) {
9497                     Log.w(CONTENT_CAPTURE_LOG_TAG, "no AttachInfo on appeared for " + this);
9498                 }
9499             }
9500         } else {
9501             if ((mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) == 0
9502                     || (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED) != 0) {
9503                 if (DEBUG_CONTENT_CAPTURE) {
9504                     Log.v(CONTENT_CAPTURE_LOG_TAG, "Ignoring 'disappeared' on " + this + ": laid="
9505                             + isLaidOut() + ", visibleToUser=" + isVisibleToUser()
9506                             + ", visible=" + (getVisibility() == VISIBLE)
9507                             + ": alreadyNotifiedAppeared=" + ((mPrivateFlags4
9508                                     & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) != 0)
9509                             + ", alreadyNotifiedDisappeared=" + ((mPrivateFlags4
9510                                     & PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED) != 0));
9511                 }
9512                 return;
9513             }
9514             mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED;
9515             mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED;
9516 
9517             if (ai != null) {
9518                 ai.delayNotifyContentCaptureEvent(session, this, appeared);
9519             } else {
9520                 if (DEBUG_CONTENT_CAPTURE) {
9521                     Log.v(CONTENT_CAPTURE_LOG_TAG, "no AttachInfo on disappeared for " + this);
9522                 }
9523             }
9524         }
9525     }
9526 
9527     private void setNotifiedContentCaptureAppeared() {
9528         mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED;
9529         mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED;
9530     }
9531 
9532     /** @hide */
9533     protected boolean getNotifiedContentCaptureAppeared() {
9534         return (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) != 0;
9535     }
9536 
9537 
9538     /**
9539      * Sets the (optional) {@link ContentCaptureSession} associated with this view.
9540      *
9541      * <p>This method should be called when you need to associate a {@link ContentCaptureContext} to
9542      * the content capture events associated with this view or its view hierarchy (if it's a
9543      * {@link ViewGroup}).
9544      *
9545      * <p>For example, if your activity is associated with a web domain, first you would need to
9546      * set the context for the main DOM:
9547      *
9548      * <pre>
9549      *   ContentCaptureSession mainSession = rootView.getContentCaptureSession();
9550      *   mainSession.setContentCaptureContext(ContentCaptureContext.forLocusId(Uri.parse(myUrl));
9551      * </pre>
9552      *
9553      * <p>Then if the page had an {@code IFRAME}, you would create a new session for it:
9554      *
9555      * <pre>
9556      *   ContentCaptureSession iframeSession = mainSession.createContentCaptureSession(
9557      *       ContentCaptureContext.forLocusId(Uri.parse(iframeUrl)));
9558      *   iframeView.setContentCaptureSession(iframeSession);
9559      * </pre>
9560      *
9561      * @param contentCaptureSession a session created by
9562      * {@link ContentCaptureSession#createContentCaptureSession(
9563      *        android.view.contentcapture.ContentCaptureContext)}.
9564      */
9565     public void setContentCaptureSession(@Nullable ContentCaptureSession contentCaptureSession) {
9566         mContentCaptureSession = contentCaptureSession;
9567     }
9568 
9569     /**
9570      * Gets the session used to notify content capture events.
9571      *
9572      * @return session explicitly set by {@link #setContentCaptureSession(ContentCaptureSession)},
9573      * inherited by ancestors, default session or {@code null} if content capture is disabled for
9574      * this view.
9575      */
9576     @Nullable
9577     public final ContentCaptureSession getContentCaptureSession() {
9578         if (mCachedContentCaptureSession != null) {
9579             return mCachedContentCaptureSession;
9580         }
9581 
9582         mCachedContentCaptureSession = getAndCacheContentCaptureSession();
9583         return mCachedContentCaptureSession;
9584     }
9585 
9586     @Nullable
9587     private ContentCaptureSession getAndCacheContentCaptureSession() {
9588         // First try the session explicitly set by setContentCaptureSession()
9589         if (mContentCaptureSession != null) return mContentCaptureSession;
9590 
9591         // Then the session explicitly set in an ancestor
9592         ContentCaptureSession session = null;
9593         if (mParent instanceof View) {
9594             session = ((View) mParent).getContentCaptureSession();
9595         }
9596 
9597         // Finally, if no session was explicitly set, use the context's default session.
9598         if (session == null) {
9599             final ContentCaptureManager ccm = mContext
9600                     .getSystemService(ContentCaptureManager.class);
9601             return ccm == null ? null : ccm.getMainContentCaptureSession();
9602         }
9603         return session;
9604     }
9605 
9606     @Nullable
9607     private AutofillManager getAutofillManager() {
9608         return mContext.getSystemService(AutofillManager.class);
9609     }
9610 
9611     private boolean isAutofillable() {
9612         if (getAutofillType() == AUTOFILL_TYPE_NONE) return false;
9613 
9614         if (!isImportantForAutofill()) {
9615             // View is not important for "regular" autofill, so we must check if Augmented Autofill
9616             // is enabled for the activity
9617             final AutofillOptions options = mContext.getAutofillOptions();
9618             if (options == null || !options.isAugmentedAutofillEnabled(mContext)) {
9619                 return false;
9620             }
9621             final AutofillManager afm = getAutofillManager();
9622             if (afm == null) return false;
9623             afm.notifyViewEnteredForAugmentedAutofill(this);
9624         }
9625 
9626         return getAutofillViewId() > LAST_APP_AUTOFILL_ID;
9627     }
9628 
9629     /** @hide */
9630     public boolean canNotifyAutofillEnterExitEvent() {
9631         return isAutofillable() && isAttachedToWindow();
9632     }
9633 
9634     private void populateVirtualStructure(ViewStructure structure,
9635             AccessibilityNodeProvider provider, AccessibilityNodeInfo info,
9636             boolean forAutofill) {
9637         structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
9638                 null, null, info.getViewIdResourceName());
9639         Rect rect = structure.getTempRect();
9640         info.getBoundsInParent(rect);
9641         structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
9642         structure.setVisibility(VISIBLE);
9643         structure.setEnabled(info.isEnabled());
9644         if (info.isClickable()) {
9645             structure.setClickable(true);
9646         }
9647         if (info.isFocusable()) {
9648             structure.setFocusable(true);
9649         }
9650         if (info.isFocused()) {
9651             structure.setFocused(true);
9652         }
9653         if (info.isAccessibilityFocused()) {
9654             structure.setAccessibilityFocused(true);
9655         }
9656         if (info.isSelected()) {
9657             structure.setSelected(true);
9658         }
9659         if (info.isLongClickable()) {
9660             structure.setLongClickable(true);
9661         }
9662         if (info.isCheckable()) {
9663             structure.setCheckable(true);
9664             if (info.isChecked()) {
9665                 structure.setChecked(true);
9666             }
9667         }
9668         if (info.isContextClickable()) {
9669             structure.setContextClickable(true);
9670         }
9671         if (forAutofill) {
9672             structure.setAutofillId(new AutofillId(getAutofillId(),
9673                     AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId())));
9674         }
9675         CharSequence cname = info.getClassName();
9676         structure.setClassName(cname != null ? cname.toString() : null);
9677         structure.setContentDescription(info.getContentDescription());
9678         if (forAutofill) {
9679             final int maxTextLength = info.getMaxTextLength();
9680             if (maxTextLength != -1) {
9681                 structure.setMaxTextLength(maxTextLength);
9682             }
9683             structure.setHint(info.getHintText());
9684         }
9685         CharSequence text = info.getText();
9686         boolean hasText = text != null || info.getError() != null;
9687         if (hasText) {
9688             structure.setText(text, info.getTextSelectionStart(), info.getTextSelectionEnd());
9689         }
9690         if (forAutofill) {
9691             if (info.isEditable()) {
9692                 structure.setDataIsSensitive(true);
9693                 if (hasText) {
9694                     structure.setAutofillType(AUTOFILL_TYPE_TEXT);
9695                     structure.setAutofillValue(AutofillValue.forText(text));
9696                 }
9697                 int inputType = info.getInputType();
9698                 if (inputType == 0 && info.isPassword()) {
9699                     inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD;
9700                 }
9701                 structure.setInputType(inputType);
9702             } else {
9703                 structure.setDataIsSensitive(false);
9704             }
9705         }
9706         final int NCHILDREN = info.getChildCount();
9707         if (NCHILDREN > 0) {
9708             structure.setChildCount(NCHILDREN);
9709             for (int i=0; i<NCHILDREN; i++) {
9710                 if (AccessibilityNodeInfo.getVirtualDescendantId(info.getChildNodeIds().get(i))
9711                         == AccessibilityNodeProvider.HOST_VIEW_ID) {
9712                     Log.e(VIEW_LOG_TAG, "Virtual view pointing to its host. Ignoring");
9713                     continue;
9714                 }
9715                 AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
9716                         AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
9717                 ViewStructure child = structure.newChild(i);
9718                 populateVirtualStructure(child, provider, cinfo, forAutofill);
9719                 cinfo.recycle();
9720             }
9721         }
9722     }
9723 
9724     /**
9725      * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
9726      * implementation calls {@link #onProvideStructure} and
9727      * {@link #onProvideVirtualStructure}.
9728      */
9729     public void dispatchProvideStructure(ViewStructure structure) {
9730         dispatchProvideStructure(structure, VIEW_STRUCTURE_FOR_ASSIST, /* flags= */ 0);
9731     }
9732 
9733     /**
9734      * Dispatches creation of a {@link ViewStructure}s for autofill purposes down the hierarchy,
9735      * when an Assist structure is being created as part of an autofill request.
9736      *
9737      * <p>The default implementation does the following:
9738      * <ul>
9739      *   <li>Sets the {@link AutofillId} in the structure.
9740      *   <li>Calls {@link #onProvideAutofillStructure(ViewStructure, int)}.
9741      *   <li>Calls {@link #onProvideAutofillVirtualStructure(ViewStructure, int)}.
9742      * </ul>
9743      *
9744      * <p>Typically, this method should only be overridden by subclasses that provide a view
9745      * hierarchy (such as {@link ViewGroup}) - other classes should override
9746      * {@link #onProvideAutofillStructure(ViewStructure, int)} or
9747      * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} instead.
9748      *
9749      * <p>When overridden, it must:
9750      *
9751      * <ul>
9752      *   <li>Either call
9753      *       {@code super.dispatchProvideAutofillStructure(structure, flags)} or explicitly
9754      *       set the {@link AutofillId} in the structure (for example, by calling
9755      *       {@code structure.setAutofillId(getAutofillId())}).
9756      *   <li>Decide how to handle the {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag - when
9757      *       set, all views in the structure should be considered important for autofill,
9758      *       regardless of what {@link #isImportantForAutofill()} returns. We encourage you to
9759      *       respect this flag to provide a better user experience - this flag is typically used
9760      *       when an user explicitly requested autofill. If the flag is not set,
9761      *       then only views marked as important for autofill should be included in the
9762      *       structure - skipping non-important views optimizes the overall autofill performance.
9763      * </ul>
9764      *
9765      * @param structure fill in with structured view data for autofill purposes.
9766      * @param flags optional flags.
9767      *
9768      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
9769      */
9770     public void dispatchProvideAutofillStructure(@NonNull ViewStructure structure,
9771             @AutofillFlags int flags) {
9772         dispatchProvideStructure(structure, VIEW_STRUCTURE_FOR_AUTOFILL, flags);
9773     }
9774 
9775     private void dispatchProvideStructure(@NonNull ViewStructure structure,
9776             @ViewStructureType int viewFor, @AutofillFlags int flags) {
9777         if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
9778             structure.setAutofillId(getAutofillId());
9779             onProvideAutofillStructure(structure, flags);
9780             onProvideAutofillVirtualStructure(structure, flags);
9781         } else if (!isAssistBlocked()) {
9782             onProvideStructure(structure);
9783             onProvideVirtualStructure(structure);
9784         } else {
9785             structure.setClassName(getAccessibilityClassName().toString());
9786             structure.setAssistBlocked(true);
9787         }
9788     }
9789 
9790     /**
9791      * Dispatches the initial content capture events for a view structure.
9792      *
9793      * @hide
9794      */
9795     public void dispatchInitialProvideContentCaptureStructure() {
9796         AttachInfo ai = mAttachInfo;
9797         if (ai == null) {
9798             Log.w(CONTENT_CAPTURE_LOG_TAG,
9799                     "dispatchProvideContentCaptureStructure(): no AttachInfo for " + this);
9800             return;
9801         }
9802         ContentCaptureManager ccm = ai.mContentCaptureManager;
9803         if (ccm == null) {
9804             Log.w(CONTENT_CAPTURE_LOG_TAG, "dispatchProvideContentCaptureStructure(): "
9805                     + "no ContentCaptureManager for " + this);
9806             return;
9807         }
9808 
9809         // We must set it before checkign if the view itself is important, because it might
9810         // initially not be (for example, if it's empty), although that might change later (for
9811         // example, if important views are added)
9812         ai.mReadyForContentCaptureUpdates = true;
9813 
9814         if (!isImportantForContentCapture()) {
9815             if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.DEBUG)) {
9816                 Log.d(CONTENT_CAPTURE_LOG_TAG,
9817                         "dispatchProvideContentCaptureStructure(): decorView is not important");
9818             }
9819             return;
9820         }
9821 
9822         ai.mContentCaptureManager = ccm;
9823 
9824         ContentCaptureSession session = getContentCaptureSession();
9825         if (session == null) {
9826             if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.DEBUG)) {
9827                 Log.d(CONTENT_CAPTURE_LOG_TAG,
9828                         "dispatchProvideContentCaptureStructure(): no session for " + this);
9829             }
9830             return;
9831         }
9832 
9833         session.internalNotifyViewTreeEvent(/* started= */ true);
9834         try {
9835             dispatchProvideContentCaptureStructure();
9836         } finally {
9837             session.internalNotifyViewTreeEvent(/* started= */ false);
9838         }
9839     }
9840 
9841     /** @hide */
9842     void dispatchProvideContentCaptureStructure() {
9843         ContentCaptureSession session = getContentCaptureSession();
9844         if (session != null) {
9845             ViewStructure structure = session.newViewStructure(this);
9846             onProvideContentCaptureStructure(structure, /* flags= */ 0);
9847             setNotifiedContentCaptureAppeared();
9848             session.notifyViewAppeared(structure);
9849         }
9850     }
9851 
9852     /**
9853      * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
9854      *
9855      * Note: Called from the default {@link AccessibilityDelegate}.
9856      *
9857      * @hide
9858      */
9859     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
9860         if (mAttachInfo == null) {
9861             return;
9862         }
9863 
9864         Rect bounds = mAttachInfo.mTmpInvalRect;
9865 
9866         getDrawingRect(bounds);
9867         info.setBoundsInParent(bounds);
9868 
9869         getBoundsOnScreen(bounds, true);
9870         info.setBoundsInScreen(bounds);
9871 
9872         ViewParent parent = getParentForAccessibility();
9873         if (parent instanceof View) {
9874             info.setParent((View) parent);
9875         }
9876 
9877         if (mID != View.NO_ID) {
9878             View rootView = getRootView();
9879             if (rootView == null) {
9880                 rootView = this;
9881             }
9882 
9883             View label = rootView.findLabelForView(this, mID);
9884             if (label != null) {
9885                 info.setLabeledBy(label);
9886             }
9887 
9888             if ((mAttachInfo.mAccessibilityFetchFlags
9889                     & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
9890                     && Resources.resourceHasPackage(mID)) {
9891                 try {
9892                     String viewId = getResources().getResourceName(mID);
9893                     info.setViewIdResourceName(viewId);
9894                 } catch (Resources.NotFoundException nfe) {
9895                     /* ignore */
9896                 }
9897             }
9898         }
9899 
9900         if (mLabelForId != View.NO_ID) {
9901             View rootView = getRootView();
9902             if (rootView == null) {
9903                 rootView = this;
9904             }
9905             View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
9906             if (labeled != null) {
9907                 info.setLabelFor(labeled);
9908             }
9909         }
9910 
9911         if (mAccessibilityTraversalBeforeId != View.NO_ID) {
9912             View rootView = getRootView();
9913             if (rootView == null) {
9914                 rootView = this;
9915             }
9916             View next = rootView.findViewInsideOutShouldExist(this,
9917                     mAccessibilityTraversalBeforeId);
9918             if (next != null && next.includeForAccessibility()) {
9919                 info.setTraversalBefore(next);
9920             }
9921         }
9922 
9923         if (mAccessibilityTraversalAfterId != View.NO_ID) {
9924             View rootView = getRootView();
9925             if (rootView == null) {
9926                 rootView = this;
9927             }
9928             View next = rootView.findViewInsideOutShouldExist(this,
9929                     mAccessibilityTraversalAfterId);
9930             if (next != null && next.includeForAccessibility()) {
9931                 info.setTraversalAfter(next);
9932             }
9933         }
9934 
9935         info.setVisibleToUser(isVisibleToUser());
9936 
9937         info.setImportantForAccessibility(isImportantForAccessibility());
9938         info.setPackageName(mContext.getPackageName());
9939         info.setClassName(getAccessibilityClassName());
9940         info.setContentDescription(getContentDescription());
9941 
9942         info.setEnabled(isEnabled());
9943         info.setClickable(isClickable());
9944         info.setFocusable(isFocusable());
9945         info.setScreenReaderFocusable(isScreenReaderFocusable());
9946         info.setFocused(isFocused());
9947         info.setAccessibilityFocused(isAccessibilityFocused());
9948         info.setSelected(isSelected());
9949         info.setLongClickable(isLongClickable());
9950         info.setContextClickable(isContextClickable());
9951         info.setLiveRegion(getAccessibilityLiveRegion());
9952         if ((mTooltipInfo != null) && (mTooltipInfo.mTooltipText != null)) {
9953             info.setTooltipText(mTooltipInfo.mTooltipText);
9954             info.addAction((mTooltipInfo.mTooltipPopup == null)
9955                     ? AccessibilityNodeInfo.AccessibilityAction.ACTION_SHOW_TOOLTIP
9956                     : AccessibilityNodeInfo.AccessibilityAction.ACTION_HIDE_TOOLTIP);
9957         }
9958 
9959         // TODO: These make sense only if we are in an AdapterView but all
9960         // views can be selected. Maybe from accessibility perspective
9961         // we should report as selectable view in an AdapterView.
9962         info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
9963         info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
9964 
9965         if (isFocusable()) {
9966             if (isFocused()) {
9967                 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
9968             } else {
9969                 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
9970             }
9971         }
9972 
9973         if (!isAccessibilityFocused()) {
9974             info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
9975         } else {
9976             info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
9977         }
9978 
9979         if (isClickable() && isEnabled()) {
9980             info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
9981         }
9982 
9983         if (isLongClickable() && isEnabled()) {
9984             info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
9985         }
9986 
9987         if (isContextClickable() && isEnabled()) {
9988             info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
9989         }
9990 
9991         CharSequence text = getIterableTextForAccessibility();
9992         if (text != null && text.length() > 0) {
9993             info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
9994 
9995             info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
9996             info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
9997             info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
9998             info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
9999                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
10000                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
10001         }
10002 
10003         info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
10004         populateAccessibilityNodeInfoDrawingOrderInParent(info);
10005         info.setPaneTitle(mAccessibilityPaneTitle);
10006         info.setHeading(isAccessibilityHeading());
10007 
10008         if (mTouchDelegate != null) {
10009             info.setTouchDelegateInfo(mTouchDelegate.getTouchDelegateInfo());
10010         }
10011     }
10012 
10013     /**
10014      * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
10015      * additional data.
10016      * <p>
10017      * This method only needs overloading if the node is marked as having extra data available.
10018      * </p>
10019      *
10020      * @param info The info to which to add the extra data. Never {@code null}.
10021      * @param extraDataKey A key specifying the type of extra data to add to the info. The
10022      *                     extra data should be added to the {@link Bundle} returned by
10023      *                     the info's {@link AccessibilityNodeInfo#getExtras} method. Never
10024      *                     {@code null}.
10025      * @param arguments A {@link Bundle} holding any arguments relevant for this request. May be
10026      *                  {@code null} if the service provided no arguments.
10027      *
10028      * @see AccessibilityNodeInfo#setAvailableExtraData(List)
10029      */
10030     public void addExtraDataToAccessibilityNodeInfo(
10031             @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
10032             @Nullable Bundle arguments) {
10033     }
10034 
10035     /**
10036      * Determine the order in which this view will be drawn relative to its siblings for a11y
10037      *
10038      * @param info The info whose drawing order should be populated
10039      */
10040     private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
10041         /*
10042          * If the view's bounds haven't been set yet, layout has not completed. In that situation,
10043          * drawing order may not be well-defined, and some Views with custom drawing order may
10044          * not be initialized sufficiently to respond properly getChildDrawingOrder.
10045          */
10046         if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
10047             info.setDrawingOrder(0);
10048             return;
10049         }
10050         int drawingOrderInParent = 1;
10051         // Iterate up the hierarchy if parents are not important for a11y
10052         View viewAtDrawingLevel = this;
10053         final ViewParent parent = getParentForAccessibility();
10054         while (viewAtDrawingLevel != parent) {
10055             final ViewParent currentParent = viewAtDrawingLevel.getParent();
10056             if (!(currentParent instanceof ViewGroup)) {
10057                 // Should only happen for the Decor
10058                 drawingOrderInParent = 0;
10059                 break;
10060             } else {
10061                 final ViewGroup parentGroup = (ViewGroup) currentParent;
10062                 final int childCount = parentGroup.getChildCount();
10063                 if (childCount > 1) {
10064                     List<View> preorderedList = parentGroup.buildOrderedChildList();
10065                     if (preorderedList != null) {
10066                         final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
10067                         for (int i = 0; i < childDrawIndex; i++) {
10068                             drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
10069                         }
10070                     } else {
10071                         final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
10072                         final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
10073                         final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
10074                                 .getChildDrawingOrder(childCount, childIndex) : childIndex;
10075                         final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
10076                         if (childDrawIndex != 0) {
10077                             for (int i = 0; i < numChildrenToIterate; i++) {
10078                                 final int otherDrawIndex = (customOrder ?
10079                                         parentGroup.getChildDrawingOrder(childCount, i) : i);
10080                                 if (otherDrawIndex < childDrawIndex) {
10081                                     drawingOrderInParent +=
10082                                             numViewsForAccessibility(parentGroup.getChildAt(i));
10083                                 }
10084                             }
10085                         }
10086                     }
10087                 }
10088             }
10089             viewAtDrawingLevel = (View) currentParent;
10090         }
10091         info.setDrawingOrder(drawingOrderInParent);
10092     }
10093 
10094     private static int numViewsForAccessibility(View view) {
10095         if (view != null) {
10096             if (view.includeForAccessibility()) {
10097                 return 1;
10098             } else if (view instanceof ViewGroup) {
10099                 return ((ViewGroup) view).getNumChildrenForAccessibility();
10100             }
10101         }
10102         return 0;
10103     }
10104 
10105     private View findLabelForView(View view, int labeledId) {
10106         if (mMatchLabelForPredicate == null) {
10107             mMatchLabelForPredicate = new MatchLabelForPredicate();
10108         }
10109         mMatchLabelForPredicate.mLabeledId = labeledId;
10110         return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
10111     }
10112 
10113     /**
10114      * Computes whether this virtual autofill view is visible to the user.
10115      *
10116      * <p><b>Note: </b>By default it returns {@code true}, but views providing a virtual hierarchy
10117      * view must override it.
10118      *
10119      * @return Whether the view is visible on the screen.
10120      */
10121     public boolean isVisibleToUserForAutofill(int virtualId) {
10122         if (mContext.isAutofillCompatibilityEnabled()) {
10123             final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
10124             if (provider != null) {
10125                 final AccessibilityNodeInfo node = provider.createAccessibilityNodeInfo(virtualId);
10126                 if (node != null) {
10127                     return node.isVisibleToUser();
10128                 }
10129                 // if node is null, assume it's not visible anymore
10130             } else {
10131                 Log.w(VIEW_LOG_TAG, "isVisibleToUserForAutofill(" + virtualId + "): no provider");
10132             }
10133             return false;
10134         }
10135         return true;
10136     }
10137 
10138     /**
10139      * Computes whether this view is visible to the user. Such a view is
10140      * attached, visible, all its predecessors are visible, it is not clipped
10141      * entirely by its predecessors, and has an alpha greater than zero.
10142      *
10143      * @return Whether the view is visible on the screen.
10144      *
10145      * @hide
10146      */
10147     @UnsupportedAppUsage
10148     public boolean isVisibleToUser() {
10149         return isVisibleToUser(null);
10150     }
10151 
10152     /**
10153      * Computes whether the given portion of this view is visible to the user.
10154      * Such a view is attached, visible, all its predecessors are visible,
10155      * has an alpha greater than zero, and the specified portion is not
10156      * clipped entirely by its predecessors.
10157      *
10158      * @param boundInView the portion of the view to test; coordinates should be relative; may be
10159      *                    <code>null</code>, and the entire view will be tested in this case.
10160      *                    When <code>true</code> is returned by the function, the actual visible
10161      *                    region will be stored in this parameter; that is, if boundInView is fully
10162      *                    contained within the view, no modification will be made, otherwise regions
10163      *                    outside of the visible area of the view will be clipped.
10164      *
10165      * @return Whether the specified portion of the view is visible on the screen.
10166      *
10167      * @hide
10168      */
10169     @UnsupportedAppUsage
10170     protected boolean isVisibleToUser(Rect boundInView) {
10171         if (mAttachInfo != null) {
10172             // Attached to invisible window means this view is not visible.
10173             if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
10174                 return false;
10175             }
10176             // An invisible predecessor or one with alpha zero means
10177             // that this view is not visible to the user.
10178             Object current = this;
10179             while (current instanceof View) {
10180                 View view = (View) current;
10181                 // We have attach info so this view is attached and there is no
10182                 // need to check whether we reach to ViewRootImpl on the way up.
10183                 if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
10184                         view.getVisibility() != VISIBLE) {
10185                     return false;
10186                 }
10187                 current = view.mParent;
10188             }
10189             // Check if the view is entirely covered by its predecessors.
10190             Rect visibleRect = mAttachInfo.mTmpInvalRect;
10191             Point offset = mAttachInfo.mPoint;
10192             if (!getGlobalVisibleRect(visibleRect, offset)) {
10193                 return false;
10194             }
10195             // Check if the visible portion intersects the rectangle of interest.
10196             if (boundInView != null) {
10197                 visibleRect.offset(-offset.x, -offset.y);
10198                 return boundInView.intersect(visibleRect);
10199             }
10200             return true;
10201         }
10202         return false;
10203     }
10204 
10205     /**
10206      * Returns the delegate for implementing accessibility support via
10207      * composition. For more details see {@link AccessibilityDelegate}.
10208      *
10209      * @return The delegate, or null if none set.
10210      */
10211     public AccessibilityDelegate getAccessibilityDelegate() {
10212         return mAccessibilityDelegate;
10213     }
10214 
10215     /**
10216      * Sets a delegate for implementing accessibility support via composition
10217      * (as opposed to inheritance). For more details, see
10218      * {@link AccessibilityDelegate}.
10219      * <p>
10220      * <strong>Note:</strong> On platform versions prior to
10221      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
10222      * views in the {@code android.widget.*} package are called <i>before</i>
10223      * host methods. This prevents certain properties such as class name from
10224      * being modified by overriding
10225      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
10226      * as any changes will be overwritten by the host class.
10227      * <p>
10228      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
10229      * methods are called <i>after</i> host methods, which all properties to be
10230      * modified without being overwritten by the host class.
10231      *
10232      * @param delegate the object to which accessibility method calls should be
10233      *                 delegated
10234      * @see AccessibilityDelegate
10235      */
10236     public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
10237         mAccessibilityDelegate = delegate;
10238     }
10239 
10240     /**
10241      * Gets the provider for managing a virtual view hierarchy rooted at this View
10242      * and reported to {@link android.accessibilityservice.AccessibilityService}s
10243      * that explore the window content.
10244      * <p>
10245      * If this method returns an instance, this instance is responsible for managing
10246      * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
10247      * View including the one representing the View itself. Similarly the returned
10248      * instance is responsible for performing accessibility actions on any virtual
10249      * view or the root view itself.
10250      * </p>
10251      * <p>
10252      * If an {@link AccessibilityDelegate} has been specified via calling
10253      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
10254      * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
10255      * is responsible for handling this call.
10256      * </p>
10257      *
10258      * @return The provider.
10259      *
10260      * @see AccessibilityNodeProvider
10261      */
10262     public AccessibilityNodeProvider getAccessibilityNodeProvider() {
10263         if (mAccessibilityDelegate != null) {
10264             return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
10265         } else {
10266             return null;
10267         }
10268     }
10269 
10270     /**
10271      * Gets the unique identifier of this view on the screen for accessibility purposes.
10272      *
10273      * @return The view accessibility id.
10274      *
10275      * @hide
10276      */
10277     @UnsupportedAppUsage
10278     public int getAccessibilityViewId() {
10279         if (mAccessibilityViewId == NO_ID) {
10280             mAccessibilityViewId = sNextAccessibilityViewId++;
10281         }
10282         return mAccessibilityViewId;
10283     }
10284 
10285     /**
10286      * Gets the unique identifier of this view on the screen for autofill purposes.
10287      *
10288      * @return The view autofill id.
10289      *
10290      * @hide
10291      */
10292     public int getAutofillViewId() {
10293         if (mAutofillViewId == NO_ID) {
10294             mAutofillViewId = mContext.getNextAutofillId();
10295         }
10296         return mAutofillViewId;
10297     }
10298 
10299     /**
10300      * Gets the unique identifier of the window in which this View resides.
10301      *
10302      * @return The window accessibility id.
10303      *
10304      * @hide
10305      */
10306     public int getAccessibilityWindowId() {
10307         return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
10308                 : AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
10309     }
10310 
10311     /**
10312      * Returns the {@link View}'s content description.
10313      * <p>
10314      * <strong>Note:</strong> Do not override this method, as it will have no
10315      * effect on the content description presented to accessibility services.
10316      * You must call {@link #setContentDescription(CharSequence)} to modify the
10317      * content description.
10318      *
10319      * @return the content description
10320      * @see #setContentDescription(CharSequence)
10321      * @attr ref android.R.styleable#View_contentDescription
10322      */
10323     @ViewDebug.ExportedProperty(category = "accessibility")
10324     @InspectableProperty
10325     public CharSequence getContentDescription() {
10326         return mContentDescription;
10327     }
10328 
10329     /**
10330      * Sets the {@link View}'s content description.
10331      * <p>
10332      * A content description briefly describes the view and is primarily used
10333      * for accessibility support to determine how a view should be presented to
10334      * the user. In the case of a view with no textual representation, such as
10335      * {@link android.widget.ImageButton}, a useful content description
10336      * explains what the view does. For example, an image button with a phone
10337      * icon that is used to place a call may use "Call" as its content
10338      * description. An image of a floppy disk that is used to save a file may
10339      * use "Save".
10340      *
10341      * @param contentDescription The content description.
10342      * @see #getContentDescription()
10343      * @attr ref android.R.styleable#View_contentDescription
10344      */
10345     @RemotableViewMethod
10346     public void setContentDescription(CharSequence contentDescription) {
10347         if (mContentDescription == null) {
10348             if (contentDescription == null) {
10349                 return;
10350             }
10351         } else if (mContentDescription.equals(contentDescription)) {
10352             return;
10353         }
10354         mContentDescription = contentDescription;
10355         final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
10356         if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
10357             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
10358             notifySubtreeAccessibilityStateChangedIfNeeded();
10359         } else {
10360             notifyViewAccessibilityStateChangedIfNeeded(
10361                     AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
10362         }
10363     }
10364 
10365     /**
10366      * Sets the id of a view before which this one is visited in accessibility traversal.
10367      * A screen-reader must visit the content of this view before the content of the one
10368      * it precedes. For example, if view B is set to be before view A, then a screen-reader
10369      * will traverse the entire content of B before traversing the entire content of A,
10370      * regardles of what traversal strategy it is using.
10371      * <p>
10372      * Views that do not have specified before/after relationships are traversed in order
10373      * determined by the screen-reader.
10374      * </p>
10375      * <p>
10376      * Setting that this view is before a view that is not important for accessibility
10377      * or if this view is not important for accessibility will have no effect as the
10378      * screen-reader is not aware of unimportant views.
10379      * </p>
10380      *
10381      * @param beforeId The id of a view this one precedes in accessibility traversal.
10382      *
10383      * @attr ref android.R.styleable#View_accessibilityTraversalBefore
10384      *
10385      * @see #setImportantForAccessibility(int)
10386      */
10387     @RemotableViewMethod
10388     public void setAccessibilityTraversalBefore(@IdRes int beforeId) {
10389         if (mAccessibilityTraversalBeforeId == beforeId) {
10390             return;
10391         }
10392         mAccessibilityTraversalBeforeId = beforeId;
10393         notifyViewAccessibilityStateChangedIfNeeded(
10394                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10395     }
10396 
10397     /**
10398      * Gets the id of a view before which this one is visited in accessibility traversal.
10399      *
10400      * @return The id of a view this one precedes in accessibility traversal if
10401      *         specified, otherwise {@link #NO_ID}.
10402      *
10403      * @see #setAccessibilityTraversalBefore(int)
10404      */
10405     @IdRes
10406     @InspectableProperty
10407     public int getAccessibilityTraversalBefore() {
10408         return mAccessibilityTraversalBeforeId;
10409     }
10410 
10411     /**
10412      * Sets the id of a view after which this one is visited in accessibility traversal.
10413      * A screen-reader must visit the content of the other view before the content of this
10414      * one. For example, if view B is set to be after view A, then a screen-reader
10415      * will traverse the entire content of A before traversing the entire content of B,
10416      * regardles of what traversal strategy it is using.
10417      * <p>
10418      * Views that do not have specified before/after relationships are traversed in order
10419      * determined by the screen-reader.
10420      * </p>
10421      * <p>
10422      * Setting that this view is after a view that is not important for accessibility
10423      * or if this view is not important for accessibility will have no effect as the
10424      * screen-reader is not aware of unimportant views.
10425      * </p>
10426      *
10427      * @param afterId The id of a view this one succedees in accessibility traversal.
10428      *
10429      * @attr ref android.R.styleable#View_accessibilityTraversalAfter
10430      *
10431      * @see #setImportantForAccessibility(int)
10432      */
10433     @RemotableViewMethod
10434     public void setAccessibilityTraversalAfter(@IdRes int afterId) {
10435         if (mAccessibilityTraversalAfterId == afterId) {
10436             return;
10437         }
10438         mAccessibilityTraversalAfterId = afterId;
10439         notifyViewAccessibilityStateChangedIfNeeded(
10440                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10441     }
10442 
10443     /**
10444      * Gets the id of a view after which this one is visited in accessibility traversal.
10445      *
10446      * @return The id of a view this one succeedes in accessibility traversal if
10447      *         specified, otherwise {@link #NO_ID}.
10448      *
10449      * @see #setAccessibilityTraversalAfter(int)
10450      */
10451     @IdRes
10452     @InspectableProperty
10453     public int getAccessibilityTraversalAfter() {
10454         return mAccessibilityTraversalAfterId;
10455     }
10456 
10457     /**
10458      * Gets the id of a view for which this view serves as a label for
10459      * accessibility purposes.
10460      *
10461      * @return The labeled view id.
10462      */
10463     @IdRes
10464     @ViewDebug.ExportedProperty(category = "accessibility")
10465     @InspectableProperty
10466     public int getLabelFor() {
10467         return mLabelForId;
10468     }
10469 
10470     /**
10471      * Sets the id of a view for which this view serves as a label for
10472      * accessibility purposes.
10473      *
10474      * @param id The labeled view id.
10475      */
10476     @RemotableViewMethod
10477     public void setLabelFor(@IdRes int id) {
10478         if (mLabelForId == id) {
10479             return;
10480         }
10481         mLabelForId = id;
10482         if (mLabelForId != View.NO_ID
10483                 && mID == View.NO_ID) {
10484             mID = generateViewId();
10485         }
10486         notifyViewAccessibilityStateChangedIfNeeded(
10487                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10488     }
10489 
10490     /**
10491      * Invoked whenever this view loses focus, either by losing window focus or by losing
10492      * focus within its window. This method can be used to clear any state tied to the
10493      * focus. For instance, if a button is held pressed with the trackball and the window
10494      * loses focus, this method can be used to cancel the press.
10495      *
10496      * Subclasses of View overriding this method should always call super.onFocusLost().
10497      *
10498      * @see #onFocusChanged(boolean, int, android.graphics.Rect)
10499      * @see #onWindowFocusChanged(boolean)
10500      *
10501      * @hide pending API council approval
10502      */
10503     @CallSuper
10504     @UnsupportedAppUsage
10505     protected void onFocusLost() {
10506         resetPressedState();
10507     }
10508 
10509     private void resetPressedState() {
10510         if ((mViewFlags & ENABLED_MASK) == DISABLED) {
10511             return;
10512         }
10513 
10514         if (isPressed()) {
10515             setPressed(false);
10516 
10517             if (!mHasPerformedLongPress) {
10518                 removeLongPressCallback();
10519             }
10520         }
10521     }
10522 
10523     /**
10524      * Returns true if this view has focus
10525      *
10526      * @return True if this view has focus, false otherwise.
10527      */
10528     @ViewDebug.ExportedProperty(category = "focus")
10529     @InspectableProperty(hasAttributeId = false)
10530     public boolean isFocused() {
10531         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
10532     }
10533 
10534     /**
10535      * Find the view in the hierarchy rooted at this view that currently has
10536      * focus.
10537      *
10538      * @return The view that currently has focus, or null if no focused view can
10539      *         be found.
10540      */
10541     public View findFocus() {
10542         return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
10543     }
10544 
10545     /**
10546      * Indicates whether this view is one of the set of scrollable containers in
10547      * its window.
10548      *
10549      * @return whether this view is one of the set of scrollable containers in
10550      * its window
10551      *
10552      * @attr ref android.R.styleable#View_isScrollContainer
10553      */
10554     @InspectableProperty(name = "isScrollContainer")
10555     public boolean isScrollContainer() {
10556         return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
10557     }
10558 
10559     /**
10560      * Change whether this view is one of the set of scrollable containers in
10561      * its window.  This will be used to determine whether the window can
10562      * resize or must pan when a soft input area is open -- scrollable
10563      * containers allow the window to use resize mode since the container
10564      * will appropriately shrink.
10565      *
10566      * @attr ref android.R.styleable#View_isScrollContainer
10567      */
10568     public void setScrollContainer(boolean isScrollContainer) {
10569         if (isScrollContainer) {
10570             if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
10571                 mAttachInfo.mScrollContainers.add(this);
10572                 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
10573             }
10574             mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
10575         } else {
10576             if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
10577                 mAttachInfo.mScrollContainers.remove(this);
10578             }
10579             mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
10580         }
10581     }
10582 
10583     /**
10584      * Returns the quality of the drawing cache.
10585      *
10586      * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
10587      *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
10588      *
10589      * @see #setDrawingCacheQuality(int)
10590      * @see #setDrawingCacheEnabled(boolean)
10591      * @see #isDrawingCacheEnabled()
10592      *
10593      * @attr ref android.R.styleable#View_drawingCacheQuality
10594      *
10595      * @deprecated The view drawing cache was largely made obsolete with the introduction of
10596      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
10597      * layers are largely unnecessary and can easily result in a net loss in performance due to the
10598      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
10599      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
10600      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
10601      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
10602      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
10603      * software-rendered usages are discouraged and have compatibility issues with hardware-only
10604      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
10605      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
10606      * reports or unit testing the {@link PixelCopy} API is recommended.
10607      */
10608     @Deprecated
10609     @DrawingCacheQuality
10610     @InspectableProperty(enumMapping = {
10611             @EnumEntry(value = DRAWING_CACHE_QUALITY_LOW, name = "low"),
10612             @EnumEntry(value = DRAWING_CACHE_QUALITY_HIGH, name = "high"),
10613             @EnumEntry(value = DRAWING_CACHE_QUALITY_AUTO, name = "auto")
10614     })
10615     public int getDrawingCacheQuality() {
10616         return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
10617     }
10618 
10619     /**
10620      * Set the drawing cache quality of this view. This value is used only when the
10621      * drawing cache is enabled
10622      *
10623      * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
10624      *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
10625      *
10626      * @see #getDrawingCacheQuality()
10627      * @see #setDrawingCacheEnabled(boolean)
10628      * @see #isDrawingCacheEnabled()
10629      *
10630      * @attr ref android.R.styleable#View_drawingCacheQuality
10631      *
10632      * @deprecated The view drawing cache was largely made obsolete with the introduction of
10633      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
10634      * layers are largely unnecessary and can easily result in a net loss in performance due to the
10635      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
10636      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
10637      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
10638      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
10639      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
10640      * software-rendered usages are discouraged and have compatibility issues with hardware-only
10641      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
10642      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
10643      * reports or unit testing the {@link PixelCopy} API is recommended.
10644      */
10645     @Deprecated
10646     public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
10647         setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
10648     }
10649 
10650     /**
10651      * Returns whether the screen should remain on, corresponding to the current
10652      * value of {@link #KEEP_SCREEN_ON}.
10653      *
10654      * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
10655      *
10656      * @see #setKeepScreenOn(boolean)
10657      *
10658      * @attr ref android.R.styleable#View_keepScreenOn
10659      */
10660     @InspectableProperty
10661     public boolean getKeepScreenOn() {
10662         return (mViewFlags & KEEP_SCREEN_ON) != 0;
10663     }
10664 
10665     /**
10666      * Controls whether the screen should remain on, modifying the
10667      * value of {@link #KEEP_SCREEN_ON}.
10668      *
10669      * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
10670      *
10671      * @see #getKeepScreenOn()
10672      *
10673      * @attr ref android.R.styleable#View_keepScreenOn
10674      */
10675     public void setKeepScreenOn(boolean keepScreenOn) {
10676         setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
10677     }
10678 
10679     /**
10680      * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
10681      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
10682      *
10683      * @attr ref android.R.styleable#View_nextFocusLeft
10684      */
10685     @IdRes
10686     @InspectableProperty(name = "nextFocusLeft")
10687     public int getNextFocusLeftId() {
10688         return mNextFocusLeftId;
10689     }
10690 
10691     /**
10692      * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
10693      * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
10694      * decide automatically.
10695      *
10696      * @attr ref android.R.styleable#View_nextFocusLeft
10697      */
10698     public void setNextFocusLeftId(@IdRes int nextFocusLeftId) {
10699         mNextFocusLeftId = nextFocusLeftId;
10700     }
10701 
10702     /**
10703      * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
10704      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
10705      *
10706      * @attr ref android.R.styleable#View_nextFocusRight
10707      */
10708     @IdRes
10709     @InspectableProperty(name = "nextFocusRight")
10710     public int getNextFocusRightId() {
10711         return mNextFocusRightId;
10712     }
10713 
10714     /**
10715      * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
10716      * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
10717      * decide automatically.
10718      *
10719      * @attr ref android.R.styleable#View_nextFocusRight
10720      */
10721     public void setNextFocusRightId(@IdRes int nextFocusRightId) {
10722         mNextFocusRightId = nextFocusRightId;
10723     }
10724 
10725     /**
10726      * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
10727      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
10728      *
10729      * @attr ref android.R.styleable#View_nextFocusUp
10730      */
10731     @IdRes
10732     @InspectableProperty(name = "nextFocusUp")
10733     public int getNextFocusUpId() {
10734         return mNextFocusUpId;
10735     }
10736 
10737     /**
10738      * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
10739      * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
10740      * decide automatically.
10741      *
10742      * @attr ref android.R.styleable#View_nextFocusUp
10743      */
10744     public void setNextFocusUpId(@IdRes int nextFocusUpId) {
10745         mNextFocusUpId = nextFocusUpId;
10746     }
10747 
10748     /**
10749      * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
10750      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
10751      *
10752      * @attr ref android.R.styleable#View_nextFocusDown
10753      */
10754     @IdRes
10755     @InspectableProperty(name = "nextFocusDown")
10756     public int getNextFocusDownId() {
10757         return mNextFocusDownId;
10758     }
10759 
10760     /**
10761      * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
10762      * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
10763      * decide automatically.
10764      *
10765      * @attr ref android.R.styleable#View_nextFocusDown
10766      */
10767     public void setNextFocusDownId(@IdRes int nextFocusDownId) {
10768         mNextFocusDownId = nextFocusDownId;
10769     }
10770 
10771     /**
10772      * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
10773      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
10774      *
10775      * @attr ref android.R.styleable#View_nextFocusForward
10776      */
10777     @IdRes
10778     @InspectableProperty(name = "nextFocusForward")
10779     public int getNextFocusForwardId() {
10780         return mNextFocusForwardId;
10781     }
10782 
10783     /**
10784      * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
10785      * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
10786      * decide automatically.
10787      *
10788      * @attr ref android.R.styleable#View_nextFocusForward
10789      */
10790     public void setNextFocusForwardId(@IdRes int nextFocusForwardId) {
10791         mNextFocusForwardId = nextFocusForwardId;
10792     }
10793 
10794     /**
10795      * Gets the id of the root of the next keyboard navigation cluster.
10796      * @return The next keyboard navigation cluster ID, or {@link #NO_ID} if the framework should
10797      * decide automatically.
10798      *
10799      * @attr ref android.R.styleable#View_nextClusterForward
10800      */
10801     @IdRes
10802     @InspectableProperty(name = "nextClusterForward")
10803     public int getNextClusterForwardId() {
10804         return mNextClusterForwardId;
10805     }
10806 
10807     /**
10808      * Sets the id of the view to use as the root of the next keyboard navigation cluster.
10809      * @param nextClusterForwardId The next cluster ID, or {@link #NO_ID} if the framework should
10810      * decide automatically.
10811      *
10812      * @attr ref android.R.styleable#View_nextClusterForward
10813      */
10814     public void setNextClusterForwardId(@IdRes int nextClusterForwardId) {
10815         mNextClusterForwardId = nextClusterForwardId;
10816     }
10817 
10818     /**
10819      * Returns the visibility of this view and all of its ancestors
10820      *
10821      * @return True if this view and all of its ancestors are {@link #VISIBLE}
10822      */
10823     public boolean isShown() {
10824         View current = this;
10825         //noinspection ConstantConditions
10826         do {
10827             if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
10828                 return false;
10829             }
10830             ViewParent parent = current.mParent;
10831             if (parent == null) {
10832                 return false; // We are not attached to the view root
10833             }
10834             if (!(parent instanceof View)) {
10835                 return true;
10836             }
10837             current = (View) parent;
10838         } while (current != null);
10839 
10840         return false;
10841     }
10842 
10843     /**
10844      * Called by the view hierarchy when the content insets for a window have
10845      * changed, to allow it to adjust its content to fit within those windows.
10846      * The content insets tell you the space that the status bar, input method,
10847      * and other system windows infringe on the application's window.
10848      *
10849      * <p>You do not normally need to deal with this function, since the default
10850      * window decoration given to applications takes care of applying it to the
10851      * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
10852      * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
10853      * and your content can be placed under those system elements.  You can then
10854      * use this method within your view hierarchy if you have parts of your UI
10855      * which you would like to ensure are not being covered.
10856      *
10857      * <p>The default implementation of this method simply applies the content
10858      * insets to the view's padding, consuming that content (modifying the
10859      * insets to be 0), and returning true.  This behavior is off by default, but can
10860      * be enabled through {@link #setFitsSystemWindows(boolean)}.
10861      *
10862      * <p>This function's traversal down the hierarchy is depth-first.  The same content
10863      * insets object is propagated down the hierarchy, so any changes made to it will
10864      * be seen by all following views (including potentially ones above in
10865      * the hierarchy since this is a depth-first traversal).  The first view
10866      * that returns true will abort the entire traversal.
10867      *
10868      * <p>The default implementation works well for a situation where it is
10869      * used with a container that covers the entire window, allowing it to
10870      * apply the appropriate insets to its content on all edges.  If you need
10871      * a more complicated layout (such as two different views fitting system
10872      * windows, one on the top of the window, and one on the bottom),
10873      * you can override the method and handle the insets however you would like.
10874      * Note that the insets provided by the framework are always relative to the
10875      * far edges of the window, not accounting for the location of the called view
10876      * within that window.  (In fact when this method is called you do not yet know
10877      * where the layout will place the view, as it is done before layout happens.)
10878      *
10879      * <p>Note: unlike many View methods, there is no dispatch phase to this
10880      * call.  If you are overriding it in a ViewGroup and want to allow the
10881      * call to continue to your children, you must be sure to call the super
10882      * implementation.
10883      *
10884      * <p>Here is a sample layout that makes use of fitting system windows
10885      * to have controls for a video view placed inside of the window decorations
10886      * that it hides and shows.  This can be used with code like the second
10887      * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
10888      *
10889      * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
10890      *
10891      * @param insets Current content insets of the window.  Prior to
10892      * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
10893      * the insets or else you and Android will be unhappy.
10894      *
10895      * @return {@code true} if this view applied the insets and it should not
10896      * continue propagating further down the hierarchy, {@code false} otherwise.
10897      * @see #getFitsSystemWindows()
10898      * @see #setFitsSystemWindows(boolean)
10899      * @see #setSystemUiVisibility(int)
10900      *
10901      * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
10902      * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
10903      * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
10904      * to implement handling their own insets.
10905      */
10906     @Deprecated
10907     protected boolean fitSystemWindows(Rect insets) {
10908         if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
10909             if (insets == null) {
10910                 // Null insets by definition have already been consumed.
10911                 // This call cannot apply insets since there are none to apply,
10912                 // so return false.
10913                 return false;
10914             }
10915             // If we're not in the process of dispatching the newer apply insets call,
10916             // that means we're not in the compatibility path. Dispatch into the newer
10917             // apply insets path and take things from there.
10918             try {
10919                 mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
10920                 return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
10921             } finally {
10922                 mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
10923             }
10924         } else {
10925             // We're being called from the newer apply insets path.
10926             // Perform the standard fallback behavior.
10927             return fitSystemWindowsInt(insets);
10928         }
10929     }
10930 
10931     private boolean fitSystemWindowsInt(Rect insets) {
10932         if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
10933             mUserPaddingStart = UNDEFINED_PADDING;
10934             mUserPaddingEnd = UNDEFINED_PADDING;
10935             Rect localInsets = sThreadLocal.get();
10936             if (localInsets == null) {
10937                 localInsets = new Rect();
10938                 sThreadLocal.set(localInsets);
10939             }
10940             boolean res = computeFitSystemWindows(insets, localInsets);
10941             mUserPaddingLeftInitial = localInsets.left;
10942             mUserPaddingRightInitial = localInsets.right;
10943             internalSetPadding(localInsets.left, localInsets.top,
10944                     localInsets.right, localInsets.bottom);
10945             return res;
10946         }
10947         return false;
10948     }
10949 
10950     /**
10951      * Called when the view should apply {@link WindowInsets} according to its internal policy.
10952      *
10953      * <p>This method should be overridden by views that wish to apply a policy different from or
10954      * in addition to the default behavior. Clients that wish to force a view subtree
10955      * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
10956      *
10957      * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
10958      * it will be called during dispatch instead of this method. The listener may optionally
10959      * call this method from its own implementation if it wishes to apply the view's default
10960      * insets policy in addition to its own.</p>
10961      *
10962      * <p>Implementations of this method should either return the insets parameter unchanged
10963      * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
10964      * that this view applied itself. This allows new inset types added in future platform
10965      * versions to pass through existing implementations unchanged without being erroneously
10966      * consumed.</p>
10967      *
10968      * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
10969      * property is set then the view will consume the system window insets and apply them
10970      * as padding for the view.</p>
10971      *
10972      * @param insets Insets to apply
10973      * @return The supplied insets with any applied insets consumed
10974      */
10975     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
10976         if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
10977             // We weren't called from within a direct call to fitSystemWindows,
10978             // call into it as a fallback in case we're in a class that overrides it
10979             // and has logic to perform.
10980             if (fitSystemWindows(insets.getSystemWindowInsetsAsRect())) {
10981                 return insets.consumeSystemWindowInsets();
10982             }
10983         } else {
10984             // We were called from within a direct call to fitSystemWindows.
10985             if (fitSystemWindowsInt(insets.getSystemWindowInsetsAsRect())) {
10986                 return insets.consumeSystemWindowInsets();
10987             }
10988         }
10989         return insets;
10990     }
10991 
10992     /**
10993      * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
10994      * window insets to this view. The listener's
10995      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
10996      * method will be called instead of the view's
10997      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
10998      *
10999      * @param listener Listener to set
11000      *
11001      * @see #onApplyWindowInsets(WindowInsets)
11002      */
11003     public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
11004         getListenerInfo().mOnApplyWindowInsetsListener = listener;
11005     }
11006 
11007     /**
11008      * Request to apply the given window insets to this view or another view in its subtree.
11009      *
11010      * <p>This method should be called by clients wishing to apply insets corresponding to areas
11011      * obscured by window decorations or overlays. This can include the status and navigation bars,
11012      * action bars, input methods and more. New inset categories may be added in the future.
11013      * The method returns the insets provided minus any that were applied by this view or its
11014      * children.</p>
11015      *
11016      * <p>Clients wishing to provide custom behavior should override the
11017      * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
11018      * {@link OnApplyWindowInsetsListener} via the
11019      * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
11020      * method.</p>
11021      *
11022      * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
11023      * </p>
11024      *
11025      * @param insets Insets to apply
11026      * @return The provided insets minus the insets that were consumed
11027      */
11028     public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
11029         try {
11030             mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
11031             if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
11032                 return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
11033             } else {
11034                 return onApplyWindowInsets(insets);
11035             }
11036         } finally {
11037             mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
11038         }
11039     }
11040 
11041     /**
11042      * Sets a {@link WindowInsetsAnimationListener} to be notified about animations of windows that
11043      * cause insets.
11044      *
11045      * @param listener The listener to set.
11046      * @hide pending unhide
11047      */
11048     public void setWindowInsetsAnimationListener(WindowInsetsAnimationListener listener) {
11049         getListenerInfo().mWindowInsetsAnimationListener = listener;
11050     }
11051 
11052     void dispatchWindowInsetsAnimationStarted(InsetsAnimation animation) {
11053         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationListener != null) {
11054             mListenerInfo.mWindowInsetsAnimationListener.onStarted(animation);
11055         }
11056     }
11057 
11058     WindowInsets dispatchWindowInsetsAnimationProgress(WindowInsets insets) {
11059         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationListener != null) {
11060             return mListenerInfo.mWindowInsetsAnimationListener.onProgress(insets);
11061         } else {
11062             return insets;
11063         }
11064     }
11065 
11066     void dispatchWindowInsetsAnimationFinished(InsetsAnimation animation) {
11067         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationListener != null) {
11068             mListenerInfo.mWindowInsetsAnimationListener.onFinished(animation);
11069         }
11070     }
11071 
11072     /**
11073      * Sets a list of areas within this view's post-layout coordinate space where the system
11074      * should not intercept touch or other pointing device gestures. <em>This method should
11075      * be called by {@link #onLayout(boolean, int, int, int, int)} or {@link #onDraw(Canvas)}.</em>
11076      *
11077      * <p>Use this to tell the system which specific sub-areas of a view need to receive gesture
11078      * input in order to function correctly in the presence of global system gestures that may
11079      * conflict. For example, if the system wishes to capture swipe-in-from-screen-edge gestures
11080      * to provide system-level navigation functionality, a view such as a navigation drawer
11081      * container can mark the left (or starting) edge of itself as requiring gesture capture
11082      * priority using this API. The system may then choose to relax its own gesture recognition
11083      * to allow the app to consume the user's gesture. It is not necessary for an app to register
11084      * exclusion rects for broadly spanning regions such as the entirety of a
11085      * <code>ScrollView</code> or for simple press and release click targets such as
11086      * <code>Button</code>. Mark an exclusion rect when interacting with a view requires
11087      * a precision touch gesture in a small area in either the X or Y dimension, such as
11088      * an edge swipe or dragging a <code>SeekBar</code> thumb.</p>
11089      *
11090      * <p>Do not modify the provided list after this method is called.</p>
11091      *
11092      * <p>Note: the system will put a limit of <code>200dp</code> on the vertical extent of the
11093      * exclusions it takes into account. The limit does not apply while the navigation
11094      * bar is {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY stickily} hidden, nor to the
11095      * {@link android.inputmethodservice.InputMethodService input method} and
11096      * {@link Intent#CATEGORY_HOME home activity}.
11097      * </p>
11098      *
11099      * @param rects A list of precision gesture regions that this view needs to function correctly
11100      */
11101     public void setSystemGestureExclusionRects(@NonNull List<Rect> rects) {
11102         if (rects.isEmpty() && mListenerInfo == null) return;
11103 
11104         final ListenerInfo info = getListenerInfo();
11105         if (rects.isEmpty()) {
11106             info.mSystemGestureExclusionRects = null;
11107             if (info.mPositionUpdateListener != null) {
11108                 mRenderNode.removePositionUpdateListener(info.mPositionUpdateListener);
11109             }
11110         } else {
11111             info.mSystemGestureExclusionRects = rects;
11112             if (info.mPositionUpdateListener == null) {
11113                 info.mPositionUpdateListener = new RenderNode.PositionUpdateListener() {
11114                     @Override
11115                     public void positionChanged(long n, int l, int t, int r, int b) {
11116                         postUpdateSystemGestureExclusionRects();
11117                     }
11118 
11119                     @Override
11120                     public void positionLost(long frameNumber) {
11121                         postUpdateSystemGestureExclusionRects();
11122                     }
11123                 };
11124                 mRenderNode.addPositionUpdateListener(info.mPositionUpdateListener);
11125             }
11126         }
11127         postUpdateSystemGestureExclusionRects();
11128     }
11129 
11130     /**
11131      * WARNING: this can be called by a hwui worker thread, not just the UI thread!
11132      */
11133     void postUpdateSystemGestureExclusionRects() {
11134         // Potentially racey from a background thread. It's ok if it's not perfect.
11135         final Handler h = getHandler();
11136         if (h != null) {
11137             h.postAtFrontOfQueue(this::updateSystemGestureExclusionRects);
11138         }
11139     }
11140 
11141     void updateSystemGestureExclusionRects() {
11142         final AttachInfo ai = mAttachInfo;
11143         if (ai != null) {
11144             ai.mViewRootImpl.updateSystemGestureExclusionRectsForView(this);
11145         }
11146     }
11147 
11148     /**
11149      * Retrieve the list of areas within this view's post-layout coordinate space where the system
11150      * should not intercept touch or other pointing device gestures.
11151      *
11152      * <p>Do not modify the returned list.</p>
11153      *
11154      * @return the list set by {@link #setSystemGestureExclusionRects(List)}
11155      */
11156     @NonNull
11157     public List<Rect> getSystemGestureExclusionRects() {
11158         final ListenerInfo info = mListenerInfo;
11159         if (info != null) {
11160             final List<Rect> list = info.mSystemGestureExclusionRects;
11161             if (list != null) {
11162                 return list;
11163             }
11164         }
11165         return Collections.emptyList();
11166     }
11167 
11168     /**
11169      * Compute the view's coordinate within the surface.
11170      *
11171      * <p>Computes the coordinates of this view in its surface. The argument
11172      * must be an array of two integers. After the method returns, the array
11173      * contains the x and y location in that order.</p>
11174      *
11175      * @param location an array of two integers in which to hold the coordinates
11176      */
11177     public void getLocationInSurface(@NonNull @Size(2) int[] location) {
11178         getLocationInWindow(location);
11179         if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
11180             location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
11181             location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
11182         }
11183     }
11184 
11185     /**
11186      * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
11187      * only available if the view is attached.
11188      *
11189      * @return WindowInsets from the top of the view hierarchy or null if View is detached
11190      */
11191     public WindowInsets getRootWindowInsets() {
11192         if (mAttachInfo != null) {
11193             return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
11194         }
11195         return null;
11196     }
11197 
11198     /**
11199      * Retrieves the single {@link WindowInsetsController} of the window this view is attached to.
11200      *
11201      * @return The {@link WindowInsetsController} or {@code null} if the view isn't attached to a
11202      *         a window.
11203      * @see Window#getInsetsController()
11204      * @hide pending unhide
11205      */
11206     public @Nullable WindowInsetsController getWindowInsetsController() {
11207         if (mAttachInfo != null) {
11208             return mAttachInfo.mViewRootImpl.getInsetsController();
11209         }
11210         return null;
11211     }
11212 
11213     /**
11214      * @hide Compute the insets that should be consumed by this view and the ones
11215      * that should propagate to those under it.
11216      *
11217      * Note: This is used by appcompat's ActionBarOverlayLayout through reflection.
11218      *
11219      * @param inoutInsets the insets given to this view
11220      * @param outLocalInsets the insets that should be applied to this view
11221      * @deprecated use {@link #computeSystemWindowInsets}
11222      * @return
11223      */
11224     @Deprecated
11225     @UnsupportedAppUsage
11226     protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
11227         WindowInsets innerInsets = computeSystemWindowInsets(new WindowInsets(inoutInsets),
11228                 outLocalInsets);
11229         inoutInsets.set(innerInsets.getSystemWindowInsetsAsRect());
11230         return innerInsets.isSystemWindowInsetsConsumed();
11231     }
11232 
11233     /**
11234      * Compute insets that should be consumed by this view and the ones that should propagate
11235      * to those under it.
11236      *
11237      * @param in Insets currently being processed by this View, likely received as a parameter
11238      *           to {@link #onApplyWindowInsets(WindowInsets)}.
11239      * @param outLocalInsets A Rect that will receive the insets that should be consumed
11240      *                       by this view
11241      * @return Insets that should be passed along to views under this one
11242      */
11243     public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
11244         if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
11245                 || mAttachInfo == null
11246                 || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
11247                 && !mAttachInfo.mOverscanRequested)) {
11248             outLocalInsets.set(in.getSystemWindowInsetsAsRect());
11249             return in.consumeSystemWindowInsets().inset(outLocalInsets);
11250         } else {
11251             // The application wants to take care of fitting system window for
11252             // the content...  however we still need to take care of any overscan here.
11253             final Rect overscan = mAttachInfo.mOverscanInsets;
11254             outLocalInsets.set(overscan);
11255             return in.inset(outLocalInsets);
11256         }
11257     }
11258 
11259     /**
11260      * Sets whether or not this view should account for system screen decorations
11261      * such as the status bar and inset its content; that is, controlling whether
11262      * the default implementation of {@link #fitSystemWindows(Rect)} will be
11263      * executed.  See that method for more details.
11264      *
11265      * <p>Note that if you are providing your own implementation of
11266      * {@link #fitSystemWindows(Rect)}, then there is no need to set this
11267      * flag to true -- your implementation will be overriding the default
11268      * implementation that checks this flag.
11269      *
11270      * @param fitSystemWindows If true, then the default implementation of
11271      * {@link #fitSystemWindows(Rect)} will be executed.
11272      *
11273      * @attr ref android.R.styleable#View_fitsSystemWindows
11274      * @see #getFitsSystemWindows()
11275      * @see #fitSystemWindows(Rect)
11276      * @see #setSystemUiVisibility(int)
11277      */
11278     public void setFitsSystemWindows(boolean fitSystemWindows) {
11279         setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
11280     }
11281 
11282     /**
11283      * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
11284      * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
11285      * will be executed.
11286      *
11287      * @return {@code true} if the default implementation of
11288      * {@link #fitSystemWindows(Rect)} will be executed.
11289      *
11290      * @attr ref android.R.styleable#View_fitsSystemWindows
11291      * @see #setFitsSystemWindows(boolean)
11292      * @see #fitSystemWindows(Rect)
11293      * @see #setSystemUiVisibility(int)
11294      */
11295     @ViewDebug.ExportedProperty
11296     @InspectableProperty
11297     public boolean getFitsSystemWindows() {
11298         return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
11299     }
11300 
11301     /** @hide */
11302     @UnsupportedAppUsage
11303     public boolean fitsSystemWindows() {
11304         return getFitsSystemWindows();
11305     }
11306 
11307     /**
11308      * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
11309      * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
11310      */
11311     @Deprecated
11312     public void requestFitSystemWindows() {
11313         if (mParent != null) {
11314             mParent.requestFitSystemWindows();
11315         }
11316     }
11317 
11318     /**
11319      * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
11320      */
11321     public void requestApplyInsets() {
11322         requestFitSystemWindows();
11323     }
11324 
11325     /**
11326      * For use by PhoneWindow to make its own system window fitting optional.
11327      * @hide
11328      */
11329     @UnsupportedAppUsage
11330     public void makeOptionalFitsSystemWindows() {
11331         setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
11332     }
11333 
11334     /**
11335      * Returns the outsets, which areas of the device that aren't a surface, but we would like to
11336      * treat them as such.
11337      * @hide
11338      */
11339     public void getOutsets(Rect outOutsetRect) {
11340         if (mAttachInfo != null) {
11341             outOutsetRect.set(mAttachInfo.mOutsets);
11342         } else {
11343             outOutsetRect.setEmpty();
11344         }
11345     }
11346 
11347     /**
11348      * Returns the visibility status for this view.
11349      *
11350      * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
11351      * @attr ref android.R.styleable#View_visibility
11352      */
11353     @ViewDebug.ExportedProperty(mapping = {
11354         @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
11355         @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
11356         @ViewDebug.IntToString(from = GONE,      to = "GONE")
11357     })
11358     @InspectableProperty(enumMapping = {
11359             @EnumEntry(value = VISIBLE, name = "visible"),
11360             @EnumEntry(value = INVISIBLE, name = "invisible"),
11361             @EnumEntry(value = GONE, name = "gone")
11362     })
11363     @Visibility
11364     public int getVisibility() {
11365         return mViewFlags & VISIBILITY_MASK;
11366     }
11367 
11368     /**
11369      * Set the visibility state of this view.
11370      *
11371      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
11372      * @attr ref android.R.styleable#View_visibility
11373      */
11374     @RemotableViewMethod
11375     public void setVisibility(@Visibility int visibility) {
11376         setFlags(visibility, VISIBILITY_MASK);
11377     }
11378 
11379     /**
11380      * Returns the enabled status for this view. The interpretation of the
11381      * enabled state varies by subclass.
11382      *
11383      * @return True if this view is enabled, false otherwise.
11384      */
11385     @ViewDebug.ExportedProperty
11386     @InspectableProperty
11387     public boolean isEnabled() {
11388         return (mViewFlags & ENABLED_MASK) == ENABLED;
11389     }
11390 
11391     /**
11392      * Set the enabled state of this view. The interpretation of the enabled
11393      * state varies by subclass.
11394      *
11395      * @param enabled True if this view is enabled, false otherwise.
11396      */
11397     @RemotableViewMethod
11398     public void setEnabled(boolean enabled) {
11399         if (enabled == isEnabled()) return;
11400 
11401         setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
11402 
11403         /*
11404          * The View most likely has to change its appearance, so refresh
11405          * the drawable state.
11406          */
11407         refreshDrawableState();
11408 
11409         // Invalidate too, since the default behavior for views is to be
11410         // be drawn at 50% alpha rather than to change the drawable.
11411         invalidate(true);
11412 
11413         if (!enabled) {
11414             cancelPendingInputEvents();
11415         }
11416     }
11417 
11418     /**
11419      * Set whether this view can receive the focus.
11420      * <p>
11421      * Setting this to false will also ensure that this view is not focusable
11422      * in touch mode.
11423      *
11424      * @param focusable If true, this view can receive the focus.
11425      *
11426      * @see #setFocusableInTouchMode(boolean)
11427      * @see #setFocusable(int)
11428      * @attr ref android.R.styleable#View_focusable
11429      */
11430     public void setFocusable(boolean focusable) {
11431         setFocusable(focusable ? FOCUSABLE : NOT_FOCUSABLE);
11432     }
11433 
11434     /**
11435      * Sets whether this view can receive focus.
11436      * <p>
11437      * Setting this to {@link #FOCUSABLE_AUTO} tells the framework to determine focusability
11438      * automatically based on the view's interactivity. This is the default.
11439      * <p>
11440      * Setting this to NOT_FOCUSABLE will ensure that this view is also not focusable
11441      * in touch mode.
11442      *
11443      * @param focusable One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE},
11444      *                  or {@link #FOCUSABLE_AUTO}.
11445      * @see #setFocusableInTouchMode(boolean)
11446      * @attr ref android.R.styleable#View_focusable
11447      */
11448     public void setFocusable(@Focusable int focusable) {
11449         if ((focusable & (FOCUSABLE_AUTO | FOCUSABLE)) == 0) {
11450             setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
11451         }
11452         setFlags(focusable, FOCUSABLE_MASK);
11453     }
11454 
11455     /**
11456      * Set whether this view can receive focus while in touch mode.
11457      *
11458      * Setting this to true will also ensure that this view is focusable.
11459      *
11460      * @param focusableInTouchMode If true, this view can receive the focus while
11461      *   in touch mode.
11462      *
11463      * @see #setFocusable(boolean)
11464      * @attr ref android.R.styleable#View_focusableInTouchMode
11465      */
11466     public void setFocusableInTouchMode(boolean focusableInTouchMode) {
11467         // Focusable in touch mode should always be set before the focusable flag
11468         // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
11469         // which, in touch mode, will not successfully request focus on this view
11470         // because the focusable in touch mode flag is not set
11471         setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
11472 
11473         // Clear FOCUSABLE_AUTO if set.
11474         if (focusableInTouchMode) {
11475             // Clears FOCUSABLE_AUTO if set.
11476             setFlags(FOCUSABLE, FOCUSABLE_MASK);
11477         }
11478     }
11479 
11480     /**
11481      * Sets the hints that help an {@link android.service.autofill.AutofillService} determine how
11482      * to autofill the view with the user's data.
11483      *
11484      * <p>Typically, there is only one way to autofill a view, but there could be more than one.
11485      * For example, if the application accepts either an username or email address to identify
11486      * an user.
11487      *
11488      * <p>These hints are not validated by the Android System, but passed "as is" to the service.
11489      * Hence, they can have any value, but it's recommended to use the {@code AUTOFILL_HINT_}
11490      * constants such as:
11491      * {@link #AUTOFILL_HINT_USERNAME}, {@link #AUTOFILL_HINT_PASSWORD},
11492      * {@link #AUTOFILL_HINT_EMAIL_ADDRESS},
11493      * {@link #AUTOFILL_HINT_NAME},
11494      * {@link #AUTOFILL_HINT_PHONE},
11495      * {@link #AUTOFILL_HINT_POSTAL_ADDRESS}, {@link #AUTOFILL_HINT_POSTAL_CODE},
11496      * {@link #AUTOFILL_HINT_CREDIT_CARD_NUMBER}, {@link #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE},
11497      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE},
11498      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
11499      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH} or
11500      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}.
11501      *
11502      * @param autofillHints The autofill hints to set. If the array is emtpy, {@code null} is set.
11503      * @attr ref android.R.styleable#View_autofillHints
11504      */
11505     public void setAutofillHints(@Nullable String... autofillHints) {
11506         if (autofillHints == null || autofillHints.length == 0) {
11507             mAutofillHints = null;
11508         } else {
11509             mAutofillHints = autofillHints;
11510         }
11511     }
11512 
11513     /**
11514      * @hide
11515      */
11516     @TestApi
11517     public void setAutofilled(boolean isAutofilled) {
11518         boolean wasChanged = isAutofilled != isAutofilled();
11519 
11520         if (wasChanged) {
11521             if (isAutofilled) {
11522                 mPrivateFlags3 |= PFLAG3_IS_AUTOFILLED;
11523             } else {
11524                 mPrivateFlags3 &= ~PFLAG3_IS_AUTOFILLED;
11525             }
11526 
11527             invalidate();
11528         }
11529     }
11530 
11531     /**
11532      * Set whether this view should have sound effects enabled for events such as
11533      * clicking and touching.
11534      *
11535      * <p>You may wish to disable sound effects for a view if you already play sounds,
11536      * for instance, a dial key that plays dtmf tones.
11537      *
11538      * @param soundEffectsEnabled whether sound effects are enabled for this view.
11539      * @see #isSoundEffectsEnabled()
11540      * @see #playSoundEffect(int)
11541      * @attr ref android.R.styleable#View_soundEffectsEnabled
11542      */
11543     public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
11544         setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
11545     }
11546 
11547     /**
11548      * @return whether this view should have sound effects enabled for events such as
11549      *     clicking and touching.
11550      *
11551      * @see #setSoundEffectsEnabled(boolean)
11552      * @see #playSoundEffect(int)
11553      * @attr ref android.R.styleable#View_soundEffectsEnabled
11554      */
11555     @ViewDebug.ExportedProperty
11556     @InspectableProperty
11557     public boolean isSoundEffectsEnabled() {
11558         return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
11559     }
11560 
11561     /**
11562      * Set whether this view should have haptic feedback for events such as
11563      * long presses.
11564      *
11565      * <p>You may wish to disable haptic feedback if your view already controls
11566      * its own haptic feedback.
11567      *
11568      * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
11569      * @see #isHapticFeedbackEnabled()
11570      * @see #performHapticFeedback(int)
11571      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
11572      */
11573     public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
11574         setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
11575     }
11576 
11577     /**
11578      * @return whether this view should have haptic feedback enabled for events
11579      * long presses.
11580      *
11581      * @see #setHapticFeedbackEnabled(boolean)
11582      * @see #performHapticFeedback(int)
11583      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
11584      */
11585     @ViewDebug.ExportedProperty
11586     @InspectableProperty
11587     public boolean isHapticFeedbackEnabled() {
11588         return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
11589     }
11590 
11591     /**
11592      * Returns the layout direction for this view.
11593      *
11594      * @return One of {@link #LAYOUT_DIRECTION_LTR},
11595      *   {@link #LAYOUT_DIRECTION_RTL},
11596      *   {@link #LAYOUT_DIRECTION_INHERIT} or
11597      *   {@link #LAYOUT_DIRECTION_LOCALE}.
11598      *
11599      * @attr ref android.R.styleable#View_layoutDirection
11600      *
11601      * @hide
11602      */
11603     @ViewDebug.ExportedProperty(category = "layout", mapping = {
11604         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
11605         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
11606         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
11607         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
11608     })
11609     @InspectableProperty(hasAttributeId = false, enumMapping = {
11610             @EnumEntry(value = LAYOUT_DIRECTION_LTR, name = "ltr"),
11611             @EnumEntry(value = LAYOUT_DIRECTION_RTL, name = "rtl"),
11612             @EnumEntry(value = LAYOUT_DIRECTION_INHERIT, name = "inherit"),
11613             @EnumEntry(value = LAYOUT_DIRECTION_LOCALE, name = "locale")
11614     })
11615     @LayoutDir
11616     public int getRawLayoutDirection() {
11617         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
11618     }
11619 
11620     /**
11621      * Set the layout direction for this view. This will propagate a reset of layout direction
11622      * resolution to the view's children and resolve layout direction for this view.
11623      *
11624      * @param layoutDirection the layout direction to set. Should be one of:
11625      *
11626      * {@link #LAYOUT_DIRECTION_LTR},
11627      * {@link #LAYOUT_DIRECTION_RTL},
11628      * {@link #LAYOUT_DIRECTION_INHERIT},
11629      * {@link #LAYOUT_DIRECTION_LOCALE}.
11630      *
11631      * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
11632      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
11633      * will return the default {@link #LAYOUT_DIRECTION_LTR}.
11634      *
11635      * @attr ref android.R.styleable#View_layoutDirection
11636      */
11637     @RemotableViewMethod
11638     public void setLayoutDirection(@LayoutDir int layoutDirection) {
11639         if (getRawLayoutDirection() != layoutDirection) {
11640             // Reset the current layout direction and the resolved one
11641             mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
11642             resetRtlProperties();
11643             // Set the new layout direction (filtered)
11644             mPrivateFlags2 |=
11645                     ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
11646             // We need to resolve all RTL properties as they all depend on layout direction
11647             resolveRtlPropertiesIfNeeded();
11648             requestLayout();
11649             invalidate(true);
11650         }
11651     }
11652 
11653     /**
11654      * Returns the resolved layout direction for this view.
11655      *
11656      * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
11657      * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
11658      *
11659      * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
11660      * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
11661      *
11662      * @attr ref android.R.styleable#View_layoutDirection
11663      */
11664     @ViewDebug.ExportedProperty(category = "layout", mapping = {
11665         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
11666         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
11667     })
11668     @InspectableProperty(enumMapping = {
11669             @EnumEntry(value = LAYOUT_DIRECTION_LTR, name = "ltr"),
11670             @EnumEntry(value = LAYOUT_DIRECTION_RTL, name = "rtl")
11671     })
11672     @ResolvedLayoutDir
11673     public int getLayoutDirection() {
11674         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
11675         if (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
11676             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
11677             return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
11678         }
11679         return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
11680                 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
11681     }
11682 
11683     /**
11684      * Indicates whether or not this view's layout is right-to-left. This is resolved from
11685      * layout attribute and/or the inherited value from the parent
11686      *
11687      * @return true if the layout is right-to-left.
11688      *
11689      * @hide
11690      */
11691     @ViewDebug.ExportedProperty(category = "layout")
11692     @UnsupportedAppUsage
11693     public boolean isLayoutRtl() {
11694         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
11695     }
11696 
11697     /**
11698      * Indicates whether the view is currently tracking transient state that the
11699      * app should not need to concern itself with saving and restoring, but that
11700      * the framework should take special note to preserve when possible.
11701      *
11702      * <p>A view with transient state cannot be trivially rebound from an external
11703      * data source, such as an adapter binding item views in a list. This may be
11704      * because the view is performing an animation, tracking user selection
11705      * of content, or similar.</p>
11706      *
11707      * @return true if the view has transient state
11708      */
11709     @ViewDebug.ExportedProperty(category = "layout")
11710     public boolean hasTransientState() {
11711         return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
11712     }
11713 
11714     /**
11715      * Set whether this view is currently tracking transient state that the
11716      * framework should attempt to preserve when possible. This flag is reference counted,
11717      * so every call to setHasTransientState(true) should be paired with a later call
11718      * to setHasTransientState(false).
11719      *
11720      * <p>A view with transient state cannot be trivially rebound from an external
11721      * data source, such as an adapter binding item views in a list. This may be
11722      * because the view is performing an animation, tracking user selection
11723      * of content, or similar.</p>
11724      *
11725      * @param hasTransientState true if this view has transient state
11726      */
11727     public void setHasTransientState(boolean hasTransientState) {
11728         final boolean oldHasTransientState = hasTransientState();
11729         mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
11730                 mTransientStateCount - 1;
11731         if (mTransientStateCount < 0) {
11732             mTransientStateCount = 0;
11733             Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
11734                     "unmatched pair of setHasTransientState calls");
11735         } else if ((hasTransientState && mTransientStateCount == 1) ||
11736                 (!hasTransientState && mTransientStateCount == 0)) {
11737             // update flag if we've just incremented up from 0 or decremented down to 0
11738             mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
11739                     (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
11740             final boolean newHasTransientState = hasTransientState();
11741             if (mParent != null && newHasTransientState != oldHasTransientState) {
11742                 try {
11743                     mParent.childHasTransientStateChanged(this, newHasTransientState);
11744                 } catch (AbstractMethodError e) {
11745                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
11746                             " does not fully implement ViewParent", e);
11747                 }
11748             }
11749         }
11750     }
11751 
11752     /**
11753      * Returns true if this view is currently attached to a window.
11754      */
11755     public boolean isAttachedToWindow() {
11756         return mAttachInfo != null;
11757     }
11758 
11759     /**
11760      * Returns true if this view has been through at least one layout since it
11761      * was last attached to or detached from a window.
11762      */
11763     public boolean isLaidOut() {
11764         return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
11765     }
11766 
11767     /**
11768      * @return {@code true} if laid-out and not about to do another layout.
11769      */
11770     boolean isLayoutValid() {
11771         return isLaidOut() && ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == 0);
11772     }
11773 
11774     /**
11775      * If this view doesn't do any drawing on its own, set this flag to
11776      * allow further optimizations. By default, this flag is not set on
11777      * View, but could be set on some View subclasses such as ViewGroup.
11778      *
11779      * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
11780      * you should clear this flag.
11781      *
11782      * @param willNotDraw whether or not this View draw on its own
11783      */
11784     public void setWillNotDraw(boolean willNotDraw) {
11785         setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
11786     }
11787 
11788     /**
11789      * Returns whether or not this View draws on its own.
11790      *
11791      * @return true if this view has nothing to draw, false otherwise
11792      */
11793     @ViewDebug.ExportedProperty(category = "drawing")
11794     public boolean willNotDraw() {
11795         return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
11796     }
11797 
11798     /**
11799      * When a View's drawing cache is enabled, drawing is redirected to an
11800      * offscreen bitmap. Some views, like an ImageView, must be able to
11801      * bypass this mechanism if they already draw a single bitmap, to avoid
11802      * unnecessary usage of the memory.
11803      *
11804      * @param willNotCacheDrawing true if this view does not cache its
11805      *        drawing, false otherwise
11806      *
11807      * @deprecated The view drawing cache was largely made obsolete with the introduction of
11808      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
11809      * layers are largely unnecessary and can easily result in a net loss in performance due to the
11810      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
11811      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
11812      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
11813      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
11814      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
11815      * software-rendered usages are discouraged and have compatibility issues with hardware-only
11816      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
11817      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
11818      * reports or unit testing the {@link PixelCopy} API is recommended.
11819      */
11820     @Deprecated
11821     public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
11822         setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
11823     }
11824 
11825     /**
11826      * Returns whether or not this View can cache its drawing or not.
11827      *
11828      * @return true if this view does not cache its drawing, false otherwise
11829      *
11830      * @deprecated The view drawing cache was largely made obsolete with the introduction of
11831      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
11832      * layers are largely unnecessary and can easily result in a net loss in performance due to the
11833      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
11834      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
11835      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
11836      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
11837      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
11838      * software-rendered usages are discouraged and have compatibility issues with hardware-only
11839      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
11840      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
11841      * reports or unit testing the {@link PixelCopy} API is recommended.
11842      */
11843     @ViewDebug.ExportedProperty(category = "drawing")
11844     @Deprecated
11845     public boolean willNotCacheDrawing() {
11846         return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
11847     }
11848 
11849     /**
11850      * Indicates whether this view reacts to click events or not.
11851      *
11852      * @return true if the view is clickable, false otherwise
11853      *
11854      * @see #setClickable(boolean)
11855      * @attr ref android.R.styleable#View_clickable
11856      */
11857     @ViewDebug.ExportedProperty
11858     @InspectableProperty
11859     public boolean isClickable() {
11860         return (mViewFlags & CLICKABLE) == CLICKABLE;
11861     }
11862 
11863     /**
11864      * Enables or disables click events for this view. When a view
11865      * is clickable it will change its state to "pressed" on every click.
11866      * Subclasses should set the view clickable to visually react to
11867      * user's clicks.
11868      *
11869      * @param clickable true to make the view clickable, false otherwise
11870      *
11871      * @see #isClickable()
11872      * @attr ref android.R.styleable#View_clickable
11873      */
11874     public void setClickable(boolean clickable) {
11875         setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
11876     }
11877 
11878     /**
11879      * Indicates whether this view reacts to long click events or not.
11880      *
11881      * @return true if the view is long clickable, false otherwise
11882      *
11883      * @see #setLongClickable(boolean)
11884      * @attr ref android.R.styleable#View_longClickable
11885      */
11886     @InspectableProperty
11887     public boolean isLongClickable() {
11888         return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
11889     }
11890 
11891     /**
11892      * Enables or disables long click events for this view. When a view is long
11893      * clickable it reacts to the user holding down the button for a longer
11894      * duration than a tap. This event can either launch the listener or a
11895      * context menu.
11896      *
11897      * @param longClickable true to make the view long clickable, false otherwise
11898      * @see #isLongClickable()
11899      * @attr ref android.R.styleable#View_longClickable
11900      */
11901     public void setLongClickable(boolean longClickable) {
11902         setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
11903     }
11904 
11905     /**
11906      * Indicates whether this view reacts to context clicks or not.
11907      *
11908      * @return true if the view is context clickable, false otherwise
11909      * @see #setContextClickable(boolean)
11910      * @attr ref android.R.styleable#View_contextClickable
11911      */
11912     @InspectableProperty
11913     public boolean isContextClickable() {
11914         return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
11915     }
11916 
11917     /**
11918      * Enables or disables context clicking for this view. This event can launch the listener.
11919      *
11920      * @param contextClickable true to make the view react to a context click, false otherwise
11921      * @see #isContextClickable()
11922      * @attr ref android.R.styleable#View_contextClickable
11923      */
11924     public void setContextClickable(boolean contextClickable) {
11925         setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
11926     }
11927 
11928     /**
11929      * Sets the pressed state for this view and provides a touch coordinate for
11930      * animation hinting.
11931      *
11932      * @param pressed Pass true to set the View's internal state to "pressed",
11933      *            or false to reverts the View's internal state from a
11934      *            previously set "pressed" state.
11935      * @param x The x coordinate of the touch that caused the press
11936      * @param y The y coordinate of the touch that caused the press
11937      */
11938     private void setPressed(boolean pressed, float x, float y) {
11939         if (pressed) {
11940             drawableHotspotChanged(x, y);
11941         }
11942 
11943         setPressed(pressed);
11944     }
11945 
11946     /**
11947      * Sets the pressed state for this view.
11948      *
11949      * @see #isClickable()
11950      * @see #setClickable(boolean)
11951      *
11952      * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
11953      *        the View's internal state from a previously set "pressed" state.
11954      */
11955     public void setPressed(boolean pressed) {
11956         final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
11957 
11958         if (pressed) {
11959             mPrivateFlags |= PFLAG_PRESSED;
11960         } else {
11961             mPrivateFlags &= ~PFLAG_PRESSED;
11962         }
11963 
11964         if (needsRefresh) {
11965             refreshDrawableState();
11966         }
11967         dispatchSetPressed(pressed);
11968     }
11969 
11970     /**
11971      * Dispatch setPressed to all of this View's children.
11972      *
11973      * @see #setPressed(boolean)
11974      *
11975      * @param pressed The new pressed state
11976      */
11977     protected void dispatchSetPressed(boolean pressed) {
11978     }
11979 
11980     /**
11981      * Indicates whether the view is currently in pressed state. Unless
11982      * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
11983      * the pressed state.
11984      *
11985      * @see #setPressed(boolean)
11986      * @see #isClickable()
11987      * @see #setClickable(boolean)
11988      *
11989      * @return true if the view is currently pressed, false otherwise
11990      */
11991     @ViewDebug.ExportedProperty
11992     @InspectableProperty(hasAttributeId = false)
11993     public boolean isPressed() {
11994         return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
11995     }
11996 
11997     /**
11998      * @hide
11999      * Indicates whether this view will participate in data collection through
12000      * {@link ViewStructure}.  If true, it will not provide any data
12001      * for itself or its children.  If false, the normal data collection will be allowed.
12002      *
12003      * @return Returns false if assist data collection is not blocked, else true.
12004      *
12005      * @see #setAssistBlocked(boolean)
12006      * @attr ref android.R.styleable#View_assistBlocked
12007      */
12008     public boolean isAssistBlocked() {
12009         return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
12010     }
12011 
12012     /**
12013      * @hide
12014      * Controls whether assist data collection from this view and its children is enabled
12015      * (that is, whether {@link #onProvideStructure} and
12016      * {@link #onProvideVirtualStructure} will be called).  The default value is false,
12017      * allowing normal assist collection.  Setting this to false will disable assist collection.
12018      *
12019      * @param enabled Set to true to <em>disable</em> assist data collection, or false
12020      * (the default) to allow it.
12021      *
12022      * @see #isAssistBlocked()
12023      * @see #onProvideStructure
12024      * @see #onProvideVirtualStructure
12025      * @attr ref android.R.styleable#View_assistBlocked
12026      */
12027     @UnsupportedAppUsage
12028     public void setAssistBlocked(boolean enabled) {
12029         if (enabled) {
12030             mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
12031         } else {
12032             mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
12033         }
12034     }
12035 
12036     /**
12037      * Indicates whether this view will save its state (that is,
12038      * whether its {@link #onSaveInstanceState} method will be called).
12039      *
12040      * @return Returns true if the view state saving is enabled, else false.
12041      *
12042      * @see #setSaveEnabled(boolean)
12043      * @attr ref android.R.styleable#View_saveEnabled
12044      */
12045     @InspectableProperty
12046     public boolean isSaveEnabled() {
12047         return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
12048     }
12049 
12050     /**
12051      * Controls whether the saving of this view's state is
12052      * enabled (that is, whether its {@link #onSaveInstanceState} method
12053      * will be called).  Note that even if freezing is enabled, the
12054      * view still must have an id assigned to it (via {@link #setId(int)})
12055      * for its state to be saved.  This flag can only disable the
12056      * saving of this view; any child views may still have their state saved.
12057      *
12058      * @param enabled Set to false to <em>disable</em> state saving, or true
12059      * (the default) to allow it.
12060      *
12061      * @see #isSaveEnabled()
12062      * @see #setId(int)
12063      * @see #onSaveInstanceState()
12064      * @attr ref android.R.styleable#View_saveEnabled
12065      */
12066     public void setSaveEnabled(boolean enabled) {
12067         setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
12068     }
12069 
12070     /**
12071      * Gets whether the framework should discard touches when the view's
12072      * window is obscured by another visible window.
12073      * Refer to the {@link View} security documentation for more details.
12074      *
12075      * @return True if touch filtering is enabled.
12076      *
12077      * @see #setFilterTouchesWhenObscured(boolean)
12078      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
12079      */
12080     @ViewDebug.ExportedProperty
12081     @InspectableProperty
12082     public boolean getFilterTouchesWhenObscured() {
12083         return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
12084     }
12085 
12086     /**
12087      * Sets whether the framework should discard touches when the view's
12088      * window is obscured by another visible window.
12089      * Refer to the {@link View} security documentation for more details.
12090      *
12091      * @param enabled True if touch filtering should be enabled.
12092      *
12093      * @see #getFilterTouchesWhenObscured
12094      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
12095      */
12096     public void setFilterTouchesWhenObscured(boolean enabled) {
12097         setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
12098                 FILTER_TOUCHES_WHEN_OBSCURED);
12099     }
12100 
12101     /**
12102      * Indicates whether the entire hierarchy under this view will save its
12103      * state when a state saving traversal occurs from its parent.  The default
12104      * is true; if false, these views will not be saved unless
12105      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
12106      *
12107      * @return Returns true if the view state saving from parent is enabled, else false.
12108      *
12109      * @see #setSaveFromParentEnabled(boolean)
12110      */
12111     public boolean isSaveFromParentEnabled() {
12112         return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
12113     }
12114 
12115     /**
12116      * Controls whether the entire hierarchy under this view will save its
12117      * state when a state saving traversal occurs from its parent.  The default
12118      * is true; if false, these views will not be saved unless
12119      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
12120      *
12121      * @param enabled Set to false to <em>disable</em> state saving, or true
12122      * (the default) to allow it.
12123      *
12124      * @see #isSaveFromParentEnabled()
12125      * @see #setId(int)
12126      * @see #onSaveInstanceState()
12127      */
12128     public void setSaveFromParentEnabled(boolean enabled) {
12129         setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
12130     }
12131 
12132 
12133     /**
12134      * Returns whether this View is currently able to take focus.
12135      *
12136      * @return True if this view can take focus, or false otherwise.
12137      */
12138     @ViewDebug.ExportedProperty(category = "focus")
12139     public final boolean isFocusable() {
12140         return FOCUSABLE == (mViewFlags & FOCUSABLE);
12141     }
12142 
12143     /**
12144      * Returns the focusable setting for this view.
12145      *
12146      * @return One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE}, or {@link #FOCUSABLE_AUTO}.
12147      * @attr ref android.R.styleable#View_focusable
12148      */
12149     @ViewDebug.ExportedProperty(mapping = {
12150             @ViewDebug.IntToString(from = NOT_FOCUSABLE, to = "NOT_FOCUSABLE"),
12151             @ViewDebug.IntToString(from = FOCUSABLE, to = "FOCUSABLE"),
12152             @ViewDebug.IntToString(from = FOCUSABLE_AUTO, to = "FOCUSABLE_AUTO")
12153             }, category = "focus")
12154     @InspectableProperty(enumMapping = {
12155             @EnumEntry(value = NOT_FOCUSABLE, name = "false"),
12156             @EnumEntry(value = FOCUSABLE, name = "true"),
12157             @EnumEntry(value = FOCUSABLE_AUTO, name = "auto")
12158     })
12159     @Focusable
12160     public int getFocusable() {
12161         return (mViewFlags & FOCUSABLE_AUTO) > 0 ? FOCUSABLE_AUTO : mViewFlags & FOCUSABLE;
12162     }
12163 
12164     /**
12165      * When a view is focusable, it may not want to take focus when in touch mode.
12166      * For example, a button would like focus when the user is navigating via a D-pad
12167      * so that the user can click on it, but once the user starts touching the screen,
12168      * the button shouldn't take focus
12169      * @return Whether the view is focusable in touch mode.
12170      * @attr ref android.R.styleable#View_focusableInTouchMode
12171      */
12172     @ViewDebug.ExportedProperty(category = "focus")
12173     @InspectableProperty
12174     public final boolean isFocusableInTouchMode() {
12175         return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
12176     }
12177 
12178     /**
12179      * Returns whether the view should be treated as a focusable unit by screen reader
12180      * accessibility tools.
12181      * @see #setScreenReaderFocusable(boolean)
12182      *
12183      * @return Whether the view should be treated as a focusable unit by screen reader.
12184      *
12185      * @attr ref android.R.styleable#View_screenReaderFocusable
12186      */
12187     @InspectableProperty
12188     public boolean isScreenReaderFocusable() {
12189         return (mPrivateFlags3 & PFLAG3_SCREEN_READER_FOCUSABLE) != 0;
12190     }
12191 
12192     /**
12193      * Sets whether this View should be a focusable element for screen readers
12194      * and include non-focusable Views from its subtree when providing feedback.
12195      * <p>
12196      * Note: this is similar to using <a href="#attr_android:focusable">{@code android:focusable},
12197      * but does not impact input focus behavior.
12198      *
12199      * @param screenReaderFocusable Whether the view should be treated as a unit by screen reader
12200      *                              accessibility tools.
12201      *
12202      * @attr ref android.R.styleable#View_screenReaderFocusable
12203      */
12204     public void setScreenReaderFocusable(boolean screenReaderFocusable) {
12205         updatePflags3AndNotifyA11yIfChanged(PFLAG3_SCREEN_READER_FOCUSABLE, screenReaderFocusable);
12206     }
12207 
12208     /**
12209      * Gets whether this view is a heading for accessibility purposes.
12210      *
12211      * @return {@code true} if the view is a heading, {@code false} otherwise.
12212      *
12213      * @attr ref android.R.styleable#View_accessibilityHeading
12214      */
12215     @InspectableProperty
12216     public boolean isAccessibilityHeading() {
12217         return (mPrivateFlags3 & PFLAG3_ACCESSIBILITY_HEADING) != 0;
12218     }
12219 
12220     /**
12221      * Set if view is a heading for a section of content for accessibility purposes.
12222      *
12223      * @param isHeading {@code true} if the view is a heading, {@code false} otherwise.
12224      *
12225      * @attr ref android.R.styleable#View_accessibilityHeading
12226      */
12227     public void setAccessibilityHeading(boolean isHeading) {
12228         updatePflags3AndNotifyA11yIfChanged(PFLAG3_ACCESSIBILITY_HEADING, isHeading);
12229     }
12230 
12231     private void updatePflags3AndNotifyA11yIfChanged(int mask, boolean newValue) {
12232         int pflags3 = mPrivateFlags3;
12233         if (newValue) {
12234             pflags3 |= mask;
12235         } else {
12236             pflags3 &= ~mask;
12237         }
12238 
12239         if (pflags3 != mPrivateFlags3) {
12240             mPrivateFlags3 = pflags3;
12241             notifyViewAccessibilityStateChangedIfNeeded(
12242                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
12243         }
12244     }
12245 
12246     /**
12247      * Find the nearest view in the specified direction that can take focus.
12248      * This does not actually give focus to that view.
12249      *
12250      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
12251      *
12252      * @return The nearest focusable in the specified direction, or null if none
12253      *         can be found.
12254      */
12255     public View focusSearch(@FocusRealDirection int direction) {
12256         if (mParent != null) {
12257             return mParent.focusSearch(this, direction);
12258         } else {
12259             return null;
12260         }
12261     }
12262 
12263     /**
12264      * Returns whether this View is a root of a keyboard navigation cluster.
12265      *
12266      * @return True if this view is a root of a cluster, or false otherwise.
12267      * @attr ref android.R.styleable#View_keyboardNavigationCluster
12268      */
12269     @ViewDebug.ExportedProperty(category = "focus")
12270     @InspectableProperty
12271     public final boolean isKeyboardNavigationCluster() {
12272         return (mPrivateFlags3 & PFLAG3_CLUSTER) != 0;
12273     }
12274 
12275     /**
12276      * Searches up the view hierarchy to find the top-most cluster. All deeper/nested clusters
12277      * will be ignored.
12278      *
12279      * @return the keyboard navigation cluster that this view is in (can be this view)
12280      *         or {@code null} if not in one
12281      */
12282     View findKeyboardNavigationCluster() {
12283         if (mParent instanceof View) {
12284             View cluster = ((View) mParent).findKeyboardNavigationCluster();
12285             if (cluster != null) {
12286                 return cluster;
12287             } else if (isKeyboardNavigationCluster()) {
12288                 return this;
12289             }
12290         }
12291         return null;
12292     }
12293 
12294     /**
12295      * Set whether this view is a root of a keyboard navigation cluster.
12296      *
12297      * @param isCluster If true, this view is a root of a cluster.
12298      *
12299      * @attr ref android.R.styleable#View_keyboardNavigationCluster
12300      */
12301     public void setKeyboardNavigationCluster(boolean isCluster) {
12302         if (isCluster) {
12303             mPrivateFlags3 |= PFLAG3_CLUSTER;
12304         } else {
12305             mPrivateFlags3 &= ~PFLAG3_CLUSTER;
12306         }
12307     }
12308 
12309     /**
12310      * Sets this View as the one which receives focus the next time cluster navigation jumps
12311      * to the cluster containing this View. This does NOT change focus even if the cluster
12312      * containing this view is current.
12313      *
12314      * @hide
12315      */
12316     @TestApi
12317     public final void setFocusedInCluster() {
12318         setFocusedInCluster(findKeyboardNavigationCluster());
12319     }
12320 
12321     private void setFocusedInCluster(View cluster) {
12322         if (this instanceof ViewGroup) {
12323             ((ViewGroup) this).mFocusedInCluster = null;
12324         }
12325         if (cluster == this) {
12326             return;
12327         }
12328         ViewParent parent = mParent;
12329         View child = this;
12330         while (parent instanceof ViewGroup) {
12331             ((ViewGroup) parent).mFocusedInCluster = child;
12332             if (parent == cluster) {
12333                 break;
12334             }
12335             child = (View) parent;
12336             parent = parent.getParent();
12337         }
12338     }
12339 
12340     private void updateFocusedInCluster(View oldFocus, @FocusDirection int direction) {
12341         if (oldFocus != null) {
12342             View oldCluster = oldFocus.findKeyboardNavigationCluster();
12343             View cluster = findKeyboardNavigationCluster();
12344             if (oldCluster != cluster) {
12345                 // Going from one cluster to another, so save last-focused.
12346                 // This covers cluster jumps because they are always FOCUS_DOWN
12347                 oldFocus.setFocusedInCluster(oldCluster);
12348                 if (!(oldFocus.mParent instanceof ViewGroup)) {
12349                     return;
12350                 }
12351                 if (direction == FOCUS_FORWARD || direction == FOCUS_BACKWARD) {
12352                     // This is a result of ordered navigation so consider navigation through
12353                     // the previous cluster "complete" and clear its last-focused memory.
12354                     ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
12355                 } else if (oldFocus instanceof ViewGroup
12356                         && ((ViewGroup) oldFocus).getDescendantFocusability()
12357                                 == ViewGroup.FOCUS_AFTER_DESCENDANTS
12358                         && ViewRootImpl.isViewDescendantOf(this, oldFocus)) {
12359                     // This means oldFocus is not focusable since it obviously has a focusable
12360                     // child (this). Don't restore focus to it in the future.
12361                     ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
12362                 }
12363             }
12364         }
12365     }
12366 
12367     /**
12368      * Returns whether this View should receive focus when the focus is restored for the view
12369      * hierarchy containing this view.
12370      * <p>
12371      * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
12372      * window or serves as a target of cluster navigation.
12373      *
12374      * @see #restoreDefaultFocus()
12375      *
12376      * @return {@code true} if this view is the default-focus view, {@code false} otherwise
12377      * @attr ref android.R.styleable#View_focusedByDefault
12378      */
12379     @ViewDebug.ExportedProperty(category = "focus")
12380     @InspectableProperty
12381     public final boolean isFocusedByDefault() {
12382         return (mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0;
12383     }
12384 
12385     /**
12386      * Sets whether this View should receive focus when the focus is restored for the view
12387      * hierarchy containing this view.
12388      * <p>
12389      * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
12390      * window or serves as a target of cluster navigation.
12391      *
12392      * @param isFocusedByDefault {@code true} to set this view as the default-focus view,
12393      *                           {@code false} otherwise.
12394      *
12395      * @see #restoreDefaultFocus()
12396      *
12397      * @attr ref android.R.styleable#View_focusedByDefault
12398      */
12399     public void setFocusedByDefault(boolean isFocusedByDefault) {
12400         if (isFocusedByDefault == ((mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0)) {
12401             return;
12402         }
12403 
12404         if (isFocusedByDefault) {
12405             mPrivateFlags3 |= PFLAG3_FOCUSED_BY_DEFAULT;
12406         } else {
12407             mPrivateFlags3 &= ~PFLAG3_FOCUSED_BY_DEFAULT;
12408         }
12409 
12410         if (mParent instanceof ViewGroup) {
12411             if (isFocusedByDefault) {
12412                 ((ViewGroup) mParent).setDefaultFocus(this);
12413             } else {
12414                 ((ViewGroup) mParent).clearDefaultFocus(this);
12415             }
12416         }
12417     }
12418 
12419     /**
12420      * Returns whether the view hierarchy with this view as a root contain a default-focus view.
12421      *
12422      * @return {@code true} if this view has default focus, {@code false} otherwise
12423      */
12424     boolean hasDefaultFocus() {
12425         return isFocusedByDefault();
12426     }
12427 
12428     /**
12429      * Find the nearest keyboard navigation cluster in the specified direction.
12430      * This does not actually give focus to that cluster.
12431      *
12432      * @param currentCluster The starting point of the search. Null means the current cluster is not
12433      *                       found yet
12434      * @param direction Direction to look
12435      *
12436      * @return The nearest keyboard navigation cluster in the specified direction, or null if none
12437      *         can be found
12438      */
12439     public View keyboardNavigationClusterSearch(View currentCluster,
12440             @FocusDirection int direction) {
12441         if (isKeyboardNavigationCluster()) {
12442             currentCluster = this;
12443         }
12444         if (isRootNamespace()) {
12445             // Root namespace means we should consider ourselves the top of the
12446             // tree for group searching; otherwise we could be group searching
12447             // into other tabs.  see LocalActivityManager and TabHost for more info.
12448             return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
12449                     this, currentCluster, direction);
12450         } else if (mParent != null) {
12451             return mParent.keyboardNavigationClusterSearch(currentCluster, direction);
12452         }
12453         return null;
12454     }
12455 
12456     /**
12457      * This method is the last chance for the focused view and its ancestors to
12458      * respond to an arrow key. This is called when the focused view did not
12459      * consume the key internally, nor could the view system find a new view in
12460      * the requested direction to give focus to.
12461      *
12462      * @param focused The currently focused view.
12463      * @param direction The direction focus wants to move. One of FOCUS_UP,
12464      *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
12465      * @return True if the this view consumed this unhandled move.
12466      */
12467     public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
12468         return false;
12469     }
12470 
12471     /**
12472      * Sets whether this View should use a default focus highlight when it gets focused but doesn't
12473      * have {@link android.R.attr#state_focused} defined in its background.
12474      *
12475      * @param defaultFocusHighlightEnabled {@code true} to set this view to use a default focus
12476      *                                      highlight, {@code false} otherwise.
12477      *
12478      * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
12479      */
12480     public void setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled) {
12481         mDefaultFocusHighlightEnabled = defaultFocusHighlightEnabled;
12482     }
12483 
12484     /**
12485 
12486     /**
12487      * Returns whether this View should use a default focus highlight when it gets focused but
12488      * doesn't have {@link android.R.attr#state_focused} defined in its background.
12489      *
12490      * @return True if this View should use a default focus highlight.
12491      * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
12492      */
12493     @ViewDebug.ExportedProperty(category = "focus")
12494     @InspectableProperty
12495     public final boolean getDefaultFocusHighlightEnabled() {
12496         return mDefaultFocusHighlightEnabled;
12497     }
12498 
12499     /**
12500      * If a user manually specified the next view id for a particular direction,
12501      * use the root to look up the view.
12502      * @param root The root view of the hierarchy containing this view.
12503      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
12504      * or FOCUS_BACKWARD.
12505      * @return The user specified next view, or null if there is none.
12506      */
12507     View findUserSetNextFocus(View root, @FocusDirection int direction) {
12508         switch (direction) {
12509             case FOCUS_LEFT:
12510                 if (mNextFocusLeftId == View.NO_ID) return null;
12511                 return findViewInsideOutShouldExist(root, mNextFocusLeftId);
12512             case FOCUS_RIGHT:
12513                 if (mNextFocusRightId == View.NO_ID) return null;
12514                 return findViewInsideOutShouldExist(root, mNextFocusRightId);
12515             case FOCUS_UP:
12516                 if (mNextFocusUpId == View.NO_ID) return null;
12517                 return findViewInsideOutShouldExist(root, mNextFocusUpId);
12518             case FOCUS_DOWN:
12519                 if (mNextFocusDownId == View.NO_ID) return null;
12520                 return findViewInsideOutShouldExist(root, mNextFocusDownId);
12521             case FOCUS_FORWARD:
12522                 if (mNextFocusForwardId == View.NO_ID) return null;
12523                 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
12524             case FOCUS_BACKWARD: {
12525                 if (mID == View.NO_ID) return null;
12526                 final int id = mID;
12527                 return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
12528                     @Override
12529                     public boolean test(View t) {
12530                         return t.mNextFocusForwardId == id;
12531                     }
12532                 });
12533             }
12534         }
12535         return null;
12536     }
12537 
12538     /**
12539      * If a user manually specified the next keyboard-navigation cluster for a particular direction,
12540      * use the root to look up the view.
12541      *
12542      * @param root the root view of the hierarchy containing this view
12543      * @param direction {@link #FOCUS_FORWARD} or {@link #FOCUS_BACKWARD}
12544      * @return the user-specified next cluster, or {@code null} if there is none
12545      */
12546     View findUserSetNextKeyboardNavigationCluster(View root, @FocusDirection int direction) {
12547         switch (direction) {
12548             case FOCUS_FORWARD:
12549                 if (mNextClusterForwardId == View.NO_ID) return null;
12550                 return findViewInsideOutShouldExist(root, mNextClusterForwardId);
12551             case FOCUS_BACKWARD: {
12552                 if (mID == View.NO_ID) return null;
12553                 final int id = mID;
12554                 return root.findViewByPredicateInsideOut(this,
12555                         (Predicate<View>) t -> t.mNextClusterForwardId == id);
12556             }
12557         }
12558         return null;
12559     }
12560 
12561     private View findViewInsideOutShouldExist(View root, int id) {
12562         if (mMatchIdPredicate == null) {
12563             mMatchIdPredicate = new MatchIdPredicate();
12564         }
12565         mMatchIdPredicate.mId = id;
12566         View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
12567         if (result == null) {
12568             Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
12569         }
12570         return result;
12571     }
12572 
12573     /**
12574      * Find and return all focusable views that are descendants of this view,
12575      * possibly including this view if it is focusable itself.
12576      *
12577      * @param direction The direction of the focus
12578      * @return A list of focusable views
12579      */
12580     public ArrayList<View> getFocusables(@FocusDirection int direction) {
12581         ArrayList<View> result = new ArrayList<View>(24);
12582         addFocusables(result, direction);
12583         return result;
12584     }
12585 
12586     /**
12587      * Add any focusable views that are descendants of this view (possibly
12588      * including this view if it is focusable itself) to views.  If we are in touch mode,
12589      * only add views that are also focusable in touch mode.
12590      *
12591      * @param views Focusable views found so far
12592      * @param direction The direction of the focus
12593      */
12594     public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
12595         addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
12596     }
12597 
12598     /**
12599      * Adds any focusable views that are descendants of this view (possibly
12600      * including this view if it is focusable itself) to views. This method
12601      * adds all focusable views regardless if we are in touch mode or
12602      * only views focusable in touch mode if we are in touch mode or
12603      * only views that can take accessibility focus if accessibility is enabled
12604      * depending on the focusable mode parameter.
12605      *
12606      * @param views Focusable views found so far or null if all we are interested is
12607      *        the number of focusables.
12608      * @param direction The direction of the focus.
12609      * @param focusableMode The type of focusables to be added.
12610      *
12611      * @see #FOCUSABLES_ALL
12612      * @see #FOCUSABLES_TOUCH_MODE
12613      */
12614     public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
12615             @FocusableMode int focusableMode) {
12616         if (views == null) {
12617             return;
12618         }
12619         if (!canTakeFocus()) {
12620             return;
12621         }
12622         if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
12623                 && !isFocusableInTouchMode()) {
12624             return;
12625         }
12626         views.add(this);
12627     }
12628 
12629     /**
12630      * Adds any keyboard navigation cluster roots that are descendants of this view (possibly
12631      * including this view if it is a cluster root itself) to views.
12632      *
12633      * @param views Keyboard navigation cluster roots found so far
12634      * @param direction Direction to look
12635      */
12636     public void addKeyboardNavigationClusters(
12637             @NonNull Collection<View> views,
12638             int direction) {
12639         if (!isKeyboardNavigationCluster()) {
12640             return;
12641         }
12642         if (!hasFocusable()) {
12643             return;
12644         }
12645         views.add(this);
12646     }
12647 
12648     /**
12649      * Finds the Views that contain given text. The containment is case insensitive.
12650      * The search is performed by either the text that the View renders or the content
12651      * description that describes the view for accessibility purposes and the view does
12652      * not render or both. Clients can specify how the search is to be performed via
12653      * passing the {@link #FIND_VIEWS_WITH_TEXT} and
12654      * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
12655      *
12656      * @param outViews The output list of matching Views.
12657      * @param searched The text to match against.
12658      *
12659      * @see #FIND_VIEWS_WITH_TEXT
12660      * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
12661      * @see #setContentDescription(CharSequence)
12662      */
12663     public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
12664             @FindViewFlags int flags) {
12665         if (getAccessibilityNodeProvider() != null) {
12666             if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
12667                 outViews.add(this);
12668             }
12669         } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
12670                 && (searched != null && searched.length() > 0)
12671                 && (mContentDescription != null && mContentDescription.length() > 0)) {
12672             String searchedLowerCase = searched.toString().toLowerCase();
12673             String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
12674             if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
12675                 outViews.add(this);
12676             }
12677         }
12678     }
12679 
12680     /**
12681      * Find and return all touchable views that are descendants of this view,
12682      * possibly including this view if it is touchable itself.
12683      *
12684      * @return A list of touchable views
12685      */
12686     public ArrayList<View> getTouchables() {
12687         ArrayList<View> result = new ArrayList<View>();
12688         addTouchables(result);
12689         return result;
12690     }
12691 
12692     /**
12693      * Add any touchable views that are descendants of this view (possibly
12694      * including this view if it is touchable itself) to views.
12695      *
12696      * @param views Touchable views found so far
12697      */
12698     public void addTouchables(ArrayList<View> views) {
12699         final int viewFlags = mViewFlags;
12700 
12701         if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
12702                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
12703                 && (viewFlags & ENABLED_MASK) == ENABLED) {
12704             views.add(this);
12705         }
12706     }
12707 
12708     /**
12709      * Returns whether this View is accessibility focused.
12710      *
12711      * @return True if this View is accessibility focused.
12712      */
12713     @InspectableProperty(hasAttributeId = false)
12714     public boolean isAccessibilityFocused() {
12715         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
12716     }
12717 
12718     /**
12719      * Call this to try to give accessibility focus to this view.
12720      *
12721      * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
12722      * returns false or the view is no visible or the view already has accessibility
12723      * focus.
12724      *
12725      * See also {@link #focusSearch(int)}, which is what you call to say that you
12726      * have focus, and you want your parent to look for the next one.
12727      *
12728      * @return Whether this view actually took accessibility focus.
12729      *
12730      * @hide
12731      */
12732     @UnsupportedAppUsage
12733     public boolean requestAccessibilityFocus() {
12734         AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
12735         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
12736             return false;
12737         }
12738         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
12739             return false;
12740         }
12741         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
12742             mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
12743             ViewRootImpl viewRootImpl = getViewRootImpl();
12744             if (viewRootImpl != null) {
12745                 viewRootImpl.setAccessibilityFocus(this, null);
12746             }
12747             invalidate();
12748             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
12749             return true;
12750         }
12751         return false;
12752     }
12753 
12754     /**
12755      * Call this to try to clear accessibility focus of this view.
12756      *
12757      * See also {@link #focusSearch(int)}, which is what you call to say that you
12758      * have focus, and you want your parent to look for the next one.
12759      *
12760      * @hide
12761      */
12762     @UnsupportedAppUsage
12763     public void clearAccessibilityFocus() {
12764         clearAccessibilityFocusNoCallbacks(0);
12765 
12766         // Clear the global reference of accessibility focus if this view or
12767         // any of its descendants had accessibility focus. This will NOT send
12768         // an event or update internal state if focus is cleared from a
12769         // descendant view, which may leave views in inconsistent states.
12770         final ViewRootImpl viewRootImpl = getViewRootImpl();
12771         if (viewRootImpl != null) {
12772             final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
12773             if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
12774                 viewRootImpl.setAccessibilityFocus(null, null);
12775             }
12776         }
12777     }
12778 
12779     private void sendAccessibilityHoverEvent(int eventType) {
12780         // Since we are not delivering to a client accessibility events from not
12781         // important views (unless the clinet request that) we need to fire the
12782         // event from the deepest view exposed to the client. As a consequence if
12783         // the user crosses a not exposed view the client will see enter and exit
12784         // of the exposed predecessor followed by and enter and exit of that same
12785         // predecessor when entering and exiting the not exposed descendant. This
12786         // is fine since the client has a clear idea which view is hovered at the
12787         // price of a couple more events being sent. This is a simple and
12788         // working solution.
12789         View source = this;
12790         while (true) {
12791             if (source.includeForAccessibility()) {
12792                 source.sendAccessibilityEvent(eventType);
12793                 return;
12794             }
12795             ViewParent parent = source.getParent();
12796             if (parent instanceof View) {
12797                 source = (View) parent;
12798             } else {
12799                 return;
12800             }
12801         }
12802     }
12803 
12804     /**
12805      * Clears accessibility focus without calling any callback methods
12806      * normally invoked in {@link #clearAccessibilityFocus()}. This method
12807      * is used separately from that one for clearing accessibility focus when
12808      * giving this focus to another view.
12809      *
12810      * @param action The action, if any, that led to focus being cleared. Set to
12811      * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
12812      * the window.
12813      */
12814     void clearAccessibilityFocusNoCallbacks(int action) {
12815         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
12816             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
12817             invalidate();
12818             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
12819                 AccessibilityEvent event = AccessibilityEvent.obtain(
12820                         AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
12821                 event.setAction(action);
12822                 if (mAccessibilityDelegate != null) {
12823                     mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
12824                 } else {
12825                     sendAccessibilityEventUnchecked(event);
12826                 }
12827             }
12828         }
12829     }
12830 
12831     /**
12832      * Call this to try to give focus to a specific view or to one of its
12833      * descendants.
12834      *
12835      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
12836      * false), or if it can't be focused due to other conditions (not focusable in touch mode
12837      * ({@link #isFocusableInTouchMode}) while the device is in touch mode, not visible, not
12838      * enabled, or has no size).
12839      *
12840      * See also {@link #focusSearch(int)}, which is what you call to say that you
12841      * have focus, and you want your parent to look for the next one.
12842      *
12843      * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
12844      * {@link #FOCUS_DOWN} and <code>null</code>.
12845      *
12846      * @return Whether this view or one of its descendants actually took focus.
12847      */
12848     public final boolean requestFocus() {
12849         return requestFocus(View.FOCUS_DOWN);
12850     }
12851 
12852     /**
12853      * This will request focus for whichever View was last focused within this
12854      * cluster before a focus-jump out of it.
12855      *
12856      * @hide
12857      */
12858     @TestApi
12859     public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
12860         // Prioritize focusableByDefault over algorithmic focus selection.
12861         if (restoreDefaultFocus()) {
12862             return true;
12863         }
12864         return requestFocus(direction);
12865     }
12866 
12867     /**
12868      * This will request focus for whichever View not in a cluster was last focused before a
12869      * focus-jump to a cluster. If no non-cluster View has previously had focus, this will focus
12870      * the "first" focusable view it finds.
12871      *
12872      * @hide
12873      */
12874     @TestApi
12875     public boolean restoreFocusNotInCluster() {
12876         return requestFocus(View.FOCUS_DOWN);
12877     }
12878 
12879     /**
12880      * Gives focus to the default-focus view in the view hierarchy that has this view as a root.
12881      * If the default-focus view cannot be found, falls back to calling {@link #requestFocus(int)}.
12882      *
12883      * @return Whether this view or one of its descendants actually took focus
12884      */
12885     public boolean restoreDefaultFocus() {
12886         return requestFocus(View.FOCUS_DOWN);
12887     }
12888 
12889     /**
12890      * Call this to try to give focus to a specific view or to one of its
12891      * descendants and give it a hint about what direction focus is heading.
12892      *
12893      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
12894      * false), or if it is focusable and it is not focusable in touch mode
12895      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
12896      *
12897      * See also {@link #focusSearch(int)}, which is what you call to say that you
12898      * have focus, and you want your parent to look for the next one.
12899      *
12900      * This is equivalent to calling {@link #requestFocus(int, Rect)} with
12901      * <code>null</code> set for the previously focused rectangle.
12902      *
12903      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
12904      * @return Whether this view or one of its descendants actually took focus.
12905      */
12906     public final boolean requestFocus(int direction) {
12907         return requestFocus(direction, null);
12908     }
12909 
12910     /**
12911      * Call this to try to give focus to a specific view or to one of its descendants
12912      * and give it hints about the direction and a specific rectangle that the focus
12913      * is coming from.  The rectangle can help give larger views a finer grained hint
12914      * about where focus is coming from, and therefore, where to show selection, or
12915      * forward focus change internally.
12916      *
12917      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
12918      * false), or if it is focusable and it is not focusable in touch mode
12919      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
12920      *
12921      * A View will not take focus if it is not visible.
12922      *
12923      * A View will not take focus if one of its parents has
12924      * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
12925      * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
12926      *
12927      * See also {@link #focusSearch(int)}, which is what you call to say that you
12928      * have focus, and you want your parent to look for the next one.
12929      *
12930      * You may wish to override this method if your custom {@link View} has an internal
12931      * {@link View} that it wishes to forward the request to.
12932      *
12933      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
12934      * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
12935      *        to give a finer grained hint about where focus is coming from.  May be null
12936      *        if there is no hint.
12937      * @return Whether this view or one of its descendants actually took focus.
12938      */
12939     public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
12940         return requestFocusNoSearch(direction, previouslyFocusedRect);
12941     }
12942 
12943     private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
12944         // need to be focusable
12945         if (!canTakeFocus()) {
12946             return false;
12947         }
12948 
12949         // need to be focusable in touch mode if in touch mode
12950         if (isInTouchMode() &&
12951             (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
12952                return false;
12953         }
12954 
12955         // need to not have any parents blocking us
12956         if (hasAncestorThatBlocksDescendantFocus()) {
12957             return false;
12958         }
12959 
12960         if (!isLayoutValid()) {
12961             mPrivateFlags |= PFLAG_WANTS_FOCUS;
12962         } else {
12963             clearParentsWantFocus();
12964         }
12965 
12966         handleFocusGainInternal(direction, previouslyFocusedRect);
12967         return true;
12968     }
12969 
12970     void clearParentsWantFocus() {
12971         if (mParent instanceof View) {
12972             ((View) mParent).mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
12973             ((View) mParent).clearParentsWantFocus();
12974         }
12975     }
12976 
12977     /**
12978      * Call this to try to give focus to a specific view or to one of its descendants. This is a
12979      * special variant of {@link #requestFocus() } that will allow views that are not focusable in
12980      * touch mode to request focus when they are touched.
12981      *
12982      * @return Whether this view or one of its descendants actually took focus.
12983      *
12984      * @see #isInTouchMode()
12985      *
12986      */
12987     public final boolean requestFocusFromTouch() {
12988         // Leave touch mode if we need to
12989         if (isInTouchMode()) {
12990             ViewRootImpl viewRoot = getViewRootImpl();
12991             if (viewRoot != null) {
12992                 viewRoot.ensureTouchMode(false);
12993             }
12994         }
12995         return requestFocus(View.FOCUS_DOWN);
12996     }
12997 
12998     /**
12999      * @return Whether any ancestor of this view blocks descendant focus.
13000      */
13001     private boolean hasAncestorThatBlocksDescendantFocus() {
13002         final boolean focusableInTouchMode = isFocusableInTouchMode();
13003         ViewParent ancestor = mParent;
13004         while (ancestor instanceof ViewGroup) {
13005             final ViewGroup vgAncestor = (ViewGroup) ancestor;
13006             if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
13007                     || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
13008                 return true;
13009             } else {
13010                 ancestor = vgAncestor.getParent();
13011             }
13012         }
13013         return false;
13014     }
13015 
13016     /**
13017      * Gets the mode for determining whether this View is important for accessibility.
13018      * A view is important for accessibility if it fires accessibility events and if it
13019      * is reported to accessibility services that query the screen.
13020      *
13021      * @return The mode for determining whether a view is important for accessibility, one
13022      * of {@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, {@link #IMPORTANT_FOR_ACCESSIBILITY_YES},
13023      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO}, or
13024      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}.
13025      *
13026      * @attr ref android.R.styleable#View_importantForAccessibility
13027      *
13028      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
13029      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
13030      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
13031      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
13032      */
13033     @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
13034             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
13035             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
13036             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
13037             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
13038                     to = "noHideDescendants")
13039         })
13040     @InspectableProperty(enumMapping = {
13041             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_AUTO, name = "auto"),
13042             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_YES, name = "yes"),
13043             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_NO, name = "no"),
13044             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
13045                     name = "noHideDescendants"),
13046     })
13047     public int getImportantForAccessibility() {
13048         return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
13049                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
13050     }
13051 
13052     /**
13053      * Sets the live region mode for this view. This indicates to accessibility
13054      * services whether they should automatically notify the user about changes
13055      * to the view's content description or text, or to the content descriptions
13056      * or text of the view's children (where applicable).
13057      * <p>
13058      * For example, in a login screen with a TextView that displays an "incorrect
13059      * password" notification, that view should be marked as a live region with
13060      * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
13061      * <p>
13062      * To disable change notifications for this view, use
13063      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
13064      * mode for most views.
13065      * <p>
13066      * To indicate that the user should be notified of changes, use
13067      * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
13068      * <p>
13069      * If the view's changes should interrupt ongoing speech and notify the user
13070      * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
13071      *
13072      * @param mode The live region mode for this view, one of:
13073      *        <ul>
13074      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
13075      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
13076      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
13077      *        </ul>
13078      * @attr ref android.R.styleable#View_accessibilityLiveRegion
13079      */
13080     public void setAccessibilityLiveRegion(int mode) {
13081         if (mode != getAccessibilityLiveRegion()) {
13082             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
13083             mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
13084                     & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
13085             notifyViewAccessibilityStateChangedIfNeeded(
13086                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
13087         }
13088     }
13089 
13090     /**
13091      * Gets the live region mode for this View.
13092      *
13093      * @return The live region mode for the view.
13094      *
13095      * @attr ref android.R.styleable#View_accessibilityLiveRegion
13096      *
13097      * @see #setAccessibilityLiveRegion(int)
13098      */
13099     @InspectableProperty(enumMapping = {
13100             @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_NONE, name = "none"),
13101             @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_POLITE, name = "polite"),
13102             @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_ASSERTIVE, name = "assertive")
13103     })
13104     public int getAccessibilityLiveRegion() {
13105         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
13106                 >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
13107     }
13108 
13109     /**
13110      * Sets how to determine whether this view is important for accessibility
13111      * which is if it fires accessibility events and if it is reported to
13112      * accessibility services that query the screen.
13113      *
13114      * @param mode How to determine whether this view is important for accessibility.
13115      *
13116      * @attr ref android.R.styleable#View_importantForAccessibility
13117      *
13118      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
13119      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
13120      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
13121      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
13122      */
13123     public void setImportantForAccessibility(int mode) {
13124         final int oldMode = getImportantForAccessibility();
13125         if (mode != oldMode) {
13126             final boolean hideDescendants =
13127                     mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
13128 
13129             // If this node or its descendants are no longer important, try to
13130             // clear accessibility focus.
13131             if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
13132                 final View focusHost = findAccessibilityFocusHost(hideDescendants);
13133                 if (focusHost != null) {
13134                     focusHost.clearAccessibilityFocus();
13135                 }
13136             }
13137 
13138             // If we're moving between AUTO and another state, we might not need
13139             // to send a subtree changed notification. We'll store the computed
13140             // importance, since we'll need to check it later to make sure.
13141             final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
13142                     || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
13143             final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
13144             mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
13145             mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
13146                     & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
13147             if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
13148                 notifySubtreeAccessibilityStateChangedIfNeeded();
13149             } else {
13150                 notifyViewAccessibilityStateChangedIfNeeded(
13151                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
13152             }
13153         }
13154     }
13155 
13156     /**
13157      * Returns the view within this view's hierarchy that is hosting
13158      * accessibility focus.
13159      *
13160      * @param searchDescendants whether to search for focus in descendant views
13161      * @return the view hosting accessibility focus, or {@code null}
13162      */
13163     private View findAccessibilityFocusHost(boolean searchDescendants) {
13164         if (isAccessibilityFocusedViewOrHost()) {
13165             return this;
13166         }
13167 
13168         if (searchDescendants) {
13169             final ViewRootImpl viewRoot = getViewRootImpl();
13170             if (viewRoot != null) {
13171                 final View focusHost = viewRoot.getAccessibilityFocusedHost();
13172                 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
13173                     return focusHost;
13174                 }
13175             }
13176         }
13177 
13178         return null;
13179     }
13180 
13181     /**
13182      * Computes whether this view should be exposed for accessibility. In
13183      * general, views that are interactive or provide information are exposed
13184      * while views that serve only as containers are hidden.
13185      * <p>
13186      * If an ancestor of this view has importance
13187      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
13188      * returns <code>false</code>.
13189      * <p>
13190      * Otherwise, the value is computed according to the view's
13191      * {@link #getImportantForAccessibility()} value:
13192      * <ol>
13193      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
13194      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
13195      * </code>
13196      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
13197      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
13198      * view satisfies any of the following:
13199      * <ul>
13200      * <li>Is actionable, e.g. {@link #isClickable()},
13201      * {@link #isLongClickable()}, or {@link #isFocusable()}
13202      * <li>Has an {@link AccessibilityDelegate}
13203      * <li>Has an interaction listener, e.g. {@link OnTouchListener},
13204      * {@link OnKeyListener}, etc.
13205      * <li>Is an accessibility live region, e.g.
13206      * {@link #getAccessibilityLiveRegion()} is not
13207      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
13208      * </ul>
13209      * <li>Has an accessibility pane title, see {@link #setAccessibilityPaneTitle}</li>
13210      * </ol>
13211      *
13212      * @return Whether the view is exposed for accessibility.
13213      * @see #setImportantForAccessibility(int)
13214      * @see #getImportantForAccessibility()
13215      */
13216     public boolean isImportantForAccessibility() {
13217         final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
13218                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
13219         if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
13220                 || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
13221             return false;
13222         }
13223 
13224         // Check parent mode to ensure we're not hidden.
13225         ViewParent parent = mParent;
13226         while (parent instanceof View) {
13227             if (((View) parent).getImportantForAccessibility()
13228                     == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
13229                 return false;
13230             }
13231             parent = parent.getParent();
13232         }
13233 
13234         return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
13235                 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
13236                 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE
13237                 || isAccessibilityPane();
13238     }
13239 
13240     /**
13241      * Gets the parent for accessibility purposes. Note that the parent for
13242      * accessibility is not necessary the immediate parent. It is the first
13243      * predecessor that is important for accessibility.
13244      *
13245      * @return The parent for accessibility purposes.
13246      */
13247     public ViewParent getParentForAccessibility() {
13248         if (mParent instanceof View) {
13249             View parentView = (View) mParent;
13250             if (parentView.includeForAccessibility()) {
13251                 return mParent;
13252             } else {
13253                 return mParent.getParentForAccessibility();
13254             }
13255         }
13256         return null;
13257     }
13258 
13259     /** @hide */
13260     View getSelfOrParentImportantForA11y() {
13261         if (isImportantForAccessibility()) return this;
13262         ViewParent parent = getParentForAccessibility();
13263         if (parent instanceof View) return (View) parent;
13264         return null;
13265     }
13266 
13267     /**
13268      * Adds the children of this View relevant for accessibility to the given list
13269      * as output. Since some Views are not important for accessibility the added
13270      * child views are not necessarily direct children of this view, rather they are
13271      * the first level of descendants important for accessibility.
13272      *
13273      * @param outChildren The output list that will receive children for accessibility.
13274      */
13275     public void addChildrenForAccessibility(ArrayList<View> outChildren) {
13276 
13277     }
13278 
13279     /**
13280      * Whether to regard this view for accessibility. A view is regarded for
13281      * accessibility if it is important for accessibility or the querying
13282      * accessibility service has explicitly requested that view not
13283      * important for accessibility are regarded.
13284      *
13285      * @return Whether to regard the view for accessibility.
13286      *
13287      * @hide
13288      */
13289     @UnsupportedAppUsage
13290     public boolean includeForAccessibility() {
13291         if (mAttachInfo != null) {
13292             return (mAttachInfo.mAccessibilityFetchFlags
13293                     & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
13294                     || isImportantForAccessibility();
13295         }
13296         return false;
13297     }
13298 
13299     /**
13300      * Returns whether the View is considered actionable from
13301      * accessibility perspective. Such view are important for
13302      * accessibility.
13303      *
13304      * @return True if the view is actionable for accessibility.
13305      *
13306      * @hide
13307      */
13308     public boolean isActionableForAccessibility() {
13309         return (isClickable() || isLongClickable() || isFocusable());
13310     }
13311 
13312     /**
13313      * Returns whether the View has registered callbacks which makes it
13314      * important for accessibility.
13315      *
13316      * @return True if the view is actionable for accessibility.
13317      */
13318     private boolean hasListenersForAccessibility() {
13319         ListenerInfo info = getListenerInfo();
13320         return mTouchDelegate != null || info.mOnKeyListener != null
13321                 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
13322                 || info.mOnHoverListener != null || info.mOnDragListener != null;
13323     }
13324 
13325     /**
13326      * Notifies that the accessibility state of this view changed. The change
13327      * is local to this view and does not represent structural changes such
13328      * as children and parent. For example, the view became focusable. The
13329      * notification is at at most once every
13330      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
13331      * to avoid unnecessary load to the system. Also once a view has a pending
13332      * notification this method is a NOP until the notification has been sent.
13333      *
13334      * @hide
13335      */
13336     @UnsupportedAppUsage
13337     public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
13338         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
13339             return;
13340         }
13341 
13342         // Changes to views with a pane title count as window state changes, as the pane title
13343         // marks them as significant parts of the UI.
13344         if ((changeType != AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE)
13345                 && isAccessibilityPane()) {
13346             // If the pane isn't visible, content changed events are sufficient unless we're
13347             // reporting that the view just disappeared
13348             if ((getVisibility() == VISIBLE)
13349                     || (changeType == AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED)) {
13350                 final AccessibilityEvent event = AccessibilityEvent.obtain();
13351                 onInitializeAccessibilityEvent(event);
13352                 event.setEventType(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
13353                 event.setContentChangeTypes(changeType);
13354                 event.setSource(this);
13355                 onPopulateAccessibilityEvent(event);
13356                 if (mParent != null) {
13357                     try {
13358                         mParent.requestSendAccessibilityEvent(this, event);
13359                     } catch (AbstractMethodError e) {
13360                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName()
13361                                 + " does not fully implement ViewParent", e);
13362                     }
13363                 }
13364                 return;
13365             }
13366         }
13367 
13368         // If this is a live region, we should send a subtree change event
13369         // from this view immediately. Otherwise, we can let it propagate up.
13370         if (getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE) {
13371             final AccessibilityEvent event = AccessibilityEvent.obtain();
13372             event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
13373             event.setContentChangeTypes(changeType);
13374             sendAccessibilityEventUnchecked(event);
13375         } else if (mParent != null) {
13376             try {
13377                 mParent.notifySubtreeAccessibilityStateChanged(this, this, changeType);
13378             } catch (AbstractMethodError e) {
13379                 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
13380                         " does not fully implement ViewParent", e);
13381             }
13382         }
13383     }
13384 
13385     /**
13386      * Notifies that the accessibility state of this view changed. The change
13387      * is *not* local to this view and does represent structural changes such
13388      * as children and parent. For example, the view size changed. The
13389      * notification is at at most once every
13390      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
13391      * to avoid unnecessary load to the system. Also once a view has a pending
13392      * notification this method is a NOP until the notification has been sent.
13393      *
13394      * @hide
13395      */
13396     @UnsupportedAppUsage
13397     public void notifySubtreeAccessibilityStateChangedIfNeeded() {
13398         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
13399             return;
13400         }
13401 
13402         if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
13403             mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
13404             if (mParent != null) {
13405                 try {
13406                     mParent.notifySubtreeAccessibilityStateChanged(
13407                             this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
13408                 } catch (AbstractMethodError e) {
13409                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
13410                             " does not fully implement ViewParent", e);
13411                 }
13412             }
13413         }
13414     }
13415 
13416     /**
13417      * Changes the visibility of this View without triggering any other changes. This should only
13418      * be used by animation frameworks, such as {@link android.transition.Transition}, where
13419      * visibility changes should not adjust focus or trigger a new layout. Application developers
13420      * should use {@link #setVisibility} instead to ensure that the hierarchy is correctly updated.
13421      *
13422      * <p>Only call this method when a temporary visibility must be applied during an
13423      * animation and the original visibility value is guaranteed to be reset after the
13424      * animation completes. Use {@link #setVisibility} in all other cases.</p>
13425      *
13426      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
13427      * @see #setVisibility(int)
13428      */
13429     public void setTransitionVisibility(@Visibility int visibility) {
13430         mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
13431     }
13432 
13433     /**
13434      * Reset the flag indicating the accessibility state of the subtree rooted
13435      * at this view changed.
13436      */
13437     void resetSubtreeAccessibilityStateChanged() {
13438         mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
13439     }
13440 
13441     /**
13442      * Report an accessibility action to this view's parents for delegated processing.
13443      *
13444      * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
13445      * call this method to delegate an accessibility action to a supporting parent. If the parent
13446      * returns true from its
13447      * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
13448      * method this method will return true to signify that the action was consumed.</p>
13449      *
13450      * <p>This method is useful for implementing nested scrolling child views. If
13451      * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
13452      * a custom view implementation may invoke this method to allow a parent to consume the
13453      * scroll first. If this method returns true the custom view should skip its own scrolling
13454      * behavior.</p>
13455      *
13456      * @param action Accessibility action to delegate
13457      * @param arguments Optional action arguments
13458      * @return true if the action was consumed by a parent
13459      */
13460     public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
13461         for (ViewParent p = getParent(); p != null; p = p.getParent()) {
13462             if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
13463                 return true;
13464             }
13465         }
13466         return false;
13467     }
13468 
13469     /**
13470      * Performs the specified accessibility action on the view. For
13471      * possible accessibility actions look at {@link AccessibilityNodeInfo}.
13472      * <p>
13473      * If an {@link AccessibilityDelegate} has been specified via calling
13474      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
13475      * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
13476      * is responsible for handling this call.
13477      * </p>
13478      *
13479      * <p>The default implementation will delegate
13480      * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
13481      * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
13482      * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
13483      *
13484      * @param action The action to perform.
13485      * @param arguments Optional action arguments.
13486      * @return Whether the action was performed.
13487      */
13488     public boolean performAccessibilityAction(int action, Bundle arguments) {
13489       if (mAccessibilityDelegate != null) {
13490           return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
13491       } else {
13492           return performAccessibilityActionInternal(action, arguments);
13493       }
13494     }
13495 
13496    /**
13497     * @see #performAccessibilityAction(int, Bundle)
13498     *
13499     * Note: Called from the default {@link AccessibilityDelegate}.
13500     *
13501     * @hide
13502     */
13503     @UnsupportedAppUsage
13504     public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
13505         if (isNestedScrollingEnabled()
13506                 && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
13507                 || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
13508                 || action == R.id.accessibilityActionScrollUp
13509                 || action == R.id.accessibilityActionScrollLeft
13510                 || action == R.id.accessibilityActionScrollDown
13511                 || action == R.id.accessibilityActionScrollRight)) {
13512             if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
13513                 return true;
13514             }
13515         }
13516 
13517         switch (action) {
13518             case AccessibilityNodeInfo.ACTION_CLICK: {
13519                 if (isClickable()) {
13520                     performClickInternal();
13521                     return true;
13522                 }
13523             } break;
13524             case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
13525                 if (isLongClickable()) {
13526                     performLongClick();
13527                     return true;
13528                 }
13529             } break;
13530             case AccessibilityNodeInfo.ACTION_FOCUS: {
13531                 if (!hasFocus()) {
13532                     // Get out of touch mode since accessibility
13533                     // wants to move focus around.
13534                     getViewRootImpl().ensureTouchMode(false);
13535                     return requestFocus();
13536                 }
13537             } break;
13538             case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
13539                 if (hasFocus()) {
13540                     clearFocus();
13541                     return !isFocused();
13542                 }
13543             } break;
13544             case AccessibilityNodeInfo.ACTION_SELECT: {
13545                 if (!isSelected()) {
13546                     setSelected(true);
13547                     return isSelected();
13548                 }
13549             } break;
13550             case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
13551                 if (isSelected()) {
13552                     setSelected(false);
13553                     return !isSelected();
13554                 }
13555             } break;
13556             case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
13557                 if (!isAccessibilityFocused()) {
13558                     return requestAccessibilityFocus();
13559                 }
13560             } break;
13561             case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
13562                 if (isAccessibilityFocused()) {
13563                     clearAccessibilityFocus();
13564                     return true;
13565                 }
13566             } break;
13567             case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
13568                 if (arguments != null) {
13569                     final int granularity = arguments.getInt(
13570                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
13571                     final boolean extendSelection = arguments.getBoolean(
13572                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
13573                     return traverseAtGranularity(granularity, true, extendSelection);
13574                 }
13575             } break;
13576             case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
13577                 if (arguments != null) {
13578                     final int granularity = arguments.getInt(
13579                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
13580                     final boolean extendSelection = arguments.getBoolean(
13581                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
13582                     return traverseAtGranularity(granularity, false, extendSelection);
13583                 }
13584             } break;
13585             case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
13586                 CharSequence text = getIterableTextForAccessibility();
13587                 if (text == null) {
13588                     return false;
13589                 }
13590                 final int start = (arguments != null) ? arguments.getInt(
13591                         AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
13592                 final int end = (arguments != null) ? arguments.getInt(
13593                 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
13594                 // Only cursor position can be specified (selection length == 0)
13595                 if ((getAccessibilitySelectionStart() != start
13596                         || getAccessibilitySelectionEnd() != end)
13597                         && (start == end)) {
13598                     setAccessibilitySelection(start, end);
13599                     notifyViewAccessibilityStateChangedIfNeeded(
13600                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
13601                     return true;
13602                 }
13603             } break;
13604             case R.id.accessibilityActionShowOnScreen: {
13605                 if (mAttachInfo != null) {
13606                     final Rect r = mAttachInfo.mTmpInvalRect;
13607                     getDrawingRect(r);
13608                     return requestRectangleOnScreen(r, true);
13609                 }
13610             } break;
13611             case R.id.accessibilityActionContextClick: {
13612                 if (isContextClickable()) {
13613                     performContextClick();
13614                     return true;
13615                 }
13616             } break;
13617             case R.id.accessibilityActionShowTooltip: {
13618                 if ((mTooltipInfo != null) && (mTooltipInfo.mTooltipPopup != null)) {
13619                     // Tooltip already showing
13620                     return false;
13621                 }
13622                 return showLongClickTooltip(0, 0);
13623             }
13624             case R.id.accessibilityActionHideTooltip: {
13625                 if ((mTooltipInfo == null) || (mTooltipInfo.mTooltipPopup == null)) {
13626                     // No tooltip showing
13627                     return false;
13628                 }
13629                 hideTooltip();
13630                 return true;
13631             }
13632         }
13633         return false;
13634     }
13635 
13636     private boolean traverseAtGranularity(int granularity, boolean forward,
13637             boolean extendSelection) {
13638         CharSequence text = getIterableTextForAccessibility();
13639         if (text == null || text.length() == 0) {
13640             return false;
13641         }
13642         TextSegmentIterator iterator = getIteratorForGranularity(granularity);
13643         if (iterator == null) {
13644             return false;
13645         }
13646         int current = getAccessibilitySelectionEnd();
13647         if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
13648             current = forward ? 0 : text.length();
13649         }
13650         final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
13651         if (range == null) {
13652             return false;
13653         }
13654         final int segmentStart = range[0];
13655         final int segmentEnd = range[1];
13656         int selectionStart;
13657         int selectionEnd;
13658         if (extendSelection && isAccessibilitySelectionExtendable()) {
13659             selectionStart = getAccessibilitySelectionStart();
13660             if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
13661                 selectionStart = forward ? segmentStart : segmentEnd;
13662             }
13663             selectionEnd = forward ? segmentEnd : segmentStart;
13664         } else {
13665             selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
13666         }
13667         setAccessibilitySelection(selectionStart, selectionEnd);
13668         final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
13669                 : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
13670         sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
13671         return true;
13672     }
13673 
13674     /**
13675      * Gets the text reported for accessibility purposes.
13676      *
13677      * @return The accessibility text.
13678      *
13679      * @hide
13680      */
13681     @UnsupportedAppUsage
13682     public CharSequence getIterableTextForAccessibility() {
13683         return getContentDescription();
13684     }
13685 
13686     /**
13687      * Gets whether accessibility selection can be extended.
13688      *
13689      * @return If selection is extensible.
13690      *
13691      * @hide
13692      */
13693     public boolean isAccessibilitySelectionExtendable() {
13694         return false;
13695     }
13696 
13697     /**
13698      * @hide
13699      */
13700     public int getAccessibilitySelectionStart() {
13701         return mAccessibilityCursorPosition;
13702     }
13703 
13704     /**
13705      * @hide
13706      */
13707     public int getAccessibilitySelectionEnd() {
13708         return getAccessibilitySelectionStart();
13709     }
13710 
13711     /**
13712      * @hide
13713      */
13714     public void setAccessibilitySelection(int start, int end) {
13715         if (start ==  end && end == mAccessibilityCursorPosition) {
13716             return;
13717         }
13718         if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
13719             mAccessibilityCursorPosition = start;
13720         } else {
13721             mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
13722         }
13723         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
13724     }
13725 
13726     private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
13727             int fromIndex, int toIndex) {
13728         if (mParent == null) {
13729             return;
13730         }
13731         AccessibilityEvent event = AccessibilityEvent.obtain(
13732                 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
13733         onInitializeAccessibilityEvent(event);
13734         onPopulateAccessibilityEvent(event);
13735         event.setFromIndex(fromIndex);
13736         event.setToIndex(toIndex);
13737         event.setAction(action);
13738         event.setMovementGranularity(granularity);
13739         mParent.requestSendAccessibilityEvent(this, event);
13740     }
13741 
13742     /**
13743      * @hide
13744      */
13745     @UnsupportedAppUsage
13746     public TextSegmentIterator getIteratorForGranularity(int granularity) {
13747         switch (granularity) {
13748             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
13749                 CharSequence text = getIterableTextForAccessibility();
13750                 if (text != null && text.length() > 0) {
13751                     CharacterTextSegmentIterator iterator =
13752                         CharacterTextSegmentIterator.getInstance(
13753                                 mContext.getResources().getConfiguration().locale);
13754                     iterator.initialize(text.toString());
13755                     return iterator;
13756                 }
13757             } break;
13758             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
13759                 CharSequence text = getIterableTextForAccessibility();
13760                 if (text != null && text.length() > 0) {
13761                     WordTextSegmentIterator iterator =
13762                         WordTextSegmentIterator.getInstance(
13763                                 mContext.getResources().getConfiguration().locale);
13764                     iterator.initialize(text.toString());
13765                     return iterator;
13766                 }
13767             } break;
13768             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
13769                 CharSequence text = getIterableTextForAccessibility();
13770                 if (text != null && text.length() > 0) {
13771                     ParagraphTextSegmentIterator iterator =
13772                         ParagraphTextSegmentIterator.getInstance();
13773                     iterator.initialize(text.toString());
13774                     return iterator;
13775                 }
13776             } break;
13777         }
13778         return null;
13779     }
13780 
13781     /**
13782      * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
13783      * and {@link #onFinishTemporaryDetach()}.
13784      *
13785      * <p>This method always returns {@code true} when called directly or indirectly from
13786      * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
13787      * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
13788      * <ul>
13789      *     <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
13790      *     <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
13791      * </ul>
13792      * </p>
13793      *
13794      * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
13795      * and {@link #onFinishTemporaryDetach()}.
13796      */
isTemporarilyDetached()13797     public final boolean isTemporarilyDetached() {
13798         return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
13799     }
13800 
13801     /**
13802      * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
13803      * a container View.
13804      */
13805     @CallSuper
dispatchStartTemporaryDetach()13806     public void dispatchStartTemporaryDetach() {
13807         mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
13808         notifyEnterOrExitForAutoFillIfNeeded(false);
13809         notifyAppearedOrDisappearedForContentCaptureIfNeeded(false);
13810         onStartTemporaryDetach();
13811     }
13812 
13813     /**
13814      * This is called when a container is going to temporarily detach a child, with
13815      * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
13816      * It will either be followed by {@link #onFinishTemporaryDetach()} or
13817      * {@link #onDetachedFromWindow()} when the container is done.
13818      */
onStartTemporaryDetach()13819     public void onStartTemporaryDetach() {
13820         removeUnsetPressCallback();
13821         mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
13822     }
13823 
13824     /**
13825      * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
13826      * a container View.
13827      */
13828     @CallSuper
dispatchFinishTemporaryDetach()13829     public void dispatchFinishTemporaryDetach() {
13830         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
13831         onFinishTemporaryDetach();
13832         if (hasWindowFocus() && hasFocus()) {
13833             notifyFocusChangeToInputMethodManager(true /* hasFocus */);
13834         }
13835         notifyEnterOrExitForAutoFillIfNeeded(true);
13836         notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
13837     }
13838 
13839     /**
13840      * Called after {@link #onStartTemporaryDetach} when the container is done
13841      * changing the view.
13842      */
onFinishTemporaryDetach()13843     public void onFinishTemporaryDetach() {
13844     }
13845 
13846     /**
13847      * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
13848      * for this view's window.  Returns null if the view is not currently attached
13849      * to the window.  Normally you will not need to use this directly, but
13850      * just use the standard high-level event callbacks like
13851      * {@link #onKeyDown(int, KeyEvent)}.
13852      */
getKeyDispatcherState()13853     public KeyEvent.DispatcherState getKeyDispatcherState() {
13854         return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
13855     }
13856 
13857     /**
13858      * Dispatch a key event before it is processed by any input method
13859      * associated with the view hierarchy.  This can be used to intercept
13860      * key events in special situations before the IME consumes them; a
13861      * typical example would be handling the BACK key to update the application's
13862      * UI instead of allowing the IME to see it and close itself.
13863      *
13864      * @param event The key event to be dispatched.
13865      * @return True if the event was handled, false otherwise.
13866      */
dispatchKeyEventPreIme(KeyEvent event)13867     public boolean dispatchKeyEventPreIme(KeyEvent event) {
13868         return onKeyPreIme(event.getKeyCode(), event);
13869     }
13870 
13871     /**
13872      * Dispatch a key event to the next view on the focus path. This path runs
13873      * from the top of the view tree down to the currently focused view. If this
13874      * view has focus, it will dispatch to itself. Otherwise it will dispatch
13875      * the next node down the focus path. This method also fires any key
13876      * listeners.
13877      *
13878      * @param event The key event to be dispatched.
13879      * @return True if the event was handled, false otherwise.
13880      */
dispatchKeyEvent(KeyEvent event)13881     public boolean dispatchKeyEvent(KeyEvent event) {
13882         if (mInputEventConsistencyVerifier != null) {
13883             mInputEventConsistencyVerifier.onKeyEvent(event, 0);
13884         }
13885 
13886         // Give any attached key listener a first crack at the event.
13887         //noinspection SimplifiableIfStatement
13888         ListenerInfo li = mListenerInfo;
13889         if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
13890                 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
13891             return true;
13892         }
13893 
13894         if (event.dispatch(this, mAttachInfo != null
13895                 ? mAttachInfo.mKeyDispatchState : null, this)) {
13896             return true;
13897         }
13898 
13899         if (mInputEventConsistencyVerifier != null) {
13900             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
13901         }
13902         return false;
13903     }
13904 
13905     /**
13906      * Dispatches a key shortcut event.
13907      *
13908      * @param event The key event to be dispatched.
13909      * @return True if the event was handled by the view, false otherwise.
13910      */
dispatchKeyShortcutEvent(KeyEvent event)13911     public boolean dispatchKeyShortcutEvent(KeyEvent event) {
13912         return onKeyShortcut(event.getKeyCode(), event);
13913     }
13914 
13915     /**
13916      * Pass the touch screen motion event down to the target view, or this
13917      * view if it is the target.
13918      *
13919      * @param event The motion event to be dispatched.
13920      * @return True if the event was handled by the view, false otherwise.
13921      */
dispatchTouchEvent(MotionEvent event)13922     public boolean dispatchTouchEvent(MotionEvent event) {
13923         // If the event should be handled by accessibility focus first.
13924         if (event.isTargetAccessibilityFocus()) {
13925             // We don't have focus or no virtual descendant has it, do not handle the event.
13926             if (!isAccessibilityFocusedViewOrHost()) {
13927                 return false;
13928             }
13929             // We have focus and got the event, then use normal event dispatch.
13930             event.setTargetAccessibilityFocus(false);
13931         }
13932 
13933         boolean result = false;
13934 
13935         if (mInputEventConsistencyVerifier != null) {
13936             mInputEventConsistencyVerifier.onTouchEvent(event, 0);
13937         }
13938 
13939         final int actionMasked = event.getActionMasked();
13940         if (actionMasked == MotionEvent.ACTION_DOWN) {
13941             // Defensive cleanup for new gesture
13942             stopNestedScroll();
13943         }
13944 
13945         if (onFilterTouchEventForSecurity(event)) {
13946             if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
13947                 result = true;
13948             }
13949             //noinspection SimplifiableIfStatement
13950             ListenerInfo li = mListenerInfo;
13951             if (li != null && li.mOnTouchListener != null
13952                     && (mViewFlags & ENABLED_MASK) == ENABLED
13953                     && li.mOnTouchListener.onTouch(this, event)) {
13954                 result = true;
13955             }
13956 
13957             if (!result && onTouchEvent(event)) {
13958                 result = true;
13959             }
13960         }
13961 
13962         if (!result && mInputEventConsistencyVerifier != null) {
13963             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
13964         }
13965 
13966         // Clean up after nested scrolls if this is the end of a gesture;
13967         // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
13968         // of the gesture.
13969         if (actionMasked == MotionEvent.ACTION_UP ||
13970                 actionMasked == MotionEvent.ACTION_CANCEL ||
13971                 (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
13972             stopNestedScroll();
13973         }
13974 
13975         return result;
13976     }
13977 
isAccessibilityFocusedViewOrHost()13978     boolean isAccessibilityFocusedViewOrHost() {
13979         return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
13980                 .getAccessibilityFocusedHost() == this);
13981     }
13982 
13983     /**
13984      * Returns whether this view can receive pointer events.
13985      *
13986      * @return {@code true} if this view can receive pointer events.
13987      * @hide
13988      */
canReceivePointerEvents()13989     protected boolean canReceivePointerEvents() {
13990         return (mViewFlags & VISIBILITY_MASK) == VISIBLE || getAnimation() != null;
13991     }
13992 
13993     /**
13994      * Filter the touch event to apply security policies.
13995      *
13996      * @param event The motion event to be filtered.
13997      * @return True if the event should be dispatched, false if the event should be dropped.
13998      *
13999      * @see #getFilterTouchesWhenObscured
14000      */
onFilterTouchEventForSecurity(MotionEvent event)14001     public boolean onFilterTouchEventForSecurity(MotionEvent event) {
14002         //noinspection RedundantIfStatement
14003         if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
14004                 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
14005             // Window is obscured, drop this touch.
14006             return false;
14007         }
14008         return true;
14009     }
14010 
14011     /**
14012      * Pass a trackball motion event down to the focused view.
14013      *
14014      * @param event The motion event to be dispatched.
14015      * @return True if the event was handled by the view, false otherwise.
14016      */
dispatchTrackballEvent(MotionEvent event)14017     public boolean dispatchTrackballEvent(MotionEvent event) {
14018         if (mInputEventConsistencyVerifier != null) {
14019             mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
14020         }
14021 
14022         return onTrackballEvent(event);
14023     }
14024 
14025     /**
14026      * Pass a captured pointer event down to the focused view.
14027      *
14028      * @param event The motion event to be dispatched.
14029      * @return True if the event was handled by the view, false otherwise.
14030      */
dispatchCapturedPointerEvent(MotionEvent event)14031     public boolean dispatchCapturedPointerEvent(MotionEvent event) {
14032         if (!hasPointerCapture()) {
14033             return false;
14034         }
14035         //noinspection SimplifiableIfStatement
14036         ListenerInfo li = mListenerInfo;
14037         if (li != null && li.mOnCapturedPointerListener != null
14038                 && li.mOnCapturedPointerListener.onCapturedPointer(this, event)) {
14039             return true;
14040         }
14041         return onCapturedPointerEvent(event);
14042     }
14043 
14044     /**
14045      * Dispatch a generic motion event.
14046      * <p>
14047      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
14048      * are delivered to the view under the pointer.  All other generic motion events are
14049      * delivered to the focused view.  Hover events are handled specially and are delivered
14050      * to {@link #onHoverEvent(MotionEvent)}.
14051      * </p>
14052      *
14053      * @param event The motion event to be dispatched.
14054      * @return True if the event was handled by the view, false otherwise.
14055      */
dispatchGenericMotionEvent(MotionEvent event)14056     public boolean dispatchGenericMotionEvent(MotionEvent event) {
14057         if (mInputEventConsistencyVerifier != null) {
14058             mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
14059         }
14060 
14061         final int source = event.getSource();
14062         if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
14063             final int action = event.getAction();
14064             if (action == MotionEvent.ACTION_HOVER_ENTER
14065                     || action == MotionEvent.ACTION_HOVER_MOVE
14066                     || action == MotionEvent.ACTION_HOVER_EXIT) {
14067                 if (dispatchHoverEvent(event)) {
14068                     return true;
14069                 }
14070             } else if (dispatchGenericPointerEvent(event)) {
14071                 return true;
14072             }
14073         } else if (dispatchGenericFocusedEvent(event)) {
14074             return true;
14075         }
14076 
14077         if (dispatchGenericMotionEventInternal(event)) {
14078             return true;
14079         }
14080 
14081         if (mInputEventConsistencyVerifier != null) {
14082             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
14083         }
14084         return false;
14085     }
14086 
dispatchGenericMotionEventInternal(MotionEvent event)14087     private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
14088         //noinspection SimplifiableIfStatement
14089         ListenerInfo li = mListenerInfo;
14090         if (li != null && li.mOnGenericMotionListener != null
14091                 && (mViewFlags & ENABLED_MASK) == ENABLED
14092                 && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
14093             return true;
14094         }
14095 
14096         if (onGenericMotionEvent(event)) {
14097             return true;
14098         }
14099 
14100         final int actionButton = event.getActionButton();
14101         switch (event.getActionMasked()) {
14102             case MotionEvent.ACTION_BUTTON_PRESS:
14103                 if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
14104                         && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
14105                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
14106                     if (performContextClick(event.getX(), event.getY())) {
14107                         mInContextButtonPress = true;
14108                         setPressed(true, event.getX(), event.getY());
14109                         removeTapCallback();
14110                         removeLongPressCallback();
14111                         return true;
14112                     }
14113                 }
14114                 break;
14115 
14116             case MotionEvent.ACTION_BUTTON_RELEASE:
14117                 if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
14118                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
14119                     mInContextButtonPress = false;
14120                     mIgnoreNextUpEvent = true;
14121                 }
14122                 break;
14123         }
14124 
14125         if (mInputEventConsistencyVerifier != null) {
14126             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
14127         }
14128         return false;
14129     }
14130 
14131     /**
14132      * Dispatch a hover event.
14133      * <p>
14134      * Do not call this method directly.
14135      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
14136      * </p>
14137      *
14138      * @param event The motion event to be dispatched.
14139      * @return True if the event was handled by the view, false otherwise.
14140      */
dispatchHoverEvent(MotionEvent event)14141     protected boolean dispatchHoverEvent(MotionEvent event) {
14142         ListenerInfo li = mListenerInfo;
14143         //noinspection SimplifiableIfStatement
14144         if (li != null && li.mOnHoverListener != null
14145                 && (mViewFlags & ENABLED_MASK) == ENABLED
14146                 && li.mOnHoverListener.onHover(this, event)) {
14147             return true;
14148         }
14149 
14150         return onHoverEvent(event);
14151     }
14152 
14153     /**
14154      * Returns true if the view has a child to which it has recently sent
14155      * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
14156      * it does not have a hovered child, then it must be the innermost hovered view.
14157      * @hide
14158      */
hasHoveredChild()14159     protected boolean hasHoveredChild() {
14160         return false;
14161     }
14162 
14163     /**
14164      * Returns true if the given point, in local coordinates, is inside the hovered child.
14165      *
14166      * @hide
14167      */
pointInHoveredChild(MotionEvent event)14168     protected boolean pointInHoveredChild(MotionEvent event) {
14169         return false;
14170     }
14171 
14172     /**
14173      * Dispatch a generic motion event to the view under the first pointer.
14174      * <p>
14175      * Do not call this method directly.
14176      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
14177      * </p>
14178      *
14179      * @param event The motion event to be dispatched.
14180      * @return True if the event was handled by the view, false otherwise.
14181      */
dispatchGenericPointerEvent(MotionEvent event)14182     protected boolean dispatchGenericPointerEvent(MotionEvent event) {
14183         return false;
14184     }
14185 
14186     /**
14187      * Dispatch a generic motion event to the currently focused view.
14188      * <p>
14189      * Do not call this method directly.
14190      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
14191      * </p>
14192      *
14193      * @param event The motion event to be dispatched.
14194      * @return True if the event was handled by the view, false otherwise.
14195      */
dispatchGenericFocusedEvent(MotionEvent event)14196     protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
14197         return false;
14198     }
14199 
14200     /**
14201      * Dispatch a pointer event.
14202      * <p>
14203      * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
14204      * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
14205      * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
14206      * and should not be expected to handle other pointing device features.
14207      * </p>
14208      *
14209      * @param event The motion event to be dispatched.
14210      * @return True if the event was handled by the view, false otherwise.
14211      * @hide
14212      */
14213     @UnsupportedAppUsage
dispatchPointerEvent(MotionEvent event)14214     public final boolean dispatchPointerEvent(MotionEvent event) {
14215         if (event.isTouchEvent()) {
14216             return dispatchTouchEvent(event);
14217         } else {
14218             return dispatchGenericMotionEvent(event);
14219         }
14220     }
14221 
14222     /**
14223      * Called when the window containing this view gains or loses window focus.
14224      * ViewGroups should override to route to their children.
14225      *
14226      * @param hasFocus True if the window containing this view now has focus,
14227      *        false otherwise.
14228      */
dispatchWindowFocusChanged(boolean hasFocus)14229     public void dispatchWindowFocusChanged(boolean hasFocus) {
14230         onWindowFocusChanged(hasFocus);
14231     }
14232 
14233     /**
14234      * Called when the window containing this view gains or loses focus.  Note
14235      * that this is separate from view focus: to receive key events, both
14236      * your view and its window must have focus.  If a window is displayed
14237      * on top of yours that takes input focus, then your own window will lose
14238      * focus but the view focus will remain unchanged.
14239      *
14240      * @param hasWindowFocus True if the window containing this view now has
14241      *        focus, false otherwise.
14242      */
onWindowFocusChanged(boolean hasWindowFocus)14243     public void onWindowFocusChanged(boolean hasWindowFocus) {
14244         if (!hasWindowFocus) {
14245             if (isPressed()) {
14246                 setPressed(false);
14247             }
14248             mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
14249             if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
14250                 notifyFocusChangeToInputMethodManager(false /* hasFocus */);
14251             }
14252             removeLongPressCallback();
14253             removeTapCallback();
14254             onFocusLost();
14255         } else if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
14256             notifyFocusChangeToInputMethodManager(true /* hasFocus */);
14257         }
14258 
14259         refreshDrawableState();
14260     }
14261 
14262     /**
14263      * Returns true if this view is in a window that currently has window focus.
14264      * Note that this is not the same as the view itself having focus.
14265      *
14266      * @return True if this view is in a window that currently has window focus.
14267      */
hasWindowFocus()14268     public boolean hasWindowFocus() {
14269         return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
14270     }
14271 
14272     /**
14273      * Dispatch a view visibility change down the view hierarchy.
14274      * ViewGroups should override to route to their children.
14275      * @param changedView The view whose visibility changed. Could be 'this' or
14276      * an ancestor view.
14277      * @param visibility The new visibility of changedView: {@link #VISIBLE},
14278      * {@link #INVISIBLE} or {@link #GONE}.
14279      */
dispatchVisibilityChanged(@onNull View changedView, @Visibility int visibility)14280     protected void dispatchVisibilityChanged(@NonNull View changedView,
14281             @Visibility int visibility) {
14282         onVisibilityChanged(changedView, visibility);
14283     }
14284 
14285     /**
14286      * Called when the visibility of the view or an ancestor of the view has
14287      * changed.
14288      *
14289      * @param changedView The view whose visibility changed. May be
14290      *                    {@code this} or an ancestor view.
14291      * @param visibility The new visibility, one of {@link #VISIBLE},
14292      *                   {@link #INVISIBLE} or {@link #GONE}.
14293      */
onVisibilityChanged(@onNull View changedView, @Visibility int visibility)14294     protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
14295     }
14296 
14297     /**
14298      * Dispatch a hint about whether this view is displayed. For instance, when
14299      * a View moves out of the screen, it might receives a display hint indicating
14300      * the view is not displayed. Applications should not <em>rely</em> on this hint
14301      * as there is no guarantee that they will receive one.
14302      *
14303      * @param hint A hint about whether or not this view is displayed:
14304      * {@link #VISIBLE} or {@link #INVISIBLE}.
14305      */
dispatchDisplayHint(@isibility int hint)14306     public void dispatchDisplayHint(@Visibility int hint) {
14307         onDisplayHint(hint);
14308     }
14309 
14310     /**
14311      * Gives this view a hint about whether is displayed or not. For instance, when
14312      * a View moves out of the screen, it might receives a display hint indicating
14313      * the view is not displayed. Applications should not <em>rely</em> on this hint
14314      * as there is no guarantee that they will receive one.
14315      *
14316      * @param hint A hint about whether or not this view is displayed:
14317      * {@link #VISIBLE} or {@link #INVISIBLE}.
14318      */
onDisplayHint(@isibility int hint)14319     protected void onDisplayHint(@Visibility int hint) {
14320     }
14321 
14322     /**
14323      * Dispatch a window visibility change down the view hierarchy.
14324      * ViewGroups should override to route to their children.
14325      *
14326      * @param visibility The new visibility of the window.
14327      *
14328      * @see #onWindowVisibilityChanged(int)
14329      */
dispatchWindowVisibilityChanged(@isibility int visibility)14330     public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
14331         onWindowVisibilityChanged(visibility);
14332     }
14333 
14334     /**
14335      * Called when the window containing has change its visibility
14336      * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
14337      * that this tells you whether or not your window is being made visible
14338      * to the window manager; this does <em>not</em> tell you whether or not
14339      * your window is obscured by other windows on the screen, even if it
14340      * is itself visible.
14341      *
14342      * @param visibility The new visibility of the window.
14343      */
onWindowVisibilityChanged(@isibility int visibility)14344     protected void onWindowVisibilityChanged(@Visibility int visibility) {
14345         if (visibility == VISIBLE) {
14346             initialAwakenScrollBars();
14347         }
14348     }
14349 
14350     /**
14351      * @return true if this view and all ancestors are visible as of the last
14352      * {@link #onVisibilityAggregated(boolean)} call.
14353      */
isAggregatedVisible()14354     boolean isAggregatedVisible() {
14355         return (mPrivateFlags3 & PFLAG3_AGGREGATED_VISIBLE) != 0;
14356     }
14357 
14358     /**
14359      * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
14360      * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
14361      * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
14362      *
14363      * @param isVisible true if this view's visibility to the user is uninterrupted by its
14364      *                  ancestors or by window visibility
14365      * @return true if this view is visible to the user, not counting clipping or overlapping
14366      */
dispatchVisibilityAggregated(boolean isVisible)14367     boolean dispatchVisibilityAggregated(boolean isVisible) {
14368         final boolean thisVisible = getVisibility() == VISIBLE;
14369         // If we're not visible but something is telling us we are, ignore it.
14370         if (thisVisible || !isVisible) {
14371             onVisibilityAggregated(isVisible);
14372         }
14373         return thisVisible && isVisible;
14374     }
14375 
14376     /**
14377      * Called when the user-visibility of this View is potentially affected by a change
14378      * to this view itself, an ancestor view or the window this view is attached to.
14379      *
14380      * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
14381      *                  and this view's window is also visible
14382      */
14383     @CallSuper
onVisibilityAggregated(boolean isVisible)14384     public void onVisibilityAggregated(boolean isVisible) {
14385         // Update our internal visibility tracking so we can detect changes
14386         boolean oldVisible = isAggregatedVisible();
14387         mPrivateFlags3 = isVisible ? (mPrivateFlags3 | PFLAG3_AGGREGATED_VISIBLE)
14388                 : (mPrivateFlags3 & ~PFLAG3_AGGREGATED_VISIBLE);
14389         if (isVisible && mAttachInfo != null) {
14390             initialAwakenScrollBars();
14391         }
14392 
14393         final Drawable dr = mBackground;
14394         if (dr != null && isVisible != dr.isVisible()) {
14395             dr.setVisible(isVisible, false);
14396         }
14397         final Drawable hl = mDefaultFocusHighlight;
14398         if (hl != null && isVisible != hl.isVisible()) {
14399             hl.setVisible(isVisible, false);
14400         }
14401         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
14402         if (fg != null && isVisible != fg.isVisible()) {
14403             fg.setVisible(isVisible, false);
14404         }
14405 
14406         if (isAutofillable()) {
14407             AutofillManager afm = getAutofillManager();
14408 
14409             if (afm != null && getAutofillViewId() > LAST_APP_AUTOFILL_ID) {
14410                 if (mVisibilityChangeForAutofillHandler != null) {
14411                     mVisibilityChangeForAutofillHandler.removeMessages(0);
14412                 }
14413 
14414                 // If the view is in the background but still part of the hierarchy this is called
14415                 // with isVisible=false. Hence visibility==false requires further checks
14416                 if (isVisible) {
14417                     afm.notifyViewVisibilityChanged(this, true);
14418                 } else {
14419                     if (mVisibilityChangeForAutofillHandler == null) {
14420                         mVisibilityChangeForAutofillHandler =
14421                                 new VisibilityChangeForAutofillHandler(afm, this);
14422                     }
14423                     // Let current operation (e.g. removal of the view from the hierarchy)
14424                     // finish before checking state
14425                     mVisibilityChangeForAutofillHandler.obtainMessage(0, this).sendToTarget();
14426                 }
14427             }
14428         }
14429         if (isAccessibilityPane()) {
14430             if (isVisible != oldVisible) {
14431                 notifyViewAccessibilityStateChangedIfNeeded(isVisible
14432                         ? AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_APPEARED
14433                         : AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED);
14434             }
14435         }
14436 
14437         notifyAppearedOrDisappearedForContentCaptureIfNeeded(isVisible);
14438         if (!getSystemGestureExclusionRects().isEmpty() && isVisible != oldVisible) {
14439             postUpdateSystemGestureExclusionRects();
14440         }
14441     }
14442 
14443     /**
14444      * Returns the current visibility of the window this view is attached to
14445      * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
14446      *
14447      * @return Returns the current visibility of the view's window.
14448      */
14449     @Visibility
getWindowVisibility()14450     public int getWindowVisibility() {
14451         return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
14452     }
14453 
14454     /**
14455      * Retrieve the overall visible display size in which the window this view is
14456      * attached to has been positioned in.  This takes into account screen
14457      * decorations above the window, for both cases where the window itself
14458      * is being position inside of them or the window is being placed under
14459      * then and covered insets are used for the window to position its content
14460      * inside.  In effect, this tells you the available area where content can
14461      * be placed and remain visible to users.
14462      *
14463      * <p>This function requires an IPC back to the window manager to retrieve
14464      * the requested information, so should not be used in performance critical
14465      * code like drawing.
14466      *
14467      * @param outRect Filled in with the visible display frame.  If the view
14468      * is not attached to a window, this is simply the raw display size.
14469      */
getWindowVisibleDisplayFrame(Rect outRect)14470     public void getWindowVisibleDisplayFrame(Rect outRect) {
14471         if (mAttachInfo != null) {
14472             try {
14473                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
14474             } catch (RemoteException e) {
14475                 return;
14476             }
14477             // XXX This is really broken, and probably all needs to be done
14478             // in the window manager, and we need to know more about whether
14479             // we want the area behind or in front of the IME.
14480             final Rect insets = mAttachInfo.mVisibleInsets;
14481             outRect.left += insets.left;
14482             outRect.top += insets.top;
14483             outRect.right -= insets.right;
14484             outRect.bottom -= insets.bottom;
14485             return;
14486         }
14487         // The view is not attached to a display so we don't have a context.
14488         // Make a best guess about the display size.
14489         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
14490         d.getRectSize(outRect);
14491     }
14492 
14493     /**
14494      * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
14495      * is currently in without any insets.
14496      *
14497      * @hide
14498      */
14499     @UnsupportedAppUsage
getWindowDisplayFrame(Rect outRect)14500     public void getWindowDisplayFrame(Rect outRect) {
14501         if (mAttachInfo != null) {
14502             try {
14503                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
14504             } catch (RemoteException e) {
14505                 return;
14506             }
14507             return;
14508         }
14509         // The view is not attached to a display so we don't have a context.
14510         // Make a best guess about the display size.
14511         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
14512         d.getRectSize(outRect);
14513     }
14514 
14515     /**
14516      * Dispatch a notification about a resource configuration change down
14517      * the view hierarchy.
14518      * ViewGroups should override to route to their children.
14519      *
14520      * @param newConfig The new resource configuration.
14521      *
14522      * @see #onConfigurationChanged(android.content.res.Configuration)
14523      */
dispatchConfigurationChanged(Configuration newConfig)14524     public void dispatchConfigurationChanged(Configuration newConfig) {
14525         onConfigurationChanged(newConfig);
14526     }
14527 
14528     /**
14529      * Called when the current configuration of the resources being used
14530      * by the application have changed.  You can use this to decide when
14531      * to reload resources that can changed based on orientation and other
14532      * configuration characteristics.  You only need to use this if you are
14533      * not relying on the normal {@link android.app.Activity} mechanism of
14534      * recreating the activity instance upon a configuration change.
14535      *
14536      * @param newConfig The new resource configuration.
14537      */
onConfigurationChanged(Configuration newConfig)14538     protected void onConfigurationChanged(Configuration newConfig) {
14539     }
14540 
14541     /**
14542      * Private function to aggregate all per-view attributes in to the view
14543      * root.
14544      */
dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility)14545     void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
14546         performCollectViewAttributes(attachInfo, visibility);
14547     }
14548 
performCollectViewAttributes(AttachInfo attachInfo, int visibility)14549     void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
14550         if ((visibility & VISIBILITY_MASK) == VISIBLE) {
14551             if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
14552                 attachInfo.mKeepScreenOn = true;
14553             }
14554             attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
14555             ListenerInfo li = mListenerInfo;
14556             if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
14557                 attachInfo.mHasSystemUiListeners = true;
14558             }
14559         }
14560     }
14561 
needGlobalAttributesUpdate(boolean force)14562     void needGlobalAttributesUpdate(boolean force) {
14563         final AttachInfo ai = mAttachInfo;
14564         if (ai != null && !ai.mRecomputeGlobalAttributes) {
14565             if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
14566                     || ai.mHasSystemUiListeners) {
14567                 ai.mRecomputeGlobalAttributes = true;
14568             }
14569         }
14570     }
14571 
14572     /**
14573      * Returns whether the device is currently in touch mode.  Touch mode is entered
14574      * once the user begins interacting with the device by touch, and affects various
14575      * things like whether focus is always visible to the user.
14576      *
14577      * @return Whether the device is in touch mode.
14578      */
14579     @ViewDebug.ExportedProperty
isInTouchMode()14580     public boolean isInTouchMode() {
14581         if (mAttachInfo != null) {
14582             return mAttachInfo.mInTouchMode;
14583         } else {
14584             return ViewRootImpl.isInTouchMode();
14585         }
14586     }
14587 
14588     /**
14589      * Returns the context the view is running in, through which it can
14590      * access the current theme, resources, etc.
14591      *
14592      * @return The view's Context.
14593      */
14594     @ViewDebug.CapturedViewProperty
getContext()14595     public final Context getContext() {
14596         return mContext;
14597     }
14598 
14599     /**
14600      * Handle a key event before it is processed by any input method
14601      * associated with the view hierarchy.  This can be used to intercept
14602      * key events in special situations before the IME consumes them; a
14603      * typical example would be handling the BACK key to update the application's
14604      * UI instead of allowing the IME to see it and close itself.
14605      *
14606      * @param keyCode The value in event.getKeyCode().
14607      * @param event Description of the key event.
14608      * @return If you handled the event, return true. If you want to allow the
14609      *         event to be handled by the next receiver, return false.
14610      */
onKeyPreIme(int keyCode, KeyEvent event)14611     public boolean onKeyPreIme(int keyCode, KeyEvent event) {
14612         return false;
14613     }
14614 
14615     /**
14616      * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
14617      * KeyEvent.Callback.onKeyDown()}: perform press of the view
14618      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
14619      * is released, if the view is enabled and clickable.
14620      * <p>
14621      * Key presses in software keyboards will generally NOT trigger this
14622      * listener, although some may elect to do so in some situations. Do not
14623      * rely on this to catch software key presses.
14624      *
14625      * @param keyCode a key code that represents the button pressed, from
14626      *                {@link android.view.KeyEvent}
14627      * @param event the KeyEvent object that defines the button action
14628      */
onKeyDown(int keyCode, KeyEvent event)14629     public boolean onKeyDown(int keyCode, KeyEvent event) {
14630         if (KeyEvent.isConfirmKey(keyCode)) {
14631             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
14632                 return true;
14633             }
14634 
14635             if (event.getRepeatCount() == 0) {
14636                 // Long clickable items don't necessarily have to be clickable.
14637                 final boolean clickable = (mViewFlags & CLICKABLE) == CLICKABLE
14638                         || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
14639                 if (clickable || (mViewFlags & TOOLTIP) == TOOLTIP) {
14640                     // For the purposes of menu anchoring and drawable hotspots,
14641                     // key events are considered to be at the center of the view.
14642                     final float x = getWidth() / 2f;
14643                     final float y = getHeight() / 2f;
14644                     if (clickable) {
14645                         setPressed(true, x, y);
14646                     }
14647                     checkForLongClick(
14648                             ViewConfiguration.getLongPressTimeout(),
14649                             x,
14650                             y,
14651                             // This is not a touch gesture -- do not classify it as one.
14652                             TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION);
14653                     return true;
14654                 }
14655             }
14656         }
14657 
14658         return false;
14659     }
14660 
14661     /**
14662      * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
14663      * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
14664      * the event).
14665      * <p>Key presses in software keyboards will generally NOT trigger this listener,
14666      * although some may elect to do so in some situations. Do not rely on this to
14667      * catch software key presses.
14668      */
onKeyLongPress(int keyCode, KeyEvent event)14669     public boolean onKeyLongPress(int keyCode, KeyEvent event) {
14670         return false;
14671     }
14672 
14673     /**
14674      * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
14675      * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
14676      * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
14677      * or {@link KeyEvent#KEYCODE_SPACE} is released.
14678      * <p>Key presses in software keyboards will generally NOT trigger this listener,
14679      * although some may elect to do so in some situations. Do not rely on this to
14680      * catch software key presses.
14681      *
14682      * @param keyCode A key code that represents the button pressed, from
14683      *                {@link android.view.KeyEvent}.
14684      * @param event   The KeyEvent object that defines the button action.
14685      */
onKeyUp(int keyCode, KeyEvent event)14686     public boolean onKeyUp(int keyCode, KeyEvent event) {
14687         if (KeyEvent.isConfirmKey(keyCode)) {
14688             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
14689                 return true;
14690             }
14691             if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
14692                 setPressed(false);
14693 
14694                 if (!mHasPerformedLongPress) {
14695                     // This is a tap, so remove the longpress check
14696                     removeLongPressCallback();
14697                     if (!event.isCanceled()) {
14698                         return performClickInternal();
14699                     }
14700                 }
14701             }
14702         }
14703         return false;
14704     }
14705 
14706     /**
14707      * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
14708      * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
14709      * the event).
14710      * <p>Key presses in software keyboards will generally NOT trigger this listener,
14711      * although some may elect to do so in some situations. Do not rely on this to
14712      * catch software key presses.
14713      *
14714      * @param keyCode     A key code that represents the button pressed, from
14715      *                    {@link android.view.KeyEvent}.
14716      * @param repeatCount The number of times the action was made.
14717      * @param event       The KeyEvent object that defines the button action.
14718      */
onKeyMultiple(int keyCode, int repeatCount, KeyEvent event)14719     public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
14720         return false;
14721     }
14722 
14723     /**
14724      * Called on the focused view when a key shortcut event is not handled.
14725      * Override this method to implement local key shortcuts for the View.
14726      * Key shortcuts can also be implemented by setting the
14727      * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
14728      *
14729      * @param keyCode The value in event.getKeyCode().
14730      * @param event Description of the key event.
14731      * @return If you handled the event, return true. If you want to allow the
14732      *         event to be handled by the next receiver, return false.
14733      */
onKeyShortcut(int keyCode, KeyEvent event)14734     public boolean onKeyShortcut(int keyCode, KeyEvent event) {
14735         return false;
14736     }
14737 
14738     /**
14739      * Check whether the called view is a text editor, in which case it
14740      * would make sense to automatically display a soft input window for
14741      * it.  Subclasses should override this if they implement
14742      * {@link #onCreateInputConnection(EditorInfo)} to return true if
14743      * a call on that method would return a non-null InputConnection, and
14744      * they are really a first-class editor that the user would normally
14745      * start typing on when the go into a window containing your view.
14746      *
14747      * <p>The default implementation always returns false.  This does
14748      * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
14749      * will not be called or the user can not otherwise perform edits on your
14750      * view; it is just a hint to the system that this is not the primary
14751      * purpose of this view.
14752      *
14753      * @return Returns true if this view is a text editor, else false.
14754      */
onCheckIsTextEditor()14755     public boolean onCheckIsTextEditor() {
14756         return false;
14757     }
14758 
14759     /**
14760      * Create a new InputConnection for an InputMethod to interact
14761      * with the view.  The default implementation returns null, since it doesn't
14762      * support input methods.  You can override this to implement such support.
14763      * This is only needed for views that take focus and text input.
14764      *
14765      * <p>When implementing this, you probably also want to implement
14766      * {@link #onCheckIsTextEditor()} to indicate you will return a
14767      * non-null InputConnection.</p>
14768      *
14769      * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
14770      * object correctly and in its entirety, so that the connected IME can rely
14771      * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
14772      * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
14773      * must be filled in with the correct cursor position for IMEs to work correctly
14774      * with your application.</p>
14775      *
14776      * @param outAttrs Fill in with attribute information about the connection.
14777      */
onCreateInputConnection(EditorInfo outAttrs)14778     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
14779         return null;
14780     }
14781 
14782     /**
14783      * Called by the {@link android.view.inputmethod.InputMethodManager}
14784      * when a view who is not the current
14785      * input connection target is trying to make a call on the manager.  The
14786      * default implementation returns false; you can override this to return
14787      * true for certain views if you are performing InputConnection proxying
14788      * to them.
14789      * @param view The View that is making the InputMethodManager call.
14790      * @return Return true to allow the call, false to reject.
14791      */
checkInputConnectionProxy(View view)14792     public boolean checkInputConnectionProxy(View view) {
14793         return false;
14794     }
14795 
14796     /**
14797      * Show the context menu for this view. It is not safe to hold on to the
14798      * menu after returning from this method.
14799      *
14800      * You should normally not overload this method. Overload
14801      * {@link #onCreateContextMenu(ContextMenu)} or define an
14802      * {@link OnCreateContextMenuListener} to add items to the context menu.
14803      *
14804      * @param menu The context menu to populate
14805      */
createContextMenu(ContextMenu menu)14806     public void createContextMenu(ContextMenu menu) {
14807         ContextMenuInfo menuInfo = getContextMenuInfo();
14808 
14809         // Sets the current menu info so all items added to menu will have
14810         // my extra info set.
14811         ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
14812 
14813         onCreateContextMenu(menu);
14814         ListenerInfo li = mListenerInfo;
14815         if (li != null && li.mOnCreateContextMenuListener != null) {
14816             li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
14817         }
14818 
14819         // Clear the extra information so subsequent items that aren't mine don't
14820         // have my extra info.
14821         ((MenuBuilder)menu).setCurrentMenuInfo(null);
14822 
14823         if (mParent != null) {
14824             mParent.createContextMenu(menu);
14825         }
14826     }
14827 
14828     /**
14829      * Views should implement this if they have extra information to associate
14830      * with the context menu. The return result is supplied as a parameter to
14831      * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
14832      * callback.
14833      *
14834      * @return Extra information about the item for which the context menu
14835      *         should be shown. This information will vary across different
14836      *         subclasses of View.
14837      */
getContextMenuInfo()14838     protected ContextMenuInfo getContextMenuInfo() {
14839         return null;
14840     }
14841 
14842     /**
14843      * Views should implement this if the view itself is going to add items to
14844      * the context menu.
14845      *
14846      * @param menu the context menu to populate
14847      */
onCreateContextMenu(ContextMenu menu)14848     protected void onCreateContextMenu(ContextMenu menu) {
14849     }
14850 
14851     /**
14852      * Implement this method to handle trackball motion events.  The
14853      * <em>relative</em> movement of the trackball since the last event
14854      * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
14855      * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
14856      * that a movement of 1 corresponds to the user pressing one DPAD key (so
14857      * they will often be fractional values, representing the more fine-grained
14858      * movement information available from a trackball).
14859      *
14860      * @param event The motion event.
14861      * @return True if the event was handled, false otherwise.
14862      */
onTrackballEvent(MotionEvent event)14863     public boolean onTrackballEvent(MotionEvent event) {
14864         return false;
14865     }
14866 
14867     /**
14868      * Implement this method to handle generic motion events.
14869      * <p>
14870      * Generic motion events describe joystick movements, mouse hovers, track pad
14871      * touches, scroll wheel movements and other input events.  The
14872      * {@link MotionEvent#getSource() source} of the motion event specifies
14873      * the class of input that was received.  Implementations of this method
14874      * must examine the bits in the source before processing the event.
14875      * The following code example shows how this is done.
14876      * </p><p>
14877      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
14878      * are delivered to the view under the pointer.  All other generic motion events are
14879      * delivered to the focused view.
14880      * </p>
14881      * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
14882      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
14883      *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
14884      *             // process the joystick movement...
14885      *             return true;
14886      *         }
14887      *     }
14888      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
14889      *         switch (event.getAction()) {
14890      *             case MotionEvent.ACTION_HOVER_MOVE:
14891      *                 // process the mouse hover movement...
14892      *                 return true;
14893      *             case MotionEvent.ACTION_SCROLL:
14894      *                 // process the scroll wheel movement...
14895      *                 return true;
14896      *         }
14897      *     }
14898      *     return super.onGenericMotionEvent(event);
14899      * }</pre>
14900      *
14901      * @param event The generic motion event being processed.
14902      * @return True if the event was handled, false otherwise.
14903      */
onGenericMotionEvent(MotionEvent event)14904     public boolean onGenericMotionEvent(MotionEvent event) {
14905         return false;
14906     }
14907 
14908     /**
14909      * Dispatching hover events to {@link TouchDelegate} to improve accessibility.
14910      * <p>
14911      * This method is dispatching hover events to the delegate target to support explore by touch.
14912      * Similar to {@link ViewGroup#dispatchTouchEvent}, this method send proper hover events to
14913      * the delegate target according to the pointer and the touch area of the delegate while touch
14914      * exploration enabled.
14915      * </p>
14916      *
14917      * @param event The motion event dispatch to the delegate target.
14918      * @return True if the event was handled, false otherwise.
14919      *
14920      * @see #onHoverEvent
14921      */
dispatchTouchExplorationHoverEvent(MotionEvent event)14922     private boolean dispatchTouchExplorationHoverEvent(MotionEvent event) {
14923         final AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
14924         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
14925             return false;
14926         }
14927 
14928         final boolean oldHoveringTouchDelegate = mHoveringTouchDelegate;
14929         final int action = event.getActionMasked();
14930         boolean pointInDelegateRegion = false;
14931         boolean handled = false;
14932 
14933         final AccessibilityNodeInfo.TouchDelegateInfo info = mTouchDelegate.getTouchDelegateInfo();
14934         for (int i = 0; i < info.getRegionCount(); i++) {
14935             Region r = info.getRegionAt(i);
14936             if (r.contains((int) event.getX(), (int) event.getY())) {
14937                 pointInDelegateRegion = true;
14938             }
14939         }
14940 
14941         // Explore by touch should dispatch events to children under the pointer first if any
14942         // before dispatching to TouchDelegate. For non-hoverable views that do not consume
14943         // hover events but receive accessibility focus, it should also not delegate to these
14944         // views when hovered.
14945         if (!oldHoveringTouchDelegate) {
14946             if ((action == MotionEvent.ACTION_HOVER_ENTER
14947                     || action == MotionEvent.ACTION_HOVER_MOVE)
14948                     && !pointInHoveredChild(event)
14949                     && pointInDelegateRegion) {
14950                 mHoveringTouchDelegate = true;
14951             }
14952         } else {
14953             if (action == MotionEvent.ACTION_HOVER_EXIT
14954                     || (action == MotionEvent.ACTION_HOVER_MOVE
14955                         && (pointInHoveredChild(event) || !pointInDelegateRegion))) {
14956                 mHoveringTouchDelegate = false;
14957             }
14958         }
14959         switch (action) {
14960             case MotionEvent.ACTION_HOVER_MOVE:
14961                 if (oldHoveringTouchDelegate && mHoveringTouchDelegate) {
14962                     // Inside bounds, dispatch as is.
14963                     handled = mTouchDelegate.onTouchExplorationHoverEvent(event);
14964                 } else if (!oldHoveringTouchDelegate && mHoveringTouchDelegate) {
14965                     // Moving inbound, synthesize hover enter.
14966                     MotionEvent eventNoHistory = (event.getHistorySize() == 0)
14967                             ? event : MotionEvent.obtainNoHistory(event);
14968                     eventNoHistory.setAction(MotionEvent.ACTION_HOVER_ENTER);
14969                     handled = mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
14970                     eventNoHistory.setAction(action);
14971                     handled |= mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
14972                 } else if (oldHoveringTouchDelegate && !mHoveringTouchDelegate) {
14973                     // Moving outbound, synthesize hover exit.
14974                     final boolean hoverExitPending = event.isHoverExitPending();
14975                     event.setHoverExitPending(true);
14976                     mTouchDelegate.onTouchExplorationHoverEvent(event);
14977                     MotionEvent eventNoHistory = (event.getHistorySize() == 0)
14978                             ? event : MotionEvent.obtainNoHistory(event);
14979                     eventNoHistory.setHoverExitPending(hoverExitPending);
14980                     eventNoHistory.setAction(MotionEvent.ACTION_HOVER_EXIT);
14981                     mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
14982                 }  // else: outside bounds, do nothing.
14983                 break;
14984             case MotionEvent.ACTION_HOVER_ENTER:
14985                 if (!oldHoveringTouchDelegate && mHoveringTouchDelegate) {
14986                     handled = mTouchDelegate.onTouchExplorationHoverEvent(event);
14987                 }
14988                 break;
14989             case MotionEvent.ACTION_HOVER_EXIT:
14990                 if (oldHoveringTouchDelegate) {
14991                     mTouchDelegate.onTouchExplorationHoverEvent(event);
14992                 }
14993                 break;
14994         }
14995         return handled;
14996     }
14997 
14998     /**
14999      * Implement this method to handle hover events.
15000      * <p>
15001      * This method is called whenever a pointer is hovering into, over, or out of the
15002      * bounds of a view and the view is not currently being touched.
15003      * Hover events are represented as pointer events with action
15004      * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
15005      * or {@link MotionEvent#ACTION_HOVER_EXIT}.
15006      * </p>
15007      * <ul>
15008      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
15009      * when the pointer enters the bounds of the view.</li>
15010      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
15011      * when the pointer has already entered the bounds of the view and has moved.</li>
15012      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
15013      * when the pointer has exited the bounds of the view or when the pointer is
15014      * about to go down due to a button click, tap, or similar user action that
15015      * causes the view to be touched.</li>
15016      * </ul>
15017      * <p>
15018      * The view should implement this method to return true to indicate that it is
15019      * handling the hover event, such as by changing its drawable state.
15020      * </p><p>
15021      * The default implementation calls {@link #setHovered} to update the hovered state
15022      * of the view when a hover enter or hover exit event is received, if the view
15023      * is enabled and is clickable.  The default implementation also sends hover
15024      * accessibility events.
15025      * </p>
15026      *
15027      * @param event The motion event that describes the hover.
15028      * @return True if the view handled the hover event.
15029      *
15030      * @see #isHovered
15031      * @see #setHovered
15032      * @see #onHoverChanged
15033      */
onHoverEvent(MotionEvent event)15034     public boolean onHoverEvent(MotionEvent event) {
15035         if (mTouchDelegate != null && dispatchTouchExplorationHoverEvent(event)) {
15036             return true;
15037         }
15038 
15039         // The root view may receive hover (or touch) events that are outside the bounds of
15040         // the window.  This code ensures that we only send accessibility events for
15041         // hovers that are actually within the bounds of the root view.
15042         final int action = event.getActionMasked();
15043         if (!mSendingHoverAccessibilityEvents) {
15044             if ((action == MotionEvent.ACTION_HOVER_ENTER
15045                     || action == MotionEvent.ACTION_HOVER_MOVE)
15046                     && !hasHoveredChild()
15047                     && pointInView(event.getX(), event.getY())) {
15048                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
15049                 mSendingHoverAccessibilityEvents = true;
15050             }
15051         } else {
15052             if (action == MotionEvent.ACTION_HOVER_EXIT
15053                     || (action == MotionEvent.ACTION_HOVER_MOVE
15054                             && !pointInView(event.getX(), event.getY()))) {
15055                 mSendingHoverAccessibilityEvents = false;
15056                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
15057             }
15058         }
15059 
15060         if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
15061                 && event.isFromSource(InputDevice.SOURCE_MOUSE)
15062                 && isOnScrollbar(event.getX(), event.getY())) {
15063             awakenScrollBars();
15064         }
15065 
15066         // If we consider ourself hoverable, or if we we're already hovered,
15067         // handle changing state in response to ENTER and EXIT events.
15068         if (isHoverable() || isHovered()) {
15069             switch (action) {
15070                 case MotionEvent.ACTION_HOVER_ENTER:
15071                     setHovered(true);
15072                     break;
15073                 case MotionEvent.ACTION_HOVER_EXIT:
15074                     setHovered(false);
15075                     break;
15076             }
15077 
15078             // Dispatch the event to onGenericMotionEvent before returning true.
15079             // This is to provide compatibility with existing applications that
15080             // handled HOVER_MOVE events in onGenericMotionEvent and that would
15081             // break because of the new default handling for hoverable views
15082             // in onHoverEvent.
15083             // Note that onGenericMotionEvent will be called by default when
15084             // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
15085             dispatchGenericMotionEventInternal(event);
15086             // The event was already handled by calling setHovered(), so always
15087             // return true.
15088             return true;
15089         }
15090 
15091         return false;
15092     }
15093 
15094     /**
15095      * Returns true if the view should handle {@link #onHoverEvent}
15096      * by calling {@link #setHovered} to change its hovered state.
15097      *
15098      * @return True if the view is hoverable.
15099      */
isHoverable()15100     private boolean isHoverable() {
15101         final int viewFlags = mViewFlags;
15102         if ((viewFlags & ENABLED_MASK) == DISABLED) {
15103             return false;
15104         }
15105 
15106         return (viewFlags & CLICKABLE) == CLICKABLE
15107                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
15108                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
15109     }
15110 
15111     /**
15112      * Returns true if the view is currently hovered.
15113      *
15114      * @return True if the view is currently hovered.
15115      *
15116      * @see #setHovered
15117      * @see #onHoverChanged
15118      */
15119     @ViewDebug.ExportedProperty
isHovered()15120     public boolean isHovered() {
15121         return (mPrivateFlags & PFLAG_HOVERED) != 0;
15122     }
15123 
15124     /**
15125      * Sets whether the view is currently hovered.
15126      * <p>
15127      * Calling this method also changes the drawable state of the view.  This
15128      * enables the view to react to hover by using different drawable resources
15129      * to change its appearance.
15130      * </p><p>
15131      * The {@link #onHoverChanged} method is called when the hovered state changes.
15132      * </p>
15133      *
15134      * @param hovered True if the view is hovered.
15135      *
15136      * @see #isHovered
15137      * @see #onHoverChanged
15138      */
setHovered(boolean hovered)15139     public void setHovered(boolean hovered) {
15140         if (hovered) {
15141             if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
15142                 mPrivateFlags |= PFLAG_HOVERED;
15143                 refreshDrawableState();
15144                 onHoverChanged(true);
15145             }
15146         } else {
15147             if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
15148                 mPrivateFlags &= ~PFLAG_HOVERED;
15149                 refreshDrawableState();
15150                 onHoverChanged(false);
15151             }
15152         }
15153     }
15154 
15155     /**
15156      * Implement this method to handle hover state changes.
15157      * <p>
15158      * This method is called whenever the hover state changes as a result of a
15159      * call to {@link #setHovered}.
15160      * </p>
15161      *
15162      * @param hovered The current hover state, as returned by {@link #isHovered}.
15163      *
15164      * @see #isHovered
15165      * @see #setHovered
15166      */
onHoverChanged(boolean hovered)15167     public void onHoverChanged(boolean hovered) {
15168     }
15169 
15170     /**
15171      * Handles scroll bar dragging by mouse input.
15172      *
15173      * @hide
15174      * @param event The motion event.
15175      *
15176      * @return true if the event was handled as a scroll bar dragging, false otherwise.
15177      */
handleScrollBarDragging(MotionEvent event)15178     protected boolean handleScrollBarDragging(MotionEvent event) {
15179         if (mScrollCache == null) {
15180             return false;
15181         }
15182         final float x = event.getX();
15183         final float y = event.getY();
15184         final int action = event.getAction();
15185         if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
15186                 && action != MotionEvent.ACTION_DOWN)
15187                     || !event.isFromSource(InputDevice.SOURCE_MOUSE)
15188                     || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
15189             mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
15190             return false;
15191         }
15192 
15193         switch (action) {
15194             case MotionEvent.ACTION_MOVE:
15195                 if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
15196                     return false;
15197                 }
15198                 if (mScrollCache.mScrollBarDraggingState
15199                         == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
15200                     final Rect bounds = mScrollCache.mScrollBarBounds;
15201                     getVerticalScrollBarBounds(bounds, null);
15202                     final int range = computeVerticalScrollRange();
15203                     final int offset = computeVerticalScrollOffset();
15204                     final int extent = computeVerticalScrollExtent();
15205 
15206                     final int thumbLength = ScrollBarUtils.getThumbLength(
15207                             bounds.height(), bounds.width(), extent, range);
15208                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
15209                             bounds.height(), thumbLength, extent, range, offset);
15210 
15211                     final float diff = y - mScrollCache.mScrollBarDraggingPos;
15212                     final float maxThumbOffset = bounds.height() - thumbLength;
15213                     final float newThumbOffset =
15214                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
15215                     final int height = getHeight();
15216                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
15217                             && height > 0 && extent > 0) {
15218                         final int newY = Math.round((range - extent)
15219                                 / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
15220                         if (newY != getScrollY()) {
15221                             mScrollCache.mScrollBarDraggingPos = y;
15222                             setScrollY(newY);
15223                         }
15224                     }
15225                     return true;
15226                 }
15227                 if (mScrollCache.mScrollBarDraggingState
15228                         == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
15229                     final Rect bounds = mScrollCache.mScrollBarBounds;
15230                     getHorizontalScrollBarBounds(bounds, null);
15231                     final int range = computeHorizontalScrollRange();
15232                     final int offset = computeHorizontalScrollOffset();
15233                     final int extent = computeHorizontalScrollExtent();
15234 
15235                     final int thumbLength = ScrollBarUtils.getThumbLength(
15236                             bounds.width(), bounds.height(), extent, range);
15237                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
15238                             bounds.width(), thumbLength, extent, range, offset);
15239 
15240                     final float diff = x - mScrollCache.mScrollBarDraggingPos;
15241                     final float maxThumbOffset = bounds.width() - thumbLength;
15242                     final float newThumbOffset =
15243                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
15244                     final int width = getWidth();
15245                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
15246                             && width > 0 && extent > 0) {
15247                         final int newX = Math.round((range - extent)
15248                                 / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
15249                         if (newX != getScrollX()) {
15250                             mScrollCache.mScrollBarDraggingPos = x;
15251                             setScrollX(newX);
15252                         }
15253                     }
15254                     return true;
15255                 }
15256             case MotionEvent.ACTION_DOWN:
15257                 if (mScrollCache.state == ScrollabilityCache.OFF) {
15258                     return false;
15259                 }
15260                 if (isOnVerticalScrollbarThumb(x, y)) {
15261                     mScrollCache.mScrollBarDraggingState =
15262                             ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
15263                     mScrollCache.mScrollBarDraggingPos = y;
15264                     return true;
15265                 }
15266                 if (isOnHorizontalScrollbarThumb(x, y)) {
15267                     mScrollCache.mScrollBarDraggingState =
15268                             ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
15269                     mScrollCache.mScrollBarDraggingPos = x;
15270                     return true;
15271                 }
15272         }
15273         mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
15274         return false;
15275     }
15276 
15277     /**
15278      * Implement this method to handle touch screen motion events.
15279      * <p>
15280      * If this method is used to detect click actions, it is recommended that
15281      * the actions be performed by implementing and calling
15282      * {@link #performClick()}. This will ensure consistent system behavior,
15283      * including:
15284      * <ul>
15285      * <li>obeying click sound preferences
15286      * <li>dispatching OnClickListener calls
15287      * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
15288      * accessibility features are enabled
15289      * </ul>
15290      *
15291      * @param event The motion event.
15292      * @return True if the event was handled, false otherwise.
15293      */
onTouchEvent(MotionEvent event)15294     public boolean onTouchEvent(MotionEvent event) {
15295         final float x = event.getX();
15296         final float y = event.getY();
15297         final int viewFlags = mViewFlags;
15298         final int action = event.getAction();
15299 
15300         final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE
15301                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
15302                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
15303 
15304         if ((viewFlags & ENABLED_MASK) == DISABLED) {
15305             if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
15306                 setPressed(false);
15307             }
15308             mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
15309             // A disabled view that is clickable still consumes the touch
15310             // events, it just doesn't respond to them.
15311             return clickable;
15312         }
15313         if (mTouchDelegate != null) {
15314             if (mTouchDelegate.onTouchEvent(event)) {
15315                 return true;
15316             }
15317         }
15318 
15319         if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
15320             switch (action) {
15321                 case MotionEvent.ACTION_UP:
15322                     mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
15323                     if ((viewFlags & TOOLTIP) == TOOLTIP) {
15324                         handleTooltipUp();
15325                     }
15326                     if (!clickable) {
15327                         removeTapCallback();
15328                         removeLongPressCallback();
15329                         mInContextButtonPress = false;
15330                         mHasPerformedLongPress = false;
15331                         mIgnoreNextUpEvent = false;
15332                         break;
15333                     }
15334                     boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
15335                     if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
15336                         // take focus if we don't have it already and we should in
15337                         // touch mode.
15338                         boolean focusTaken = false;
15339                         if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
15340                             focusTaken = requestFocus();
15341                         }
15342 
15343                         if (prepressed) {
15344                             // The button is being released before we actually
15345                             // showed it as pressed.  Make it show the pressed
15346                             // state now (before scheduling the click) to ensure
15347                             // the user sees it.
15348                             setPressed(true, x, y);
15349                         }
15350 
15351                         if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
15352                             // This is a tap, so remove the longpress check
15353                             removeLongPressCallback();
15354 
15355                             // Only perform take click actions if we were in the pressed state
15356                             if (!focusTaken) {
15357                                 // Use a Runnable and post this rather than calling
15358                                 // performClick directly. This lets other visual state
15359                                 // of the view update before click actions start.
15360                                 if (mPerformClick == null) {
15361                                     mPerformClick = new PerformClick();
15362                                 }
15363                                 if (!post(mPerformClick)) {
15364                                     performClickInternal();
15365                                 }
15366                             }
15367                         }
15368 
15369                         if (mUnsetPressedState == null) {
15370                             mUnsetPressedState = new UnsetPressedState();
15371                         }
15372 
15373                         if (prepressed) {
15374                             postDelayed(mUnsetPressedState,
15375                                     ViewConfiguration.getPressedStateDuration());
15376                         } else if (!post(mUnsetPressedState)) {
15377                             // If the post failed, unpress right now
15378                             mUnsetPressedState.run();
15379                         }
15380 
15381                         removeTapCallback();
15382                     }
15383                     mIgnoreNextUpEvent = false;
15384                     break;
15385 
15386                 case MotionEvent.ACTION_DOWN:
15387                     if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
15388                         mPrivateFlags3 |= PFLAG3_FINGER_DOWN;
15389                     }
15390                     mHasPerformedLongPress = false;
15391 
15392                     if (!clickable) {
15393                         checkForLongClick(
15394                                 ViewConfiguration.getLongPressTimeout(),
15395                                 x,
15396                                 y,
15397                                 TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
15398                         break;
15399                     }
15400 
15401                     if (performButtonActionOnTouchDown(event)) {
15402                         break;
15403                     }
15404 
15405                     // Walk up the hierarchy to determine if we're inside a scrolling container.
15406                     boolean isInScrollingContainer = isInScrollingContainer();
15407 
15408                     // For views inside a scrolling container, delay the pressed feedback for
15409                     // a short period in case this is a scroll.
15410                     if (isInScrollingContainer) {
15411                         mPrivateFlags |= PFLAG_PREPRESSED;
15412                         if (mPendingCheckForTap == null) {
15413                             mPendingCheckForTap = new CheckForTap();
15414                         }
15415                         mPendingCheckForTap.x = event.getX();
15416                         mPendingCheckForTap.y = event.getY();
15417                         postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
15418                     } else {
15419                         // Not inside a scrolling container, so show the feedback right away
15420                         setPressed(true, x, y);
15421                         checkForLongClick(
15422                                 ViewConfiguration.getLongPressTimeout(),
15423                                 x,
15424                                 y,
15425                                 TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
15426                     }
15427                     break;
15428 
15429                 case MotionEvent.ACTION_CANCEL:
15430                     if (clickable) {
15431                         setPressed(false);
15432                     }
15433                     removeTapCallback();
15434                     removeLongPressCallback();
15435                     mInContextButtonPress = false;
15436                     mHasPerformedLongPress = false;
15437                     mIgnoreNextUpEvent = false;
15438                     mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
15439                     break;
15440 
15441                 case MotionEvent.ACTION_MOVE:
15442                     if (clickable) {
15443                         drawableHotspotChanged(x, y);
15444                     }
15445 
15446                     final int motionClassification = event.getClassification();
15447                     final boolean ambiguousGesture =
15448                             motionClassification == MotionEvent.CLASSIFICATION_AMBIGUOUS_GESTURE;
15449                     int touchSlop = mTouchSlop;
15450                     if (ambiguousGesture && hasPendingLongPressCallback()) {
15451                         final float ambiguousMultiplier =
15452                                 ViewConfiguration.getAmbiguousGestureMultiplier();
15453                         if (!pointInView(x, y, touchSlop)) {
15454                             // The default action here is to cancel long press. But instead, we
15455                             // just extend the timeout here, in case the classification
15456                             // stays ambiguous.
15457                             removeLongPressCallback();
15458                             long delay = (long) (ViewConfiguration.getLongPressTimeout()
15459                                     * ambiguousMultiplier);
15460                             // Subtract the time already spent
15461                             delay -= event.getEventTime() - event.getDownTime();
15462                             checkForLongClick(
15463                                     delay,
15464                                     x,
15465                                     y,
15466                                     TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
15467                         }
15468                         touchSlop *= ambiguousMultiplier;
15469                     }
15470 
15471                     // Be lenient about moving outside of buttons
15472                     if (!pointInView(x, y, touchSlop)) {
15473                         // Outside button
15474                         // Remove any future long press/tap checks
15475                         removeTapCallback();
15476                         removeLongPressCallback();
15477                         if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
15478                             setPressed(false);
15479                         }
15480                         mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
15481                     }
15482 
15483                     final boolean deepPress =
15484                             motionClassification == MotionEvent.CLASSIFICATION_DEEP_PRESS;
15485                     if (deepPress && hasPendingLongPressCallback()) {
15486                         // process the long click action immediately
15487                         removeLongPressCallback();
15488                         checkForLongClick(
15489                                 0 /* send immediately */,
15490                                 x,
15491                                 y,
15492                                 TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS);
15493                     }
15494 
15495                     break;
15496             }
15497 
15498             return true;
15499         }
15500 
15501         return false;
15502     }
15503 
15504     /**
15505      * @hide
15506      */
15507     @UnsupportedAppUsage
isInScrollingContainer()15508     public boolean isInScrollingContainer() {
15509         ViewParent p = getParent();
15510         while (p != null && p instanceof ViewGroup) {
15511             if (((ViewGroup) p).shouldDelayChildPressedState()) {
15512                 return true;
15513             }
15514             p = p.getParent();
15515         }
15516         return false;
15517     }
15518 
15519     /**
15520      * Remove the longpress detection timer.
15521      */
removeLongPressCallback()15522     private void removeLongPressCallback() {
15523         if (mPendingCheckForLongPress != null) {
15524             removeCallbacks(mPendingCheckForLongPress);
15525         }
15526     }
15527 
15528     /**
15529      * Return true if the long press callback is scheduled to run sometime in the future.
15530      * Return false if there is no scheduled long press callback at the moment.
15531      */
hasPendingLongPressCallback()15532     private boolean hasPendingLongPressCallback() {
15533         if (mPendingCheckForLongPress == null) {
15534             return false;
15535         }
15536         final AttachInfo attachInfo = mAttachInfo;
15537         if (attachInfo == null) {
15538             return false;
15539         }
15540         return attachInfo.mHandler.hasCallbacks(mPendingCheckForLongPress);
15541     }
15542 
15543    /**
15544      * Remove the pending click action
15545      */
15546     @UnsupportedAppUsage
removePerformClickCallback()15547     private void removePerformClickCallback() {
15548         if (mPerformClick != null) {
15549             removeCallbacks(mPerformClick);
15550         }
15551     }
15552 
15553     /**
15554      * Remove the prepress detection timer.
15555      */
removeUnsetPressCallback()15556     private void removeUnsetPressCallback() {
15557         if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
15558             setPressed(false);
15559             removeCallbacks(mUnsetPressedState);
15560         }
15561     }
15562 
15563     /**
15564      * Remove the tap detection timer.
15565      */
removeTapCallback()15566     private void removeTapCallback() {
15567         if (mPendingCheckForTap != null) {
15568             mPrivateFlags &= ~PFLAG_PREPRESSED;
15569             removeCallbacks(mPendingCheckForTap);
15570         }
15571     }
15572 
15573     /**
15574      * Cancels a pending long press.  Your subclass can use this if you
15575      * want the context menu to come up if the user presses and holds
15576      * at the same place, but you don't want it to come up if they press
15577      * and then move around enough to cause scrolling.
15578      */
cancelLongPress()15579     public void cancelLongPress() {
15580         removeLongPressCallback();
15581 
15582         /*
15583          * The prepressed state handled by the tap callback is a display
15584          * construct, but the tap callback will post a long press callback
15585          * less its own timeout. Remove it here.
15586          */
15587         removeTapCallback();
15588     }
15589 
15590     /**
15591      * Sets the TouchDelegate for this View.
15592      */
setTouchDelegate(TouchDelegate delegate)15593     public void setTouchDelegate(TouchDelegate delegate) {
15594         mTouchDelegate = delegate;
15595     }
15596 
15597     /**
15598      * Gets the TouchDelegate for this View.
15599      */
getTouchDelegate()15600     public TouchDelegate getTouchDelegate() {
15601         return mTouchDelegate;
15602     }
15603 
15604     /**
15605      * Request unbuffered dispatch of the given stream of MotionEvents to this View.
15606      *
15607      * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
15608      * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
15609      * available. This method should only be called for touch events.
15610      *
15611      * <p class="note">This api is not intended for most applications. Buffered dispatch
15612      * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
15613      * streams will not improve your input latency. Side effects include: increased latency,
15614      * jittery scrolls and inability to take advantage of system resampling. Talk to your input
15615      * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
15616      * you.</p>
15617      */
requestUnbufferedDispatch(MotionEvent event)15618     public final void requestUnbufferedDispatch(MotionEvent event) {
15619         final int action = event.getAction();
15620         if (mAttachInfo == null
15621                 || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
15622                 || !event.isTouchEvent()) {
15623             return;
15624         }
15625         mAttachInfo.mUnbufferedDispatchRequested = true;
15626     }
15627 
hasSize()15628     private boolean hasSize() {
15629         return (mBottom > mTop) && (mRight > mLeft);
15630     }
15631 
canTakeFocus()15632     private boolean canTakeFocus() {
15633         return ((mViewFlags & VISIBILITY_MASK) == VISIBLE)
15634                 && ((mViewFlags & FOCUSABLE) == FOCUSABLE)
15635                 && ((mViewFlags & ENABLED_MASK) == ENABLED)
15636                 && (sCanFocusZeroSized || !isLayoutValid() || hasSize());
15637     }
15638 
15639     /**
15640      * Set flags controlling behavior of this view.
15641      *
15642      * @param flags Constant indicating the value which should be set
15643      * @param mask Constant indicating the bit range that should be changed
15644      */
15645     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
setFlags(int flags, int mask)15646     void setFlags(int flags, int mask) {
15647         final boolean accessibilityEnabled =
15648                 AccessibilityManager.getInstance(mContext).isEnabled();
15649         final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
15650 
15651         int old = mViewFlags;
15652         mViewFlags = (mViewFlags & ~mask) | (flags & mask);
15653 
15654         int changed = mViewFlags ^ old;
15655         if (changed == 0) {
15656             return;
15657         }
15658         int privateFlags = mPrivateFlags;
15659         boolean shouldNotifyFocusableAvailable = false;
15660 
15661         // If focusable is auto, update the FOCUSABLE bit.
15662         int focusableChangedByAuto = 0;
15663         if (((mViewFlags & FOCUSABLE_AUTO) != 0)
15664                 && (changed & (FOCUSABLE_MASK | CLICKABLE)) != 0) {
15665             // Heuristic only takes into account whether view is clickable.
15666             final int newFocus;
15667             if ((mViewFlags & CLICKABLE) != 0) {
15668                 newFocus = FOCUSABLE;
15669             } else {
15670                 newFocus = NOT_FOCUSABLE;
15671             }
15672             mViewFlags = (mViewFlags & ~FOCUSABLE) | newFocus;
15673             focusableChangedByAuto = (old & FOCUSABLE) ^ (newFocus & FOCUSABLE);
15674             changed = (changed & ~FOCUSABLE) | focusableChangedByAuto;
15675         }
15676 
15677         /* Check if the FOCUSABLE bit has changed */
15678         if (((changed & FOCUSABLE) != 0) && ((privateFlags & PFLAG_HAS_BOUNDS) != 0)) {
15679             if (((old & FOCUSABLE) == FOCUSABLE)
15680                     && ((privateFlags & PFLAG_FOCUSED) != 0)) {
15681                 /* Give up focus if we are no longer focusable */
15682                 clearFocus();
15683                 if (mParent instanceof ViewGroup) {
15684                     ((ViewGroup) mParent).clearFocusedInCluster();
15685                 }
15686             } else if (((old & FOCUSABLE) == NOT_FOCUSABLE)
15687                     && ((privateFlags & PFLAG_FOCUSED) == 0)) {
15688                 /*
15689                  * Tell the view system that we are now available to take focus
15690                  * if no one else already has it.
15691                  */
15692                 if (mParent != null) {
15693                     ViewRootImpl viewRootImpl = getViewRootImpl();
15694                     if (!sAutoFocusableOffUIThreadWontNotifyParents
15695                             || focusableChangedByAuto == 0
15696                             || viewRootImpl == null
15697                             || viewRootImpl.mThread == Thread.currentThread()) {
15698                         shouldNotifyFocusableAvailable = canTakeFocus();
15699                     }
15700                 }
15701             }
15702         }
15703 
15704         final int newVisibility = flags & VISIBILITY_MASK;
15705         if (newVisibility == VISIBLE) {
15706             if ((changed & VISIBILITY_MASK) != 0) {
15707                 /*
15708                  * If this view is becoming visible, invalidate it in case it changed while
15709                  * it was not visible. Marking it drawn ensures that the invalidation will
15710                  * go through.
15711                  */
15712                 mPrivateFlags |= PFLAG_DRAWN;
15713                 invalidate(true);
15714 
15715                 needGlobalAttributesUpdate(true);
15716 
15717                 // a view becoming visible is worth notifying the parent about in case nothing has
15718                 // focus. Even if this specific view isn't focusable, it may contain something that
15719                 // is, so let the root view try to give this focus if nothing else does.
15720                 shouldNotifyFocusableAvailable = hasSize();
15721             }
15722         }
15723 
15724         if ((changed & ENABLED_MASK) != 0) {
15725             if ((mViewFlags & ENABLED_MASK) == ENABLED) {
15726                 // a view becoming enabled should notify the parent as long as the view is also
15727                 // visible and the parent wasn't already notified by becoming visible during this
15728                 // setFlags invocation.
15729                 shouldNotifyFocusableAvailable = canTakeFocus();
15730             } else {
15731                 if (isFocused()) clearFocus();
15732             }
15733         }
15734 
15735         if (shouldNotifyFocusableAvailable && mParent != null) {
15736             mParent.focusableViewAvailable(this);
15737         }
15738 
15739         /* Check if the GONE bit has changed */
15740         if ((changed & GONE) != 0) {
15741             needGlobalAttributesUpdate(false);
15742             requestLayout();
15743 
15744             if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
15745                 if (hasFocus()) {
15746                     clearFocus();
15747                     if (mParent instanceof ViewGroup) {
15748                         ((ViewGroup) mParent).clearFocusedInCluster();
15749                     }
15750                 }
15751                 clearAccessibilityFocus();
15752                 destroyDrawingCache();
15753                 if (mParent instanceof View) {
15754                     // GONE views noop invalidation, so invalidate the parent
15755                     ((View) mParent).invalidate(true);
15756                 }
15757                 // Mark the view drawn to ensure that it gets invalidated properly the next
15758                 // time it is visible and gets invalidated
15759                 mPrivateFlags |= PFLAG_DRAWN;
15760             }
15761             if (mAttachInfo != null) {
15762                 mAttachInfo.mViewVisibilityChanged = true;
15763             }
15764         }
15765 
15766         /* Check if the VISIBLE bit has changed */
15767         if ((changed & INVISIBLE) != 0) {
15768             needGlobalAttributesUpdate(false);
15769             /*
15770              * If this view is becoming invisible, set the DRAWN flag so that
15771              * the next invalidate() will not be skipped.
15772              */
15773             mPrivateFlags |= PFLAG_DRAWN;
15774 
15775             if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
15776                 // root view becoming invisible shouldn't clear focus and accessibility focus
15777                 if (getRootView() != this) {
15778                     if (hasFocus()) {
15779                         clearFocus();
15780                         if (mParent instanceof ViewGroup) {
15781                             ((ViewGroup) mParent).clearFocusedInCluster();
15782                         }
15783                     }
15784                     clearAccessibilityFocus();
15785                 }
15786             }
15787             if (mAttachInfo != null) {
15788                 mAttachInfo.mViewVisibilityChanged = true;
15789             }
15790         }
15791 
15792         if ((changed & VISIBILITY_MASK) != 0) {
15793             // If the view is invisible, cleanup its display list to free up resources
15794             if (newVisibility != VISIBLE && mAttachInfo != null) {
15795                 cleanupDraw();
15796             }
15797 
15798             if (mParent instanceof ViewGroup) {
15799                 ViewGroup parent = (ViewGroup) mParent;
15800                 parent.onChildVisibilityChanged(this, (changed & VISIBILITY_MASK),
15801                         newVisibility);
15802                 parent.invalidate(true);
15803             } else if (mParent != null) {
15804                 mParent.invalidateChild(this, null);
15805             }
15806 
15807             if (mAttachInfo != null) {
15808                 dispatchVisibilityChanged(this, newVisibility);
15809 
15810                 // Aggregated visibility changes are dispatched to attached views
15811                 // in visible windows where the parent is currently shown/drawn
15812                 // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
15813                 // discounting clipping or overlapping. This makes it a good place
15814                 // to change animation states.
15815                 if (mParent != null && getWindowVisibility() == VISIBLE &&
15816                         ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
15817                     dispatchVisibilityAggregated(newVisibility == VISIBLE);
15818                 }
15819                 notifySubtreeAccessibilityStateChangedIfNeeded();
15820             }
15821         }
15822 
15823         if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
15824             destroyDrawingCache();
15825         }
15826 
15827         if ((changed & DRAWING_CACHE_ENABLED) != 0) {
15828             destroyDrawingCache();
15829             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
15830             invalidateParentCaches();
15831         }
15832 
15833         if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
15834             destroyDrawingCache();
15835             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
15836         }
15837 
15838         if ((changed & DRAW_MASK) != 0) {
15839             if ((mViewFlags & WILL_NOT_DRAW) != 0) {
15840                 if (mBackground != null
15841                         || mDefaultFocusHighlight != null
15842                         || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
15843                     mPrivateFlags &= ~PFLAG_SKIP_DRAW;
15844                 } else {
15845                     mPrivateFlags |= PFLAG_SKIP_DRAW;
15846                 }
15847             } else {
15848                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
15849             }
15850             requestLayout();
15851             invalidate(true);
15852         }
15853 
15854         if ((changed & KEEP_SCREEN_ON) != 0) {
15855             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
15856                 mParent.recomputeViewAttributes(this);
15857             }
15858         }
15859 
15860         if (accessibilityEnabled) {
15861             // If we're an accessibility pane and the visibility changed, we already have sent
15862             // a state change, so we really don't need to report other changes.
15863             if (isAccessibilityPane()) {
15864                 changed &= ~VISIBILITY_MASK;
15865             }
15866             if ((changed & FOCUSABLE) != 0 || (changed & VISIBILITY_MASK) != 0
15867                     || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
15868                     || (changed & CONTEXT_CLICKABLE) != 0) {
15869                 if (oldIncludeForAccessibility != includeForAccessibility()) {
15870                     notifySubtreeAccessibilityStateChangedIfNeeded();
15871                 } else {
15872                     notifyViewAccessibilityStateChangedIfNeeded(
15873                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
15874                 }
15875             } else if ((changed & ENABLED_MASK) != 0) {
15876                 notifyViewAccessibilityStateChangedIfNeeded(
15877                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
15878             }
15879         }
15880     }
15881 
15882     /**
15883      * Change the view's z order in the tree, so it's on top of other sibling
15884      * views. This ordering change may affect layout, if the parent container
15885      * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
15886      * to {@link android.os.Build.VERSION_CODES#KITKAT} this
15887      * method should be followed by calls to {@link #requestLayout()} and
15888      * {@link View#invalidate()} on the view's parent to force the parent to redraw
15889      * with the new child ordering.
15890      *
15891      * @see ViewGroup#bringChildToFront(View)
15892      */
bringToFront()15893     public void bringToFront() {
15894         if (mParent != null) {
15895             mParent.bringChildToFront(this);
15896         }
15897     }
15898 
15899     /**
15900      * This is called in response to an internal scroll in this view (i.e., the
15901      * view scrolled its own contents). This is typically as a result of
15902      * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
15903      * called.
15904      *
15905      * @param l Current horizontal scroll origin.
15906      * @param t Current vertical scroll origin.
15907      * @param oldl Previous horizontal scroll origin.
15908      * @param oldt Previous vertical scroll origin.
15909      */
onScrollChanged(int l, int t, int oldl, int oldt)15910     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
15911         notifySubtreeAccessibilityStateChangedIfNeeded();
15912 
15913         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
15914             postSendViewScrolledAccessibilityEventCallback(l - oldl, t - oldt);
15915         }
15916 
15917         mBackgroundSizeChanged = true;
15918         mDefaultFocusHighlightSizeChanged = true;
15919         if (mForegroundInfo != null) {
15920             mForegroundInfo.mBoundsChanged = true;
15921         }
15922 
15923         final AttachInfo ai = mAttachInfo;
15924         if (ai != null) {
15925             ai.mViewScrollChanged = true;
15926         }
15927 
15928         if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
15929             mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
15930         }
15931     }
15932 
15933     /**
15934      * Interface definition for a callback to be invoked when the scroll
15935      * X or Y positions of a view change.
15936      * <p>
15937      * <b>Note:</b> Some views handle scrolling independently from View and may
15938      * have their own separate listeners for scroll-type events. For example,
15939      * {@link android.widget.ListView ListView} allows clients to register an
15940      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
15941      * to listen for changes in list scroll position.
15942      *
15943      * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
15944      */
15945     public interface OnScrollChangeListener {
15946         /**
15947          * Called when the scroll position of a view changes.
15948          *
15949          * @param v The view whose scroll position has changed.
15950          * @param scrollX Current horizontal scroll origin.
15951          * @param scrollY Current vertical scroll origin.
15952          * @param oldScrollX Previous horizontal scroll origin.
15953          * @param oldScrollY Previous vertical scroll origin.
15954          */
onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY)15955         void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
15956     }
15957 
15958     /**
15959      * Interface definition for a callback to be invoked when the layout bounds of a view
15960      * changes due to layout processing.
15961      */
15962     public interface OnLayoutChangeListener {
15963         /**
15964          * Called when the layout bounds of a view changes due to layout processing.
15965          *
15966          * @param v The view whose bounds have changed.
15967          * @param left The new value of the view's left property.
15968          * @param top The new value of the view's top property.
15969          * @param right The new value of the view's right property.
15970          * @param bottom The new value of the view's bottom property.
15971          * @param oldLeft The previous value of the view's left property.
15972          * @param oldTop The previous value of the view's top property.
15973          * @param oldRight The previous value of the view's right property.
15974          * @param oldBottom The previous value of the view's bottom property.
15975          */
onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom)15976         void onLayoutChange(View v, int left, int top, int right, int bottom,
15977             int oldLeft, int oldTop, int oldRight, int oldBottom);
15978     }
15979 
15980     /**
15981      * This is called during layout when the size of this view has changed. If
15982      * you were just added to the view hierarchy, you're called with the old
15983      * values of 0.
15984      *
15985      * @param w Current width of this view.
15986      * @param h Current height of this view.
15987      * @param oldw Old width of this view.
15988      * @param oldh Old height of this view.
15989      */
onSizeChanged(int w, int h, int oldw, int oldh)15990     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
15991     }
15992 
15993     /**
15994      * Called by draw to draw the child views. This may be overridden
15995      * by derived classes to gain control just before its children are drawn
15996      * (but after its own view has been drawn).
15997      * @param canvas the canvas on which to draw the view
15998      */
dispatchDraw(Canvas canvas)15999     protected void dispatchDraw(Canvas canvas) {
16000 
16001     }
16002 
16003     /**
16004      * Gets the parent of this view. Note that the parent is a
16005      * ViewParent and not necessarily a View.
16006      *
16007      * @return Parent of this view.
16008      */
getParent()16009     public final ViewParent getParent() {
16010         return mParent;
16011     }
16012 
16013     /**
16014      * Set the horizontal scrolled position of your view. This will cause a call to
16015      * {@link #onScrollChanged(int, int, int, int)} and the view will be
16016      * invalidated.
16017      * @param value the x position to scroll to
16018      */
setScrollX(int value)16019     public void setScrollX(int value) {
16020         scrollTo(value, mScrollY);
16021     }
16022 
16023     /**
16024      * Set the vertical scrolled position of your view. This will cause a call to
16025      * {@link #onScrollChanged(int, int, int, int)} and the view will be
16026      * invalidated.
16027      * @param value the y position to scroll to
16028      */
setScrollY(int value)16029     public void setScrollY(int value) {
16030         scrollTo(mScrollX, value);
16031     }
16032 
16033     /**
16034      * Return the scrolled left position of this view. This is the left edge of
16035      * the displayed part of your view. You do not need to draw any pixels
16036      * farther left, since those are outside of the frame of your view on
16037      * screen.
16038      *
16039      * @return The left edge of the displayed part of your view, in pixels.
16040      */
16041     @InspectableProperty
getScrollX()16042     public final int getScrollX() {
16043         return mScrollX;
16044     }
16045 
16046     /**
16047      * Return the scrolled top position of this view. This is the top edge of
16048      * the displayed part of your view. You do not need to draw any pixels above
16049      * it, since those are outside of the frame of your view on screen.
16050      *
16051      * @return The top edge of the displayed part of your view, in pixels.
16052      */
16053     @InspectableProperty
getScrollY()16054     public final int getScrollY() {
16055         return mScrollY;
16056     }
16057 
16058     /**
16059      * Return the width of your view.
16060      *
16061      * @return The width of your view, in pixels.
16062      */
16063     @ViewDebug.ExportedProperty(category = "layout")
getWidth()16064     public final int getWidth() {
16065         return mRight - mLeft;
16066     }
16067 
16068     /**
16069      * Return the height of your view.
16070      *
16071      * @return The height of your view, in pixels.
16072      */
16073     @ViewDebug.ExportedProperty(category = "layout")
getHeight()16074     public final int getHeight() {
16075         return mBottom - mTop;
16076     }
16077 
16078     /**
16079      * Return the visible drawing bounds of your view. Fills in the output
16080      * rectangle with the values from getScrollX(), getScrollY(),
16081      * getWidth(), and getHeight(). These bounds do not account for any
16082      * transformation properties currently set on the view, such as
16083      * {@link #setScaleX(float)} or {@link #setRotation(float)}.
16084      *
16085      * @param outRect The (scrolled) drawing bounds of the view.
16086      */
getDrawingRect(Rect outRect)16087     public void getDrawingRect(Rect outRect) {
16088         outRect.left = mScrollX;
16089         outRect.top = mScrollY;
16090         outRect.right = mScrollX + (mRight - mLeft);
16091         outRect.bottom = mScrollY + (mBottom - mTop);
16092     }
16093 
16094     /**
16095      * Like {@link #getMeasuredWidthAndState()}, but only returns the
16096      * raw width component (that is the result is masked by
16097      * {@link #MEASURED_SIZE_MASK}).
16098      *
16099      * @return The raw measured width of this view.
16100      */
getMeasuredWidth()16101     public final int getMeasuredWidth() {
16102         return mMeasuredWidth & MEASURED_SIZE_MASK;
16103     }
16104 
16105     /**
16106      * Return the full width measurement information for this view as computed
16107      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
16108      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
16109      * This should be used during measurement and layout calculations only. Use
16110      * {@link #getWidth()} to see how wide a view is after layout.
16111      *
16112      * @return The measured width of this view as a bit mask.
16113      */
16114     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
16115             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
16116                     name = "MEASURED_STATE_TOO_SMALL"),
16117     })
getMeasuredWidthAndState()16118     public final int getMeasuredWidthAndState() {
16119         return mMeasuredWidth;
16120     }
16121 
16122     /**
16123      * Like {@link #getMeasuredHeightAndState()}, but only returns the
16124      * raw height component (that is the result is masked by
16125      * {@link #MEASURED_SIZE_MASK}).
16126      *
16127      * @return The raw measured height of this view.
16128      */
getMeasuredHeight()16129     public final int getMeasuredHeight() {
16130         return mMeasuredHeight & MEASURED_SIZE_MASK;
16131     }
16132 
16133     /**
16134      * Return the full height measurement information for this view as computed
16135      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
16136      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
16137      * This should be used during measurement and layout calculations only. Use
16138      * {@link #getHeight()} to see how high a view is after layout.
16139      *
16140      * @return The measured height of this view as a bit mask.
16141      */
16142     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
16143             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
16144                     name = "MEASURED_STATE_TOO_SMALL"),
16145     })
getMeasuredHeightAndState()16146     public final int getMeasuredHeightAndState() {
16147         return mMeasuredHeight;
16148     }
16149 
16150     /**
16151      * Return only the state bits of {@link #getMeasuredWidthAndState()}
16152      * and {@link #getMeasuredHeightAndState()}, combined into one integer.
16153      * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
16154      * and the height component is at the shifted bits
16155      * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
16156      */
getMeasuredState()16157     public final int getMeasuredState() {
16158         return (mMeasuredWidth&MEASURED_STATE_MASK)
16159                 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
16160                         & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
16161     }
16162 
16163     /**
16164      * The transform matrix of this view, which is calculated based on the current
16165      * rotation, scale, and pivot properties.
16166      *
16167      * @see #getRotation()
16168      * @see #getScaleX()
16169      * @see #getScaleY()
16170      * @see #getPivotX()
16171      * @see #getPivotY()
16172      * @return The current transform matrix for the view
16173      */
getMatrix()16174     public Matrix getMatrix() {
16175         ensureTransformationInfo();
16176         final Matrix matrix = mTransformationInfo.mMatrix;
16177         mRenderNode.getMatrix(matrix);
16178         return matrix;
16179     }
16180 
16181     /**
16182      * Returns true if the transform matrix is the identity matrix.
16183      * Recomputes the matrix if necessary.
16184      *
16185      * @return True if the transform matrix is the identity matrix, false otherwise.
16186      * @hide
16187      */
16188     @UnsupportedAppUsage
hasIdentityMatrix()16189     public final boolean hasIdentityMatrix() {
16190         return mRenderNode.hasIdentityMatrix();
16191     }
16192 
16193     @UnsupportedAppUsage
ensureTransformationInfo()16194     void ensureTransformationInfo() {
16195         if (mTransformationInfo == null) {
16196             mTransformationInfo = new TransformationInfo();
16197         }
16198     }
16199 
16200     /**
16201      * Utility method to retrieve the inverse of the current mMatrix property.
16202      * We cache the matrix to avoid recalculating it when transform properties
16203      * have not changed.
16204      *
16205      * @return The inverse of the current matrix of this view.
16206      * @hide
16207      */
16208     @UnsupportedAppUsage
getInverseMatrix()16209     public final Matrix getInverseMatrix() {
16210         ensureTransformationInfo();
16211         if (mTransformationInfo.mInverseMatrix == null) {
16212             mTransformationInfo.mInverseMatrix = new Matrix();
16213         }
16214         final Matrix matrix = mTransformationInfo.mInverseMatrix;
16215         mRenderNode.getInverseMatrix(matrix);
16216         return matrix;
16217     }
16218 
16219     /**
16220      * Gets the distance along the Z axis from the camera to this view.
16221      *
16222      * @see #setCameraDistance(float)
16223      *
16224      * @return The distance along the Z axis.
16225      */
getCameraDistance()16226     public float getCameraDistance() {
16227         final float dpi = mResources.getDisplayMetrics().densityDpi;
16228         return mRenderNode.getCameraDistance() * dpi;
16229     }
16230 
16231     /**
16232      * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
16233      * views are drawn) from the camera to this view. The camera's distance
16234      * affects 3D transformations, for instance rotations around the X and Y
16235      * axis. If the rotationX or rotationY properties are changed and this view is
16236      * large (more than half the size of the screen), it is recommended to always
16237      * use a camera distance that's greater than the height (X axis rotation) or
16238      * the width (Y axis rotation) of this view.</p>
16239      *
16240      * <p>The distance of the camera from the view plane can have an affect on the
16241      * perspective distortion of the view when it is rotated around the x or y axis.
16242      * For example, a large distance will result in a large viewing angle, and there
16243      * will not be much perspective distortion of the view as it rotates. A short
16244      * distance may cause much more perspective distortion upon rotation, and can
16245      * also result in some drawing artifacts if the rotated view ends up partially
16246      * behind the camera (which is why the recommendation is to use a distance at
16247      * least as far as the size of the view, if the view is to be rotated.)</p>
16248      *
16249      * <p>The distance is expressed in "depth pixels." The default distance depends
16250      * on the screen density. For instance, on a medium density display, the
16251      * default distance is 1280. On a high density display, the default distance
16252      * is 1920.</p>
16253      *
16254      * <p>If you want to specify a distance that leads to visually consistent
16255      * results across various densities, use the following formula:</p>
16256      * <pre>
16257      * float scale = context.getResources().getDisplayMetrics().density;
16258      * view.setCameraDistance(distance * scale);
16259      * </pre>
16260      *
16261      * <p>The density scale factor of a high density display is 1.5,
16262      * and 1920 = 1280 * 1.5.</p>
16263      *
16264      * @param distance The distance in "depth pixels", if negative the opposite
16265      *        value is used
16266      *
16267      * @see #setRotationX(float)
16268      * @see #setRotationY(float)
16269      */
setCameraDistance(float distance)16270     public void setCameraDistance(float distance) {
16271         final float dpi = mResources.getDisplayMetrics().densityDpi;
16272 
16273         invalidateViewProperty(true, false);
16274         mRenderNode.setCameraDistance(Math.abs(distance) / dpi);
16275         invalidateViewProperty(false, false);
16276 
16277         invalidateParentIfNeededAndWasQuickRejected();
16278     }
16279 
16280     /**
16281      * The degrees that the view is rotated around the pivot point.
16282      *
16283      * @see #setRotation(float)
16284      * @see #getPivotX()
16285      * @see #getPivotY()
16286      *
16287      * @return The degrees of rotation.
16288      */
16289     @ViewDebug.ExportedProperty(category = "drawing")
16290     @InspectableProperty
getRotation()16291     public float getRotation() {
16292         return mRenderNode.getRotationZ();
16293     }
16294 
16295     /**
16296      * Sets the degrees that the view is rotated around the pivot point. Increasing values
16297      * result in clockwise rotation.
16298      *
16299      * @param rotation The degrees of rotation.
16300      *
16301      * @see #getRotation()
16302      * @see #getPivotX()
16303      * @see #getPivotY()
16304      * @see #setRotationX(float)
16305      * @see #setRotationY(float)
16306      *
16307      * @attr ref android.R.styleable#View_rotation
16308      */
setRotation(float rotation)16309     public void setRotation(float rotation) {
16310         if (rotation != getRotation()) {
16311             // Double-invalidation is necessary to capture view's old and new areas
16312             invalidateViewProperty(true, false);
16313             mRenderNode.setRotationZ(rotation);
16314             invalidateViewProperty(false, true);
16315 
16316             invalidateParentIfNeededAndWasQuickRejected();
16317             notifySubtreeAccessibilityStateChangedIfNeeded();
16318         }
16319     }
16320 
16321     /**
16322      * The degrees that the view is rotated around the vertical axis through the pivot point.
16323      *
16324      * @see #getPivotX()
16325      * @see #getPivotY()
16326      * @see #setRotationY(float)
16327      *
16328      * @return The degrees of Y rotation.
16329      */
16330     @ViewDebug.ExportedProperty(category = "drawing")
16331     @InspectableProperty
getRotationY()16332     public float getRotationY() {
16333         return mRenderNode.getRotationY();
16334     }
16335 
16336     /**
16337      * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
16338      * Increasing values result in counter-clockwise rotation from the viewpoint of looking
16339      * down the y axis.
16340      *
16341      * When rotating large views, it is recommended to adjust the camera distance
16342      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
16343      *
16344      * @param rotationY The degrees of Y rotation.
16345      *
16346      * @see #getRotationY()
16347      * @see #getPivotX()
16348      * @see #getPivotY()
16349      * @see #setRotation(float)
16350      * @see #setRotationX(float)
16351      * @see #setCameraDistance(float)
16352      *
16353      * @attr ref android.R.styleable#View_rotationY
16354      */
setRotationY(float rotationY)16355     public void setRotationY(float rotationY) {
16356         if (rotationY != getRotationY()) {
16357             invalidateViewProperty(true, false);
16358             mRenderNode.setRotationY(rotationY);
16359             invalidateViewProperty(false, true);
16360 
16361             invalidateParentIfNeededAndWasQuickRejected();
16362             notifySubtreeAccessibilityStateChangedIfNeeded();
16363         }
16364     }
16365 
16366     /**
16367      * The degrees that the view is rotated around the horizontal axis through the pivot point.
16368      *
16369      * @see #getPivotX()
16370      * @see #getPivotY()
16371      * @see #setRotationX(float)
16372      *
16373      * @return The degrees of X rotation.
16374      */
16375     @ViewDebug.ExportedProperty(category = "drawing")
16376     @InspectableProperty
getRotationX()16377     public float getRotationX() {
16378         return mRenderNode.getRotationX();
16379     }
16380 
16381     /**
16382      * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
16383      * Increasing values result in clockwise rotation from the viewpoint of looking down the
16384      * x axis.
16385      *
16386      * When rotating large views, it is recommended to adjust the camera distance
16387      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
16388      *
16389      * @param rotationX The degrees of X rotation.
16390      *
16391      * @see #getRotationX()
16392      * @see #getPivotX()
16393      * @see #getPivotY()
16394      * @see #setRotation(float)
16395      * @see #setRotationY(float)
16396      * @see #setCameraDistance(float)
16397      *
16398      * @attr ref android.R.styleable#View_rotationX
16399      */
setRotationX(float rotationX)16400     public void setRotationX(float rotationX) {
16401         if (rotationX != getRotationX()) {
16402             invalidateViewProperty(true, false);
16403             mRenderNode.setRotationX(rotationX);
16404             invalidateViewProperty(false, true);
16405 
16406             invalidateParentIfNeededAndWasQuickRejected();
16407             notifySubtreeAccessibilityStateChangedIfNeeded();
16408         }
16409     }
16410 
16411     /**
16412      * The amount that the view is scaled in x around the pivot point, as a proportion of
16413      * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
16414      *
16415      * <p>By default, this is 1.0f.
16416      *
16417      * @see #getPivotX()
16418      * @see #getPivotY()
16419      * @return The scaling factor.
16420      */
16421     @ViewDebug.ExportedProperty(category = "drawing")
16422     @InspectableProperty
getScaleX()16423     public float getScaleX() {
16424         return mRenderNode.getScaleX();
16425     }
16426 
16427     /**
16428      * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
16429      * the view's unscaled width. A value of 1 means that no scaling is applied.
16430      *
16431      * @param scaleX The scaling factor.
16432      * @see #getPivotX()
16433      * @see #getPivotY()
16434      *
16435      * @attr ref android.R.styleable#View_scaleX
16436      */
setScaleX(float scaleX)16437     public void setScaleX(float scaleX) {
16438         if (scaleX != getScaleX()) {
16439             scaleX = sanitizeFloatPropertyValue(scaleX, "scaleX");
16440             invalidateViewProperty(true, false);
16441             mRenderNode.setScaleX(scaleX);
16442             invalidateViewProperty(false, true);
16443 
16444             invalidateParentIfNeededAndWasQuickRejected();
16445             notifySubtreeAccessibilityStateChangedIfNeeded();
16446         }
16447     }
16448 
16449     /**
16450      * The amount that the view is scaled in y around the pivot point, as a proportion of
16451      * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
16452      *
16453      * <p>By default, this is 1.0f.
16454      *
16455      * @see #getPivotX()
16456      * @see #getPivotY()
16457      * @return The scaling factor.
16458      */
16459     @ViewDebug.ExportedProperty(category = "drawing")
16460     @InspectableProperty
getScaleY()16461     public float getScaleY() {
16462         return mRenderNode.getScaleY();
16463     }
16464 
16465     /**
16466      * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
16467      * the view's unscaled width. A value of 1 means that no scaling is applied.
16468      *
16469      * @param scaleY The scaling factor.
16470      * @see #getPivotX()
16471      * @see #getPivotY()
16472      *
16473      * @attr ref android.R.styleable#View_scaleY
16474      */
setScaleY(float scaleY)16475     public void setScaleY(float scaleY) {
16476         if (scaleY != getScaleY()) {
16477             scaleY = sanitizeFloatPropertyValue(scaleY, "scaleY");
16478             invalidateViewProperty(true, false);
16479             mRenderNode.setScaleY(scaleY);
16480             invalidateViewProperty(false, true);
16481 
16482             invalidateParentIfNeededAndWasQuickRejected();
16483             notifySubtreeAccessibilityStateChangedIfNeeded();
16484         }
16485     }
16486 
16487     /**
16488      * The x location of the point around which the view is {@link #setRotation(float) rotated}
16489      * and {@link #setScaleX(float) scaled}.
16490      *
16491      * @see #getRotation()
16492      * @see #getScaleX()
16493      * @see #getScaleY()
16494      * @see #getPivotY()
16495      * @return The x location of the pivot point.
16496      *
16497      * @attr ref android.R.styleable#View_transformPivotX
16498      */
16499     @ViewDebug.ExportedProperty(category = "drawing")
16500     @InspectableProperty(name = "transformPivotX")
getPivotX()16501     public float getPivotX() {
16502         return mRenderNode.getPivotX();
16503     }
16504 
16505     /**
16506      * Sets the x location of the point around which the view is
16507      * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
16508      * By default, the pivot point is centered on the object.
16509      * Setting this property disables this behavior and causes the view to use only the
16510      * explicitly set pivotX and pivotY values.
16511      *
16512      * @param pivotX The x location of the pivot point.
16513      * @see #getRotation()
16514      * @see #getScaleX()
16515      * @see #getScaleY()
16516      * @see #getPivotY()
16517      *
16518      * @attr ref android.R.styleable#View_transformPivotX
16519      */
setPivotX(float pivotX)16520     public void setPivotX(float pivotX) {
16521         if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
16522             invalidateViewProperty(true, false);
16523             mRenderNode.setPivotX(pivotX);
16524             invalidateViewProperty(false, true);
16525 
16526             invalidateParentIfNeededAndWasQuickRejected();
16527         }
16528     }
16529 
16530     /**
16531      * The y location of the point around which the view is {@link #setRotation(float) rotated}
16532      * and {@link #setScaleY(float) scaled}.
16533      *
16534      * @see #getRotation()
16535      * @see #getScaleX()
16536      * @see #getScaleY()
16537      * @see #getPivotY()
16538      * @return The y location of the pivot point.
16539      *
16540      * @attr ref android.R.styleable#View_transformPivotY
16541      */
16542     @ViewDebug.ExportedProperty(category = "drawing")
16543     @InspectableProperty(name = "transformPivotY")
getPivotY()16544     public float getPivotY() {
16545         return mRenderNode.getPivotY();
16546     }
16547 
16548     /**
16549      * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
16550      * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
16551      * Setting this property disables this behavior and causes the view to use only the
16552      * explicitly set pivotX and pivotY values.
16553      *
16554      * @param pivotY The y location of the pivot point.
16555      * @see #getRotation()
16556      * @see #getScaleX()
16557      * @see #getScaleY()
16558      * @see #getPivotY()
16559      *
16560      * @attr ref android.R.styleable#View_transformPivotY
16561      */
setPivotY(float pivotY)16562     public void setPivotY(float pivotY) {
16563         if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
16564             invalidateViewProperty(true, false);
16565             mRenderNode.setPivotY(pivotY);
16566             invalidateViewProperty(false, true);
16567 
16568             invalidateParentIfNeededAndWasQuickRejected();
16569         }
16570     }
16571 
16572     /**
16573      * Returns whether or not a pivot has been set by a call to {@link #setPivotX(float)} or
16574      * {@link #setPivotY(float)}. If no pivot has been set then the pivot will be the center
16575      * of the view.
16576      *
16577      * @return True if a pivot has been set, false if the default pivot is being used
16578      */
isPivotSet()16579     public boolean isPivotSet() {
16580         return mRenderNode.isPivotExplicitlySet();
16581     }
16582 
16583     /**
16584      * Clears any pivot previously set by a call to  {@link #setPivotX(float)} or
16585      * {@link #setPivotY(float)}. After calling this {@link #isPivotSet()} will be false
16586      * and the pivot used for rotation will return to default of being centered on the view.
16587      */
resetPivot()16588     public void resetPivot() {
16589         if (mRenderNode.resetPivot()) {
16590             invalidateViewProperty(false, false);
16591         }
16592     }
16593 
16594     /**
16595      * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
16596      * completely transparent and 1 means the view is completely opaque.
16597      *
16598      * <p>By default this is 1.0f.
16599      * @return The opacity of the view.
16600      */
16601     @ViewDebug.ExportedProperty(category = "drawing")
16602     @InspectableProperty
getAlpha()16603     public float getAlpha() {
16604         return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
16605     }
16606 
16607     /**
16608      * Sets the behavior for overlapping rendering for this view (see {@link
16609      * #hasOverlappingRendering()} for more details on this behavior). Calling this method
16610      * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
16611      * providing the value which is then used internally. That is, when {@link
16612      * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
16613      * #hasOverlappingRendering()} is ignored and the value passed into this method is used
16614      * instead.
16615      *
16616      * @param hasOverlappingRendering The value for overlapping rendering to be used internally
16617      * instead of that returned by {@link #hasOverlappingRendering()}.
16618      *
16619      * @attr ref android.R.styleable#View_forceHasOverlappingRendering
16620      */
forceHasOverlappingRendering(boolean hasOverlappingRendering)16621     public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
16622         mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
16623         if (hasOverlappingRendering) {
16624             mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
16625         } else {
16626             mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
16627         }
16628     }
16629 
16630     /**
16631      * Returns the value for overlapping rendering that is used internally. This is either
16632      * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
16633      * the return value of {@link #hasOverlappingRendering()}, otherwise.
16634      *
16635      * @return The value for overlapping rendering being used internally.
16636      */
getHasOverlappingRendering()16637     public final boolean getHasOverlappingRendering() {
16638         return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
16639                 (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
16640                 hasOverlappingRendering();
16641     }
16642 
16643     /**
16644      * Returns whether this View has content which overlaps.
16645      *
16646      * <p>This function, intended to be overridden by specific View types, is an optimization when
16647      * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
16648      * an offscreen buffer and then composited into place, which can be expensive. If the view has
16649      * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
16650      * directly. An example of overlapping rendering is a TextView with a background image, such as
16651      * a Button. An example of non-overlapping rendering is a TextView with no background, or an
16652      * ImageView with only the foreground image. The default implementation returns true; subclasses
16653      * should override if they have cases which can be optimized.</p>
16654      *
16655      * <p><strong>Note:</strong> The return value of this method is ignored if {@link
16656      * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
16657      *
16658      * @return true if the content in this view might overlap, false otherwise.
16659      */
16660     @ViewDebug.ExportedProperty(category = "drawing")
hasOverlappingRendering()16661     public boolean hasOverlappingRendering() {
16662         return true;
16663     }
16664 
16665     /**
16666      * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
16667      * completely transparent and 1 means the view is completely opaque.
16668      *
16669      * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
16670      * can have significant performance implications, especially for large views. It is best to use
16671      * the alpha property sparingly and transiently, as in the case of fading animations.</p>
16672      *
16673      * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
16674      * strongly recommended for performance reasons to either override
16675      * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
16676      * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
16677      * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
16678      * the default path for rendering an unlayered View with alpha could add multiple milliseconds
16679      * of rendering cost, even for simple or small views. Starting with
16680      * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
16681      * applied to the view at the rendering level.</p>
16682      *
16683      * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
16684      * responsible for applying the opacity itself.</p>
16685      *
16686      * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
16687      * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
16688      * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
16689      * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
16690      *
16691      * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
16692      * value will clip a View to its bounds, unless the View returns <code>false</code> from
16693      * {@link #hasOverlappingRendering}.</p>
16694      *
16695      * @param alpha The opacity of the view.
16696      *
16697      * @see #hasOverlappingRendering()
16698      * @see #setLayerType(int, android.graphics.Paint)
16699      *
16700      * @attr ref android.R.styleable#View_alpha
16701      */
setAlpha(@loatRangefrom=0.0, to=1.0) float alpha)16702     public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
16703         ensureTransformationInfo();
16704         if (mTransformationInfo.mAlpha != alpha) {
16705             setAlphaInternal(alpha);
16706             if (onSetAlpha((int) (alpha * 255))) {
16707                 mPrivateFlags |= PFLAG_ALPHA_SET;
16708                 // subclass is handling alpha - don't optimize rendering cache invalidation
16709                 invalidateParentCaches();
16710                 invalidate(true);
16711             } else {
16712                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
16713                 invalidateViewProperty(true, false);
16714                 mRenderNode.setAlpha(getFinalAlpha());
16715             }
16716         }
16717     }
16718 
16719     /**
16720      * Faster version of setAlpha() which performs the same steps except there are
16721      * no calls to invalidate(). The caller of this function should perform proper invalidation
16722      * on the parent and this object. The return value indicates whether the subclass handles
16723      * alpha (the return value for onSetAlpha()).
16724      *
16725      * @param alpha The new value for the alpha property
16726      * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
16727      *         the new value for the alpha property is different from the old value
16728      */
16729     @UnsupportedAppUsage(maxTargetSdk  = Build.VERSION_CODES.P, trackingBug = 123768435)
setAlphaNoInvalidation(float alpha)16730     boolean setAlphaNoInvalidation(float alpha) {
16731         ensureTransformationInfo();
16732         if (mTransformationInfo.mAlpha != alpha) {
16733             setAlphaInternal(alpha);
16734             boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
16735             if (subclassHandlesAlpha) {
16736                 mPrivateFlags |= PFLAG_ALPHA_SET;
16737                 return true;
16738             } else {
16739                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
16740                 mRenderNode.setAlpha(getFinalAlpha());
16741             }
16742         }
16743         return false;
16744     }
16745 
setAlphaInternal(float alpha)16746     void setAlphaInternal(float alpha) {
16747         float oldAlpha = mTransformationInfo.mAlpha;
16748         mTransformationInfo.mAlpha = alpha;
16749         // Report visibility changes, which can affect children, to accessibility
16750         if ((alpha == 0) ^ (oldAlpha == 0)) {
16751             notifySubtreeAccessibilityStateChangedIfNeeded();
16752         }
16753     }
16754 
16755     /**
16756      * This property is intended only for use by the Fade transition, which animates it
16757      * to produce a visual translucency that does not side-effect (or get affected by)
16758      * the real alpha property. This value is composited with the other alpha value
16759      * (and the AlphaAnimation value, when that is present) to produce a final visual
16760      * translucency result, which is what is passed into the DisplayList.
16761      */
setTransitionAlpha(float alpha)16762     public void setTransitionAlpha(float alpha) {
16763         ensureTransformationInfo();
16764         if (mTransformationInfo.mTransitionAlpha != alpha) {
16765             mTransformationInfo.mTransitionAlpha = alpha;
16766             mPrivateFlags &= ~PFLAG_ALPHA_SET;
16767             invalidateViewProperty(true, false);
16768             mRenderNode.setAlpha(getFinalAlpha());
16769         }
16770     }
16771 
16772     /**
16773      * Calculates the visual alpha of this view, which is a combination of the actual
16774      * alpha value and the transitionAlpha value (if set).
16775      */
getFinalAlpha()16776     private float getFinalAlpha() {
16777         if (mTransformationInfo != null) {
16778             return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
16779         }
16780         return 1;
16781     }
16782 
16783     /**
16784      * This property is intended only for use by the Fade transition, which animates
16785      * it to produce a visual translucency that does not side-effect (or get affected
16786      * by) the real alpha property. This value is composited with the other alpha
16787      * value (and the AlphaAnimation value, when that is present) to produce a final
16788      * visual translucency result, which is what is passed into the DisplayList.
16789      */
16790     @ViewDebug.ExportedProperty(category = "drawing")
getTransitionAlpha()16791     public float getTransitionAlpha() {
16792         return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
16793     }
16794 
16795     /**
16796      * Sets whether or not to allow force dark to apply to this view.
16797      *
16798      * Setting this to false will disable the auto-dark feature on everything this view
16799      * draws, including any descendants.
16800      *
16801      * Setting this to true will allow this view to be automatically made dark, however
16802      * a value of 'true' will not override any 'false' value in its parent chain nor will
16803      * it prevent any 'false' in any of its children.
16804      *
16805      * The default behavior of force dark is also influenced by the Theme's
16806      * {@link android.R.styleable#Theme_isLightTheme isLightTheme} attribute.
16807      * If a theme is isLightTheme="false", then force dark is globally disabled for that theme.
16808      *
16809      * @param allow Whether or not to allow force dark.
16810      */
setForceDarkAllowed(boolean allow)16811     public void setForceDarkAllowed(boolean allow) {
16812         if (mRenderNode.setForceDarkAllowed(allow)) {
16813             // Currently toggling force-dark requires a new display list push to apply
16814             // TODO: Make it not clobber the display list so this is just a damageSelf() instead
16815             invalidate();
16816         }
16817     }
16818 
16819     /**
16820      * See {@link #setForceDarkAllowed(boolean)}
16821      *
16822      * @return true if force dark is allowed (default), false if it is disabled
16823      */
16824     @ViewDebug.ExportedProperty(category = "drawing")
16825     @InspectableProperty
isForceDarkAllowed()16826     public boolean isForceDarkAllowed() {
16827         return mRenderNode.isForceDarkAllowed();
16828     }
16829 
16830     /**
16831      * Top position of this view relative to its parent.
16832      *
16833      * @return The top of this view, in pixels.
16834      */
16835     @ViewDebug.CapturedViewProperty
getTop()16836     public final int getTop() {
16837         return mTop;
16838     }
16839 
16840     /**
16841      * Sets the top position of this view relative to its parent. This method is meant to be called
16842      * by the layout system and should not generally be called otherwise, because the property
16843      * may be changed at any time by the layout.
16844      *
16845      * @param top The top of this view, in pixels.
16846      */
setTop(int top)16847     public final void setTop(int top) {
16848         if (top != mTop) {
16849             final boolean matrixIsIdentity = hasIdentityMatrix();
16850             if (matrixIsIdentity) {
16851                 if (mAttachInfo != null) {
16852                     int minTop;
16853                     int yLoc;
16854                     if (top < mTop) {
16855                         minTop = top;
16856                         yLoc = top - mTop;
16857                     } else {
16858                         minTop = mTop;
16859                         yLoc = 0;
16860                     }
16861                     invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
16862                 }
16863             } else {
16864                 // Double-invalidation is necessary to capture view's old and new areas
16865                 invalidate(true);
16866             }
16867 
16868             int width = mRight - mLeft;
16869             int oldHeight = mBottom - mTop;
16870 
16871             mTop = top;
16872             mRenderNode.setTop(mTop);
16873 
16874             sizeChange(width, mBottom - mTop, width, oldHeight);
16875 
16876             if (!matrixIsIdentity) {
16877                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
16878                 invalidate(true);
16879             }
16880             mBackgroundSizeChanged = true;
16881             mDefaultFocusHighlightSizeChanged = true;
16882             if (mForegroundInfo != null) {
16883                 mForegroundInfo.mBoundsChanged = true;
16884             }
16885             invalidateParentIfNeeded();
16886             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
16887                 // View was rejected last time it was drawn by its parent; this may have changed
16888                 invalidateParentIfNeeded();
16889             }
16890         }
16891     }
16892 
16893     /**
16894      * Bottom position of this view relative to its parent.
16895      *
16896      * @return The bottom of this view, in pixels.
16897      */
16898     @ViewDebug.CapturedViewProperty
getBottom()16899     public final int getBottom() {
16900         return mBottom;
16901     }
16902 
16903     /**
16904      * True if this view has changed since the last time being drawn.
16905      *
16906      * @return The dirty state of this view.
16907      */
isDirty()16908     public boolean isDirty() {
16909         return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
16910     }
16911 
16912     /**
16913      * Sets the bottom position of this view relative to its parent. This method is meant to be
16914      * called by the layout system and should not generally be called otherwise, because the
16915      * property may be changed at any time by the layout.
16916      *
16917      * @param bottom The bottom of this view, in pixels.
16918      */
setBottom(int bottom)16919     public final void setBottom(int bottom) {
16920         if (bottom != mBottom) {
16921             final boolean matrixIsIdentity = hasIdentityMatrix();
16922             if (matrixIsIdentity) {
16923                 if (mAttachInfo != null) {
16924                     int maxBottom;
16925                     if (bottom < mBottom) {
16926                         maxBottom = mBottom;
16927                     } else {
16928                         maxBottom = bottom;
16929                     }
16930                     invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
16931                 }
16932             } else {
16933                 // Double-invalidation is necessary to capture view's old and new areas
16934                 invalidate(true);
16935             }
16936 
16937             int width = mRight - mLeft;
16938             int oldHeight = mBottom - mTop;
16939 
16940             mBottom = bottom;
16941             mRenderNode.setBottom(mBottom);
16942 
16943             sizeChange(width, mBottom - mTop, width, oldHeight);
16944 
16945             if (!matrixIsIdentity) {
16946                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
16947                 invalidate(true);
16948             }
16949             mBackgroundSizeChanged = true;
16950             mDefaultFocusHighlightSizeChanged = true;
16951             if (mForegroundInfo != null) {
16952                 mForegroundInfo.mBoundsChanged = true;
16953             }
16954             invalidateParentIfNeeded();
16955             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
16956                 // View was rejected last time it was drawn by its parent; this may have changed
16957                 invalidateParentIfNeeded();
16958             }
16959         }
16960     }
16961 
16962     /**
16963      * Left position of this view relative to its parent.
16964      *
16965      * @return The left edge of this view, in pixels.
16966      */
16967     @ViewDebug.CapturedViewProperty
getLeft()16968     public final int getLeft() {
16969         return mLeft;
16970     }
16971 
16972     /**
16973      * Sets the left position of this view relative to its parent. This method is meant to be called
16974      * by the layout system and should not generally be called otherwise, because the property
16975      * may be changed at any time by the layout.
16976      *
16977      * @param left The left of this view, in pixels.
16978      */
setLeft(int left)16979     public final void setLeft(int left) {
16980         if (left != mLeft) {
16981             final boolean matrixIsIdentity = hasIdentityMatrix();
16982             if (matrixIsIdentity) {
16983                 if (mAttachInfo != null) {
16984                     int minLeft;
16985                     int xLoc;
16986                     if (left < mLeft) {
16987                         minLeft = left;
16988                         xLoc = left - mLeft;
16989                     } else {
16990                         minLeft = mLeft;
16991                         xLoc = 0;
16992                     }
16993                     invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
16994                 }
16995             } else {
16996                 // Double-invalidation is necessary to capture view's old and new areas
16997                 invalidate(true);
16998             }
16999 
17000             int oldWidth = mRight - mLeft;
17001             int height = mBottom - mTop;
17002 
17003             mLeft = left;
17004             mRenderNode.setLeft(left);
17005 
17006             sizeChange(mRight - mLeft, height, oldWidth, height);
17007 
17008             if (!matrixIsIdentity) {
17009                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
17010                 invalidate(true);
17011             }
17012             mBackgroundSizeChanged = true;
17013             mDefaultFocusHighlightSizeChanged = true;
17014             if (mForegroundInfo != null) {
17015                 mForegroundInfo.mBoundsChanged = true;
17016             }
17017             invalidateParentIfNeeded();
17018             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
17019                 // View was rejected last time it was drawn by its parent; this may have changed
17020                 invalidateParentIfNeeded();
17021             }
17022         }
17023     }
17024 
17025     /**
17026      * Right position of this view relative to its parent.
17027      *
17028      * @return The right edge of this view, in pixels.
17029      */
17030     @ViewDebug.CapturedViewProperty
getRight()17031     public final int getRight() {
17032         return mRight;
17033     }
17034 
17035     /**
17036      * Sets the right position of this view relative to its parent. This method is meant to be called
17037      * by the layout system and should not generally be called otherwise, because the property
17038      * may be changed at any time by the layout.
17039      *
17040      * @param right The right of this view, in pixels.
17041      */
setRight(int right)17042     public final void setRight(int right) {
17043         if (right != mRight) {
17044             final boolean matrixIsIdentity = hasIdentityMatrix();
17045             if (matrixIsIdentity) {
17046                 if (mAttachInfo != null) {
17047                     int maxRight;
17048                     if (right < mRight) {
17049                         maxRight = mRight;
17050                     } else {
17051                         maxRight = right;
17052                     }
17053                     invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
17054                 }
17055             } else {
17056                 // Double-invalidation is necessary to capture view's old and new areas
17057                 invalidate(true);
17058             }
17059 
17060             int oldWidth = mRight - mLeft;
17061             int height = mBottom - mTop;
17062 
17063             mRight = right;
17064             mRenderNode.setRight(mRight);
17065 
17066             sizeChange(mRight - mLeft, height, oldWidth, height);
17067 
17068             if (!matrixIsIdentity) {
17069                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
17070                 invalidate(true);
17071             }
17072             mBackgroundSizeChanged = true;
17073             mDefaultFocusHighlightSizeChanged = true;
17074             if (mForegroundInfo != null) {
17075                 mForegroundInfo.mBoundsChanged = true;
17076             }
17077             invalidateParentIfNeeded();
17078             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
17079                 // View was rejected last time it was drawn by its parent; this may have changed
17080                 invalidateParentIfNeeded();
17081             }
17082         }
17083     }
17084 
sanitizeFloatPropertyValue(float value, String propertyName)17085     private static float sanitizeFloatPropertyValue(float value, String propertyName) {
17086         return sanitizeFloatPropertyValue(value, propertyName, -Float.MAX_VALUE, Float.MAX_VALUE);
17087     }
17088 
sanitizeFloatPropertyValue(float value, String propertyName, float min, float max)17089     private static float sanitizeFloatPropertyValue(float value, String propertyName,
17090             float min, float max) {
17091         // The expected "nothing bad happened" path
17092         if (value >= min && value <= max) return value;
17093 
17094         if (value < min || value == Float.NEGATIVE_INFINITY) {
17095             if (sThrowOnInvalidFloatProperties) {
17096                 throw new IllegalArgumentException("Cannot set '" + propertyName + "' to "
17097                         + value + ", the value must be >= " + min);
17098             }
17099             return min;
17100         }
17101 
17102         if (value > max || value == Float.POSITIVE_INFINITY) {
17103             if (sThrowOnInvalidFloatProperties) {
17104                 throw new IllegalArgumentException("Cannot set '" + propertyName + "' to "
17105                         + value + ", the value must be <= " + max);
17106             }
17107             return max;
17108         }
17109 
17110         if (Float.isNaN(value)) {
17111             if (sThrowOnInvalidFloatProperties) {
17112                 throw new IllegalArgumentException(
17113                         "Cannot set '" + propertyName + "' to Float.NaN");
17114             }
17115             return 0; // Unclear which direction this NaN went so... 0?
17116         }
17117 
17118         // Shouldn't be possible to reach this.
17119         throw new IllegalStateException("How do you get here?? " + value);
17120     }
17121 
17122     /**
17123      * The visual x position of this view, in pixels. This is equivalent to the
17124      * {@link #setTranslationX(float) translationX} property plus the current
17125      * {@link #getLeft() left} property.
17126      *
17127      * @return The visual x position of this view, in pixels.
17128      */
17129     @ViewDebug.ExportedProperty(category = "drawing")
getX()17130     public float getX() {
17131         return mLeft + getTranslationX();
17132     }
17133 
17134     /**
17135      * Sets the visual x position of this view, in pixels. This is equivalent to setting the
17136      * {@link #setTranslationX(float) translationX} property to be the difference between
17137      * the x value passed in and the current {@link #getLeft() left} property.
17138      *
17139      * @param x The visual x position of this view, in pixels.
17140      */
setX(float x)17141     public void setX(float x) {
17142         setTranslationX(x - mLeft);
17143     }
17144 
17145     /**
17146      * The visual y position of this view, in pixels. This is equivalent to the
17147      * {@link #setTranslationY(float) translationY} property plus the current
17148      * {@link #getTop() top} property.
17149      *
17150      * @return The visual y position of this view, in pixels.
17151      */
17152     @ViewDebug.ExportedProperty(category = "drawing")
getY()17153     public float getY() {
17154         return mTop + getTranslationY();
17155     }
17156 
17157     /**
17158      * Sets the visual y position of this view, in pixels. This is equivalent to setting the
17159      * {@link #setTranslationY(float) translationY} property to be the difference between
17160      * the y value passed in and the current {@link #getTop() top} property.
17161      *
17162      * @param y The visual y position of this view, in pixels.
17163      */
setY(float y)17164     public void setY(float y) {
17165         setTranslationY(y - mTop);
17166     }
17167 
17168     /**
17169      * The visual z position of this view, in pixels. This is equivalent to the
17170      * {@link #setTranslationZ(float) translationZ} property plus the current
17171      * {@link #getElevation() elevation} property.
17172      *
17173      * @return The visual z position of this view, in pixels.
17174      */
17175     @ViewDebug.ExportedProperty(category = "drawing")
getZ()17176     public float getZ() {
17177         return getElevation() + getTranslationZ();
17178     }
17179 
17180     /**
17181      * Sets the visual z position of this view, in pixels. This is equivalent to setting the
17182      * {@link #setTranslationZ(float) translationZ} property to be the difference between
17183      * the z value passed in and the current {@link #getElevation() elevation} property.
17184      *
17185      * @param z The visual z position of this view, in pixels.
17186      */
setZ(float z)17187     public void setZ(float z) {
17188         setTranslationZ(z - getElevation());
17189     }
17190 
17191     /**
17192      * The base elevation of this view relative to its parent, in pixels.
17193      *
17194      * @return The base depth position of the view, in pixels.
17195      */
17196     @ViewDebug.ExportedProperty(category = "drawing")
17197     @InspectableProperty
getElevation()17198     public float getElevation() {
17199         return mRenderNode.getElevation();
17200     }
17201 
17202     /**
17203      * Sets the base elevation of this view, in pixels.
17204      *
17205      * @attr ref android.R.styleable#View_elevation
17206      */
setElevation(float elevation)17207     public void setElevation(float elevation) {
17208         if (elevation != getElevation()) {
17209             elevation = sanitizeFloatPropertyValue(elevation, "elevation");
17210             invalidateViewProperty(true, false);
17211             mRenderNode.setElevation(elevation);
17212             invalidateViewProperty(false, true);
17213 
17214             invalidateParentIfNeededAndWasQuickRejected();
17215         }
17216     }
17217 
17218     /**
17219      * The horizontal location of this view relative to its {@link #getLeft() left} position.
17220      * This position is post-layout, in addition to wherever the object's
17221      * layout placed it.
17222      *
17223      * @return The horizontal position of this view relative to its left position, in pixels.
17224      */
17225     @ViewDebug.ExportedProperty(category = "drawing")
17226     @InspectableProperty
getTranslationX()17227     public float getTranslationX() {
17228         return mRenderNode.getTranslationX();
17229     }
17230 
17231     /**
17232      * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
17233      * This effectively positions the object post-layout, in addition to wherever the object's
17234      * layout placed it.
17235      *
17236      * @param translationX The horizontal position of this view relative to its left position,
17237      * in pixels.
17238      *
17239      * @attr ref android.R.styleable#View_translationX
17240      */
setTranslationX(float translationX)17241     public void setTranslationX(float translationX) {
17242         if (translationX != getTranslationX()) {
17243             invalidateViewProperty(true, false);
17244             mRenderNode.setTranslationX(translationX);
17245             invalidateViewProperty(false, true);
17246 
17247             invalidateParentIfNeededAndWasQuickRejected();
17248             notifySubtreeAccessibilityStateChangedIfNeeded();
17249         }
17250     }
17251 
17252     /**
17253      * The vertical location of this view relative to its {@link #getTop() top} position.
17254      * This position is post-layout, in addition to wherever the object's
17255      * layout placed it.
17256      *
17257      * @return The vertical position of this view relative to its top position,
17258      * in pixels.
17259      */
17260     @ViewDebug.ExportedProperty(category = "drawing")
17261     @InspectableProperty
getTranslationY()17262     public float getTranslationY() {
17263         return mRenderNode.getTranslationY();
17264     }
17265 
17266     /**
17267      * Sets the vertical location of this view relative to its {@link #getTop() top} position.
17268      * This effectively positions the object post-layout, in addition to wherever the object's
17269      * layout placed it.
17270      *
17271      * @param translationY The vertical position of this view relative to its top position,
17272      * in pixels.
17273      *
17274      * @attr ref android.R.styleable#View_translationY
17275      */
setTranslationY(float translationY)17276     public void setTranslationY(float translationY) {
17277         if (translationY != getTranslationY()) {
17278             invalidateViewProperty(true, false);
17279             mRenderNode.setTranslationY(translationY);
17280             invalidateViewProperty(false, true);
17281 
17282             invalidateParentIfNeededAndWasQuickRejected();
17283             notifySubtreeAccessibilityStateChangedIfNeeded();
17284         }
17285     }
17286 
17287     /**
17288      * The depth location of this view relative to its {@link #getElevation() elevation}.
17289      *
17290      * @return The depth of this view relative to its elevation.
17291      */
17292     @ViewDebug.ExportedProperty(category = "drawing")
17293     @InspectableProperty
getTranslationZ()17294     public float getTranslationZ() {
17295         return mRenderNode.getTranslationZ();
17296     }
17297 
17298     /**
17299      * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
17300      *
17301      * @attr ref android.R.styleable#View_translationZ
17302      */
setTranslationZ(float translationZ)17303     public void setTranslationZ(float translationZ) {
17304         if (translationZ != getTranslationZ()) {
17305             translationZ = sanitizeFloatPropertyValue(translationZ, "translationZ");
17306             invalidateViewProperty(true, false);
17307             mRenderNode.setTranslationZ(translationZ);
17308             invalidateViewProperty(false, true);
17309 
17310             invalidateParentIfNeededAndWasQuickRejected();
17311         }
17312     }
17313 
17314     /**
17315      * Changes the transformation matrix on the view. This is used in animation frameworks,
17316      * such as {@link android.transition.Transition}. When the animation finishes, the matrix
17317      * should be cleared by calling this method with <code>null</code> as the matrix parameter.
17318      * Application developers should use transformation methods like {@link #setRotation(float)},
17319      * {@link #setScaleX(float)}, {@link #setScaleX(float)}, {@link #setTranslationX(float)}}
17320      * and {@link #setTranslationY(float)} (float)}} instead.
17321      *
17322      * @param matrix The matrix, null indicates that the matrix should be cleared.
17323      * @see #getAnimationMatrix()
17324      */
setAnimationMatrix(@ullable Matrix matrix)17325     public void setAnimationMatrix(@Nullable Matrix matrix) {
17326         invalidateViewProperty(true, false);
17327         mRenderNode.setAnimationMatrix(matrix);
17328         invalidateViewProperty(false, true);
17329 
17330         invalidateParentIfNeededAndWasQuickRejected();
17331     }
17332 
17333     /**
17334      * Return the current transformation matrix of the view. This is used in animation frameworks,
17335      * such as {@link android.transition.Transition}. Returns <code>null</code> when there is no
17336      * transformation provided by {@link #setAnimationMatrix(Matrix)}.
17337      * Application developers should use transformation methods like {@link #setRotation(float)},
17338      * {@link #setScaleX(float)}, {@link #setScaleX(float)}, {@link #setTranslationX(float)}}
17339      * and {@link #setTranslationY(float)} (float)}} instead.
17340      *
17341      * @return the Matrix, null indicates there is no transformation
17342      * @see #setAnimationMatrix(Matrix)
17343      */
17344     @Nullable
getAnimationMatrix()17345     public Matrix getAnimationMatrix() {
17346         return mRenderNode.getAnimationMatrix();
17347     }
17348 
17349     /**
17350      * Returns the current StateListAnimator if exists.
17351      *
17352      * @return StateListAnimator or null if it does not exists
17353      * @see    #setStateListAnimator(android.animation.StateListAnimator)
17354      */
17355     @InspectableProperty
getStateListAnimator()17356     public StateListAnimator getStateListAnimator() {
17357         return mStateListAnimator;
17358     }
17359 
17360     /**
17361      * Attaches the provided StateListAnimator to this View.
17362      * <p>
17363      * Any previously attached StateListAnimator will be detached.
17364      *
17365      * @param stateListAnimator The StateListAnimator to update the view
17366      * @see android.animation.StateListAnimator
17367      */
setStateListAnimator(StateListAnimator stateListAnimator)17368     public void setStateListAnimator(StateListAnimator stateListAnimator) {
17369         if (mStateListAnimator == stateListAnimator) {
17370             return;
17371         }
17372         if (mStateListAnimator != null) {
17373             mStateListAnimator.setTarget(null);
17374         }
17375         mStateListAnimator = stateListAnimator;
17376         if (stateListAnimator != null) {
17377             stateListAnimator.setTarget(this);
17378             if (isAttachedToWindow()) {
17379                 stateListAnimator.setState(getDrawableState());
17380             }
17381         }
17382     }
17383 
17384     /**
17385      * Returns whether the Outline should be used to clip the contents of the View.
17386      * <p>
17387      * Note that this flag will only be respected if the View's Outline returns true from
17388      * {@link Outline#canClip()}.
17389      *
17390      * @see #setOutlineProvider(ViewOutlineProvider)
17391      * @see #setClipToOutline(boolean)
17392      */
getClipToOutline()17393     public final boolean getClipToOutline() {
17394         return mRenderNode.getClipToOutline();
17395     }
17396 
17397     /**
17398      * Sets whether the View's Outline should be used to clip the contents of the View.
17399      * <p>
17400      * Only a single non-rectangular clip can be applied on a View at any time.
17401      * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
17402      * circular reveal} animation take priority over Outline clipping, and
17403      * child Outline clipping takes priority over Outline clipping done by a
17404      * parent.
17405      * <p>
17406      * Note that this flag will only be respected if the View's Outline returns true from
17407      * {@link Outline#canClip()}.
17408      *
17409      * @see #setOutlineProvider(ViewOutlineProvider)
17410      * @see #getClipToOutline()
17411      */
setClipToOutline(boolean clipToOutline)17412     public void setClipToOutline(boolean clipToOutline) {
17413         damageInParent();
17414         if (getClipToOutline() != clipToOutline) {
17415             mRenderNode.setClipToOutline(clipToOutline);
17416         }
17417     }
17418 
17419     // correspond to the enum values of View_outlineProvider
17420     private static final int PROVIDER_BACKGROUND = 0;
17421     private static final int PROVIDER_NONE = 1;
17422     private static final int PROVIDER_BOUNDS = 2;
17423     private static final int PROVIDER_PADDED_BOUNDS = 3;
setOutlineProviderFromAttribute(int providerInt)17424     private void setOutlineProviderFromAttribute(int providerInt) {
17425         switch (providerInt) {
17426             case PROVIDER_BACKGROUND:
17427                 setOutlineProvider(ViewOutlineProvider.BACKGROUND);
17428                 break;
17429             case PROVIDER_NONE:
17430                 setOutlineProvider(null);
17431                 break;
17432             case PROVIDER_BOUNDS:
17433                 setOutlineProvider(ViewOutlineProvider.BOUNDS);
17434                 break;
17435             case PROVIDER_PADDED_BOUNDS:
17436                 setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
17437                 break;
17438         }
17439     }
17440 
17441     /**
17442      * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
17443      * the shape of the shadow it casts, and enables outline clipping.
17444      * <p>
17445      * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
17446      * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
17447      * outline provider with this method allows this behavior to be overridden.
17448      * <p>
17449      * If the ViewOutlineProvider is null, if querying it for an outline returns false,
17450      * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
17451      * <p>
17452      * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
17453      *
17454      * @see #setClipToOutline(boolean)
17455      * @see #getClipToOutline()
17456      * @see #getOutlineProvider()
17457      */
setOutlineProvider(ViewOutlineProvider provider)17458     public void setOutlineProvider(ViewOutlineProvider provider) {
17459         mOutlineProvider = provider;
17460         invalidateOutline();
17461     }
17462 
17463     /**
17464      * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
17465      * that defines the shape of the shadow it casts, and enables outline clipping.
17466      *
17467      * @see #setOutlineProvider(ViewOutlineProvider)
17468      */
17469     @InspectableProperty
getOutlineProvider()17470     public ViewOutlineProvider getOutlineProvider() {
17471         return mOutlineProvider;
17472     }
17473 
17474     /**
17475      * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
17476      *
17477      * @see #setOutlineProvider(ViewOutlineProvider)
17478      */
invalidateOutline()17479     public void invalidateOutline() {
17480         rebuildOutline();
17481 
17482         notifySubtreeAccessibilityStateChangedIfNeeded();
17483         invalidateViewProperty(false, false);
17484     }
17485 
17486     /**
17487      * Internal version of {@link #invalidateOutline()} which invalidates the
17488      * outline without invalidating the view itself. This is intended to be called from
17489      * within methods in the View class itself which are the result of the view being
17490      * invalidated already. For example, when we are drawing the background of a View,
17491      * we invalidate the outline in case it changed in the meantime, but we do not
17492      * need to invalidate the view because we're already drawing the background as part
17493      * of drawing the view in response to an earlier invalidation of the view.
17494      */
rebuildOutline()17495     private void rebuildOutline() {
17496         // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
17497         if (mAttachInfo == null) return;
17498 
17499         if (mOutlineProvider == null) {
17500             // no provider, remove outline
17501             mRenderNode.setOutline(null);
17502         } else {
17503             final Outline outline = mAttachInfo.mTmpOutline;
17504             outline.setEmpty();
17505             outline.setAlpha(1.0f);
17506 
17507             mOutlineProvider.getOutline(this, outline);
17508             mRenderNode.setOutline(outline);
17509         }
17510     }
17511 
17512     /**
17513      * HierarchyViewer only
17514      *
17515      * @hide
17516      */
17517     @ViewDebug.ExportedProperty(category = "drawing")
hasShadow()17518     public boolean hasShadow() {
17519         return mRenderNode.hasShadow();
17520     }
17521 
17522     /**
17523      * Sets the color of the spot shadow that is drawn when the view has a positive Z or
17524      * elevation value.
17525      * <p>
17526      * By default the shadow color is black. Generally, this color will be opaque so the intensity
17527      * of the shadow is consistent between different views with different colors.
17528      * <p>
17529      * The opacity of the final spot shadow is a function of the shadow caster height, the
17530      * alpha channel of the outlineSpotShadowColor (typically opaque), and the
17531      * {@link android.R.attr#spotShadowAlpha} theme attribute.
17532      *
17533      * @attr ref android.R.styleable#View_outlineSpotShadowColor
17534      * @param color The color this View will cast for its elevation spot shadow.
17535      */
setOutlineSpotShadowColor(@olorInt int color)17536     public void setOutlineSpotShadowColor(@ColorInt int color) {
17537         if (mRenderNode.setSpotShadowColor(color)) {
17538             invalidateViewProperty(true, true);
17539         }
17540     }
17541 
17542     /**
17543      * @return The shadow color set by {@link #setOutlineSpotShadowColor(int)}, or black if nothing
17544      * was set
17545      */
17546     @InspectableProperty
getOutlineSpotShadowColor()17547     public @ColorInt int getOutlineSpotShadowColor() {
17548         return mRenderNode.getSpotShadowColor();
17549     }
17550 
17551     /**
17552      * Sets the color of the ambient shadow that is drawn when the view has a positive Z or
17553      * elevation value.
17554      * <p>
17555      * By default the shadow color is black. Generally, this color will be opaque so the intensity
17556      * of the shadow is consistent between different views with different colors.
17557      * <p>
17558      * The opacity of the final ambient shadow is a function of the shadow caster height, the
17559      * alpha channel of the outlineAmbientShadowColor (typically opaque), and the
17560      * {@link android.R.attr#ambientShadowAlpha} theme attribute.
17561      *
17562      * @attr ref android.R.styleable#View_outlineAmbientShadowColor
17563      * @param color The color this View will cast for its elevation shadow.
17564      */
setOutlineAmbientShadowColor(@olorInt int color)17565     public void setOutlineAmbientShadowColor(@ColorInt int color) {
17566         if (mRenderNode.setAmbientShadowColor(color)) {
17567             invalidateViewProperty(true, true);
17568         }
17569     }
17570 
17571     /**
17572      * @return The shadow color set by {@link #setOutlineAmbientShadowColor(int)}, or black if
17573      * nothing was set
17574      */
17575     @InspectableProperty
getOutlineAmbientShadowColor()17576     public @ColorInt int getOutlineAmbientShadowColor() {
17577         return mRenderNode.getAmbientShadowColor();
17578     }
17579 
17580 
17581     /** @hide */
setRevealClip(boolean shouldClip, float x, float y, float radius)17582     public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
17583         mRenderNode.setRevealClip(shouldClip, x, y, radius);
17584         invalidateViewProperty(false, false);
17585     }
17586 
17587     /**
17588      * Hit rectangle in parent's coordinates
17589      *
17590      * @param outRect The hit rectangle of the view.
17591      */
getHitRect(Rect outRect)17592     public void getHitRect(Rect outRect) {
17593         if (hasIdentityMatrix() || mAttachInfo == null) {
17594             outRect.set(mLeft, mTop, mRight, mBottom);
17595         } else {
17596             final RectF tmpRect = mAttachInfo.mTmpTransformRect;
17597             tmpRect.set(0, 0, getWidth(), getHeight());
17598             getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
17599             outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
17600                     (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
17601         }
17602     }
17603 
17604     /**
17605      * Determines whether the given point, in local coordinates is inside the view.
17606      */
pointInView(float localX, float localY)17607     /*package*/ final boolean pointInView(float localX, float localY) {
17608         return pointInView(localX, localY, 0);
17609     }
17610 
17611     /**
17612      * Utility method to determine whether the given point, in local coordinates,
17613      * is inside the view, where the area of the view is expanded by the slop factor.
17614      * This method is called while processing touch-move events to determine if the event
17615      * is still within the view.
17616      *
17617      * @hide
17618      */
17619     @UnsupportedAppUsage
pointInView(float localX, float localY, float slop)17620     public boolean pointInView(float localX, float localY, float slop) {
17621         return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
17622                 localY < ((mBottom - mTop) + slop);
17623     }
17624 
17625     /**
17626      * When a view has focus and the user navigates away from it, the next view is searched for
17627      * starting from the rectangle filled in by this method.
17628      *
17629      * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
17630      * of the view.  However, if your view maintains some idea of internal selection,
17631      * such as a cursor, or a selected row or column, you should override this method and
17632      * fill in a more specific rectangle.
17633      *
17634      * @param r The rectangle to fill in, in this view's coordinates.
17635      */
getFocusedRect(Rect r)17636     public void getFocusedRect(Rect r) {
17637         getDrawingRect(r);
17638     }
17639 
17640     /**
17641      * If some part of this view is not clipped by any of its parents, then
17642      * return that area in r in global (root) coordinates. To convert r to local
17643      * coordinates (without taking possible View rotations into account), offset
17644      * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
17645      * If the view is completely clipped or translated out, return false.
17646      *
17647      * @param r If true is returned, r holds the global coordinates of the
17648      *        visible portion of this view.
17649      * @param globalOffset If true is returned, globalOffset holds the dx,dy
17650      *        between this view and its root. globalOffet may be null.
17651      * @return true if r is non-empty (i.e. part of the view is visible at the
17652      *         root level.
17653      */
getGlobalVisibleRect(Rect r, Point globalOffset)17654     public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
17655         int width = mRight - mLeft;
17656         int height = mBottom - mTop;
17657         if (width > 0 && height > 0) {
17658             r.set(0, 0, width, height);
17659             if (globalOffset != null) {
17660                 globalOffset.set(-mScrollX, -mScrollY);
17661             }
17662             return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
17663         }
17664         return false;
17665     }
17666 
getGlobalVisibleRect(Rect r)17667     public final boolean getGlobalVisibleRect(Rect r) {
17668         return getGlobalVisibleRect(r, null);
17669     }
17670 
getLocalVisibleRect(Rect r)17671     public final boolean getLocalVisibleRect(Rect r) {
17672         final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
17673         if (getGlobalVisibleRect(r, offset)) {
17674             r.offset(-offset.x, -offset.y); // make r local
17675             return true;
17676         }
17677         return false;
17678     }
17679 
17680     /**
17681      * Offset this view's vertical location by the specified number of pixels.
17682      *
17683      * @param offset the number of pixels to offset the view by
17684      */
offsetTopAndBottom(int offset)17685     public void offsetTopAndBottom(int offset) {
17686         if (offset != 0) {
17687             final boolean matrixIsIdentity = hasIdentityMatrix();
17688             if (matrixIsIdentity) {
17689                 if (isHardwareAccelerated()) {
17690                     invalidateViewProperty(false, false);
17691                 } else {
17692                     final ViewParent p = mParent;
17693                     if (p != null && mAttachInfo != null) {
17694                         final Rect r = mAttachInfo.mTmpInvalRect;
17695                         int minTop;
17696                         int maxBottom;
17697                         int yLoc;
17698                         if (offset < 0) {
17699                             minTop = mTop + offset;
17700                             maxBottom = mBottom;
17701                             yLoc = offset;
17702                         } else {
17703                             minTop = mTop;
17704                             maxBottom = mBottom + offset;
17705                             yLoc = 0;
17706                         }
17707                         r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
17708                         p.invalidateChild(this, r);
17709                     }
17710                 }
17711             } else {
17712                 invalidateViewProperty(false, false);
17713             }
17714 
17715             mTop += offset;
17716             mBottom += offset;
17717             mRenderNode.offsetTopAndBottom(offset);
17718             if (isHardwareAccelerated()) {
17719                 invalidateViewProperty(false, false);
17720                 invalidateParentIfNeededAndWasQuickRejected();
17721             } else {
17722                 if (!matrixIsIdentity) {
17723                     invalidateViewProperty(false, true);
17724                 }
17725                 invalidateParentIfNeeded();
17726             }
17727             notifySubtreeAccessibilityStateChangedIfNeeded();
17728         }
17729     }
17730 
17731     /**
17732      * Offset this view's horizontal location by the specified amount of pixels.
17733      *
17734      * @param offset the number of pixels to offset the view by
17735      */
offsetLeftAndRight(int offset)17736     public void offsetLeftAndRight(int offset) {
17737         if (offset != 0) {
17738             final boolean matrixIsIdentity = hasIdentityMatrix();
17739             if (matrixIsIdentity) {
17740                 if (isHardwareAccelerated()) {
17741                     invalidateViewProperty(false, false);
17742                 } else {
17743                     final ViewParent p = mParent;
17744                     if (p != null && mAttachInfo != null) {
17745                         final Rect r = mAttachInfo.mTmpInvalRect;
17746                         int minLeft;
17747                         int maxRight;
17748                         if (offset < 0) {
17749                             minLeft = mLeft + offset;
17750                             maxRight = mRight;
17751                         } else {
17752                             minLeft = mLeft;
17753                             maxRight = mRight + offset;
17754                         }
17755                         r.set(0, 0, maxRight - minLeft, mBottom - mTop);
17756                         p.invalidateChild(this, r);
17757                     }
17758                 }
17759             } else {
17760                 invalidateViewProperty(false, false);
17761             }
17762 
17763             mLeft += offset;
17764             mRight += offset;
17765             mRenderNode.offsetLeftAndRight(offset);
17766             if (isHardwareAccelerated()) {
17767                 invalidateViewProperty(false, false);
17768                 invalidateParentIfNeededAndWasQuickRejected();
17769             } else {
17770                 if (!matrixIsIdentity) {
17771                     invalidateViewProperty(false, true);
17772                 }
17773                 invalidateParentIfNeeded();
17774             }
17775             notifySubtreeAccessibilityStateChangedIfNeeded();
17776         }
17777     }
17778 
17779     /**
17780      * Get the LayoutParams associated with this view. All views should have
17781      * layout parameters. These supply parameters to the <i>parent</i> of this
17782      * view specifying how it should be arranged. There are many subclasses of
17783      * ViewGroup.LayoutParams, and these correspond to the different subclasses
17784      * of ViewGroup that are responsible for arranging their children.
17785      *
17786      * This method may return null if this View is not attached to a parent
17787      * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
17788      * was not invoked successfully. When a View is attached to a parent
17789      * ViewGroup, this method must not return null.
17790      *
17791      * @return The LayoutParams associated with this view, or null if no
17792      *         parameters have been set yet
17793      */
17794     @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
getLayoutParams()17795     public ViewGroup.LayoutParams getLayoutParams() {
17796         return mLayoutParams;
17797     }
17798 
17799     /**
17800      * Set the layout parameters associated with this view. These supply
17801      * parameters to the <i>parent</i> of this view specifying how it should be
17802      * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
17803      * correspond to the different subclasses of ViewGroup that are responsible
17804      * for arranging their children.
17805      *
17806      * @param params The layout parameters for this view, cannot be null
17807      */
setLayoutParams(ViewGroup.LayoutParams params)17808     public void setLayoutParams(ViewGroup.LayoutParams params) {
17809         if (params == null) {
17810             throw new NullPointerException("Layout parameters cannot be null");
17811         }
17812         mLayoutParams = params;
17813         resolveLayoutParams();
17814         if (mParent instanceof ViewGroup) {
17815             ((ViewGroup) mParent).onSetLayoutParams(this, params);
17816         }
17817         requestLayout();
17818     }
17819 
17820     /**
17821      * Resolve the layout parameters depending on the resolved layout direction
17822      *
17823      * @hide
17824      */
resolveLayoutParams()17825     public void resolveLayoutParams() {
17826         if (mLayoutParams != null) {
17827             mLayoutParams.resolveLayoutDirection(getLayoutDirection());
17828         }
17829     }
17830 
17831     /**
17832      * Set the scrolled position of your view. This will cause a call to
17833      * {@link #onScrollChanged(int, int, int, int)} and the view will be
17834      * invalidated.
17835      * @param x the x position to scroll to
17836      * @param y the y position to scroll to
17837      */
scrollTo(int x, int y)17838     public void scrollTo(int x, int y) {
17839         if (mScrollX != x || mScrollY != y) {
17840             int oldX = mScrollX;
17841             int oldY = mScrollY;
17842             mScrollX = x;
17843             mScrollY = y;
17844             invalidateParentCaches();
17845             onScrollChanged(mScrollX, mScrollY, oldX, oldY);
17846             if (!awakenScrollBars()) {
17847                 postInvalidateOnAnimation();
17848             }
17849         }
17850     }
17851 
17852     /**
17853      * Move the scrolled position of your view. This will cause a call to
17854      * {@link #onScrollChanged(int, int, int, int)} and the view will be
17855      * invalidated.
17856      * @param x the amount of pixels to scroll by horizontally
17857      * @param y the amount of pixels to scroll by vertically
17858      */
scrollBy(int x, int y)17859     public void scrollBy(int x, int y) {
17860         scrollTo(mScrollX + x, mScrollY + y);
17861     }
17862 
17863     /**
17864      * <p>Trigger the scrollbars to draw. When invoked this method starts an
17865      * animation to fade the scrollbars out after a default delay. If a subclass
17866      * provides animated scrolling, the start delay should equal the duration
17867      * of the scrolling animation.</p>
17868      *
17869      * <p>The animation starts only if at least one of the scrollbars is
17870      * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
17871      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
17872      * this method returns true, and false otherwise. If the animation is
17873      * started, this method calls {@link #invalidate()}; in that case the
17874      * caller should not call {@link #invalidate()}.</p>
17875      *
17876      * <p>This method should be invoked every time a subclass directly updates
17877      * the scroll parameters.</p>
17878      *
17879      * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
17880      * and {@link #scrollTo(int, int)}.</p>
17881      *
17882      * @return true if the animation is played, false otherwise
17883      *
17884      * @see #awakenScrollBars(int)
17885      * @see #scrollBy(int, int)
17886      * @see #scrollTo(int, int)
17887      * @see #isHorizontalScrollBarEnabled()
17888      * @see #isVerticalScrollBarEnabled()
17889      * @see #setHorizontalScrollBarEnabled(boolean)
17890      * @see #setVerticalScrollBarEnabled(boolean)
17891      */
awakenScrollBars()17892     protected boolean awakenScrollBars() {
17893         return mScrollCache != null &&
17894                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
17895     }
17896 
17897     /**
17898      * Trigger the scrollbars to draw.
17899      * This method differs from awakenScrollBars() only in its default duration.
17900      * initialAwakenScrollBars() will show the scroll bars for longer than
17901      * usual to give the user more of a chance to notice them.
17902      *
17903      * @return true if the animation is played, false otherwise.
17904      */
initialAwakenScrollBars()17905     private boolean initialAwakenScrollBars() {
17906         return mScrollCache != null &&
17907                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
17908     }
17909 
17910     /**
17911      * <p>
17912      * Trigger the scrollbars to draw. When invoked this method starts an
17913      * animation to fade the scrollbars out after a fixed delay. If a subclass
17914      * provides animated scrolling, the start delay should equal the duration of
17915      * the scrolling animation.
17916      * </p>
17917      *
17918      * <p>
17919      * The animation starts only if at least one of the scrollbars is enabled,
17920      * as specified by {@link #isHorizontalScrollBarEnabled()} and
17921      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
17922      * this method returns true, and false otherwise. If the animation is
17923      * started, this method calls {@link #invalidate()}; in that case the caller
17924      * should not call {@link #invalidate()}.
17925      * </p>
17926      *
17927      * <p>
17928      * This method should be invoked every time a subclass directly updates the
17929      * scroll parameters.
17930      * </p>
17931      *
17932      * @param startDelay the delay, in milliseconds, after which the animation
17933      *        should start; when the delay is 0, the animation starts
17934      *        immediately
17935      * @return true if the animation is played, false otherwise
17936      *
17937      * @see #scrollBy(int, int)
17938      * @see #scrollTo(int, int)
17939      * @see #isHorizontalScrollBarEnabled()
17940      * @see #isVerticalScrollBarEnabled()
17941      * @see #setHorizontalScrollBarEnabled(boolean)
17942      * @see #setVerticalScrollBarEnabled(boolean)
17943      */
awakenScrollBars(int startDelay)17944     protected boolean awakenScrollBars(int startDelay) {
17945         return awakenScrollBars(startDelay, true);
17946     }
17947 
17948     /**
17949      * <p>
17950      * Trigger the scrollbars to draw. When invoked this method starts an
17951      * animation to fade the scrollbars out after a fixed delay. If a subclass
17952      * provides animated scrolling, the start delay should equal the duration of
17953      * the scrolling animation.
17954      * </p>
17955      *
17956      * <p>
17957      * The animation starts only if at least one of the scrollbars is enabled,
17958      * as specified by {@link #isHorizontalScrollBarEnabled()} and
17959      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
17960      * this method returns true, and false otherwise. If the animation is
17961      * started, this method calls {@link #invalidate()} if the invalidate parameter
17962      * is set to true; in that case the caller
17963      * should not call {@link #invalidate()}.
17964      * </p>
17965      *
17966      * <p>
17967      * This method should be invoked every time a subclass directly updates the
17968      * scroll parameters.
17969      * </p>
17970      *
17971      * @param startDelay the delay, in milliseconds, after which the animation
17972      *        should start; when the delay is 0, the animation starts
17973      *        immediately
17974      *
17975      * @param invalidate Whether this method should call invalidate
17976      *
17977      * @return true if the animation is played, false otherwise
17978      *
17979      * @see #scrollBy(int, int)
17980      * @see #scrollTo(int, int)
17981      * @see #isHorizontalScrollBarEnabled()
17982      * @see #isVerticalScrollBarEnabled()
17983      * @see #setHorizontalScrollBarEnabled(boolean)
17984      * @see #setVerticalScrollBarEnabled(boolean)
17985      */
awakenScrollBars(int startDelay, boolean invalidate)17986     protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
17987         final ScrollabilityCache scrollCache = mScrollCache;
17988 
17989         if (scrollCache == null || !scrollCache.fadeScrollBars) {
17990             return false;
17991         }
17992 
17993         if (scrollCache.scrollBar == null) {
17994             scrollCache.scrollBar = new ScrollBarDrawable();
17995             scrollCache.scrollBar.setState(getDrawableState());
17996             scrollCache.scrollBar.setCallback(this);
17997         }
17998 
17999         if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
18000 
18001             if (invalidate) {
18002                 // Invalidate to show the scrollbars
18003                 postInvalidateOnAnimation();
18004             }
18005 
18006             if (scrollCache.state == ScrollabilityCache.OFF) {
18007                 // FIXME: this is copied from WindowManagerService.
18008                 // We should get this value from the system when it
18009                 // is possible to do so.
18010                 final int KEY_REPEAT_FIRST_DELAY = 750;
18011                 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
18012             }
18013 
18014             // Tell mScrollCache when we should start fading. This may
18015             // extend the fade start time if one was already scheduled
18016             long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
18017             scrollCache.fadeStartTime = fadeStartTime;
18018             scrollCache.state = ScrollabilityCache.ON;
18019 
18020             // Schedule our fader to run, unscheduling any old ones first
18021             if (mAttachInfo != null) {
18022                 mAttachInfo.mHandler.removeCallbacks(scrollCache);
18023                 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
18024             }
18025 
18026             return true;
18027         }
18028 
18029         return false;
18030     }
18031 
18032     /**
18033      * Do not invalidate views which are not visible and which are not running an animation. They
18034      * will not get drawn and they should not set dirty flags as if they will be drawn
18035      */
skipInvalidate()18036     private boolean skipInvalidate() {
18037         return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
18038                 (!(mParent instanceof ViewGroup) ||
18039                         !((ViewGroup) mParent).isViewTransitioning(this));
18040     }
18041 
18042     /**
18043      * Mark the area defined by dirty as needing to be drawn. If the view is
18044      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
18045      * point in the future.
18046      * <p>
18047      * This must be called from a UI thread. To call from a non-UI thread, call
18048      * {@link #postInvalidate()}.
18049      * <p>
18050      * <b>WARNING:</b> In API 19 and below, this method may be destructive to
18051      * {@code dirty}.
18052      *
18053      * @param dirty the rectangle representing the bounds of the dirty region
18054      *
18055      * @deprecated The switch to hardware accelerated rendering in API 14 reduced
18056      * the importance of the dirty rectangle. In API 21 the given rectangle is
18057      * ignored entirely in favor of an internally-calculated area instead.
18058      * Because of this, clients are encouraged to just call {@link #invalidate()}.
18059      */
18060     @Deprecated
invalidate(Rect dirty)18061     public void invalidate(Rect dirty) {
18062         final int scrollX = mScrollX;
18063         final int scrollY = mScrollY;
18064         invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
18065                 dirty.right - scrollX, dirty.bottom - scrollY, true, false);
18066     }
18067 
18068     /**
18069      * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
18070      * coordinates of the dirty rect are relative to the view. If the view is
18071      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
18072      * point in the future.
18073      * <p>
18074      * This must be called from a UI thread. To call from a non-UI thread, call
18075      * {@link #postInvalidate()}.
18076      *
18077      * @param l the left position of the dirty region
18078      * @param t the top position of the dirty region
18079      * @param r the right position of the dirty region
18080      * @param b the bottom position of the dirty region
18081      *
18082      * @deprecated The switch to hardware accelerated rendering in API 14 reduced
18083      * the importance of the dirty rectangle. In API 21 the given rectangle is
18084      * ignored entirely in favor of an internally-calculated area instead.
18085      * Because of this, clients are encouraged to just call {@link #invalidate()}.
18086      */
18087     @Deprecated
invalidate(int l, int t, int r, int b)18088     public void invalidate(int l, int t, int r, int b) {
18089         final int scrollX = mScrollX;
18090         final int scrollY = mScrollY;
18091         invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
18092     }
18093 
18094     /**
18095      * Invalidate the whole view. If the view is visible,
18096      * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
18097      * the future.
18098      * <p>
18099      * This must be called from a UI thread. To call from a non-UI thread, call
18100      * {@link #postInvalidate()}.
18101      */
invalidate()18102     public void invalidate() {
18103         invalidate(true);
18104     }
18105 
18106     /**
18107      * This is where the invalidate() work actually happens. A full invalidate()
18108      * causes the drawing cache to be invalidated, but this function can be
18109      * called with invalidateCache set to false to skip that invalidation step
18110      * for cases that do not need it (for example, a component that remains at
18111      * the same dimensions with the same content).
18112      *
18113      * @param invalidateCache Whether the drawing cache for this view should be
18114      *            invalidated as well. This is usually true for a full
18115      *            invalidate, but may be set to false if the View's contents or
18116      *            dimensions have not changed.
18117      * @hide
18118      */
18119     @UnsupportedAppUsage
invalidate(boolean invalidateCache)18120     public void invalidate(boolean invalidateCache) {
18121         invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
18122     }
18123 
invalidateInternal(int l, int t, int r, int b, boolean invalidateCache, boolean fullInvalidate)18124     void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
18125             boolean fullInvalidate) {
18126         if (mGhostView != null) {
18127             mGhostView.invalidate(true);
18128             return;
18129         }
18130 
18131         if (skipInvalidate()) {
18132             return;
18133         }
18134 
18135         // Reset content capture caches
18136         mPrivateFlags4 &= ~PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK;
18137         mCachedContentCaptureSession = null;
18138 
18139         if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
18140                 || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
18141                 || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
18142                 || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
18143             if (fullInvalidate) {
18144                 mLastIsOpaque = isOpaque();
18145                 mPrivateFlags &= ~PFLAG_DRAWN;
18146             }
18147 
18148             mPrivateFlags |= PFLAG_DIRTY;
18149 
18150             if (invalidateCache) {
18151                 mPrivateFlags |= PFLAG_INVALIDATED;
18152                 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
18153             }
18154 
18155             // Propagate the damage rectangle to the parent view.
18156             final AttachInfo ai = mAttachInfo;
18157             final ViewParent p = mParent;
18158             if (p != null && ai != null && l < r && t < b) {
18159                 final Rect damage = ai.mTmpInvalRect;
18160                 damage.set(l, t, r, b);
18161                 p.invalidateChild(this, damage);
18162             }
18163 
18164             // Damage the entire projection receiver, if necessary.
18165             if (mBackground != null && mBackground.isProjected()) {
18166                 final View receiver = getProjectionReceiver();
18167                 if (receiver != null) {
18168                     receiver.damageInParent();
18169                 }
18170             }
18171         }
18172     }
18173 
18174     /**
18175      * @return this view's projection receiver, or {@code null} if none exists
18176      */
getProjectionReceiver()18177     private View getProjectionReceiver() {
18178         ViewParent p = getParent();
18179         while (p != null && p instanceof View) {
18180             final View v = (View) p;
18181             if (v.isProjectionReceiver()) {
18182                 return v;
18183             }
18184             p = p.getParent();
18185         }
18186 
18187         return null;
18188     }
18189 
18190     /**
18191      * @return whether the view is a projection receiver
18192      */
isProjectionReceiver()18193     private boolean isProjectionReceiver() {
18194         return mBackground != null;
18195     }
18196 
18197     /**
18198      * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
18199      * set any flags or handle all of the cases handled by the default invalidation methods.
18200      * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
18201      * dirty rect. This method calls into fast invalidation methods in ViewGroup that
18202      * walk up the hierarchy, transforming the dirty rect as necessary.
18203      *
18204      * The method also handles normal invalidation logic if display list properties are not
18205      * being used in this view. The invalidateParent and forceRedraw flags are used by that
18206      * backup approach, to handle these cases used in the various property-setting methods.
18207      *
18208      * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
18209      * are not being used in this view
18210      * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
18211      * list properties are not being used in this view
18212      */
18213     @UnsupportedAppUsage
invalidateViewProperty(boolean invalidateParent, boolean forceRedraw)18214     void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
18215         if (!isHardwareAccelerated()
18216                 || !mRenderNode.hasDisplayList()
18217                 || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
18218             if (invalidateParent) {
18219                 invalidateParentCaches();
18220             }
18221             if (forceRedraw) {
18222                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
18223             }
18224             invalidate(false);
18225         } else {
18226             damageInParent();
18227         }
18228     }
18229 
18230     /**
18231      * Tells the parent view to damage this view's bounds.
18232      *
18233      * @hide
18234      */
damageInParent()18235     protected void damageInParent() {
18236         if (mParent != null && mAttachInfo != null) {
18237             mParent.onDescendantInvalidated(this, this);
18238         }
18239     }
18240 
18241     /**
18242      * Used to indicate that the parent of this view should clear its caches. This functionality
18243      * is used to force the parent to rebuild its display list (when hardware-accelerated),
18244      * which is necessary when various parent-managed properties of the view change, such as
18245      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
18246      * clears the parent caches and does not causes an invalidate event.
18247      *
18248      * @hide
18249      */
18250     @UnsupportedAppUsage
invalidateParentCaches()18251     protected void invalidateParentCaches() {
18252         if (mParent instanceof View) {
18253             ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
18254         }
18255     }
18256 
18257     /**
18258      * Used to indicate that the parent of this view should be invalidated. This functionality
18259      * is used to force the parent to rebuild its display list (when hardware-accelerated),
18260      * which is necessary when various parent-managed properties of the view change, such as
18261      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
18262      * an invalidation event to the parent.
18263      *
18264      * @hide
18265      */
18266     @UnsupportedAppUsage
invalidateParentIfNeeded()18267     protected void invalidateParentIfNeeded() {
18268         if (isHardwareAccelerated() && mParent instanceof View) {
18269             ((View) mParent).invalidate(true);
18270         }
18271     }
18272 
18273     /**
18274      * @hide
18275      */
invalidateParentIfNeededAndWasQuickRejected()18276     protected void invalidateParentIfNeededAndWasQuickRejected() {
18277         if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
18278             // View was rejected last time it was drawn by its parent; this may have changed
18279             invalidateParentIfNeeded();
18280         }
18281     }
18282 
18283     /**
18284      * Indicates whether this View is opaque. An opaque View guarantees that it will
18285      * draw all the pixels overlapping its bounds using a fully opaque color.
18286      *
18287      * Subclasses of View should override this method whenever possible to indicate
18288      * whether an instance is opaque. Opaque Views are treated in a special way by
18289      * the View hierarchy, possibly allowing it to perform optimizations during
18290      * invalidate/draw passes.
18291      *
18292      * @return True if this View is guaranteed to be fully opaque, false otherwise.
18293      */
18294     @ViewDebug.ExportedProperty(category = "drawing")
isOpaque()18295     public boolean isOpaque() {
18296         return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
18297                 getFinalAlpha() >= 1.0f;
18298     }
18299 
18300     /**
18301      * @hide
18302      */
18303     @UnsupportedAppUsage
computeOpaqueFlags()18304     protected void computeOpaqueFlags() {
18305         // Opaque if:
18306         //   - Has a background
18307         //   - Background is opaque
18308         //   - Doesn't have scrollbars or scrollbars overlay
18309 
18310         if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
18311             mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
18312         } else {
18313             mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
18314         }
18315 
18316         final int flags = mViewFlags;
18317         if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
18318                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
18319                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
18320             mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
18321         } else {
18322             mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
18323         }
18324     }
18325 
18326     /**
18327      * @hide
18328      */
hasOpaqueScrollbars()18329     protected boolean hasOpaqueScrollbars() {
18330         return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
18331     }
18332 
18333     /**
18334      * @return A handler associated with the thread running the View. This
18335      * handler can be used to pump events in the UI events queue.
18336      */
getHandler()18337     public Handler getHandler() {
18338         final AttachInfo attachInfo = mAttachInfo;
18339         if (attachInfo != null) {
18340             return attachInfo.mHandler;
18341         }
18342         return null;
18343     }
18344 
18345     /**
18346      * Returns the queue of runnable for this view.
18347      *
18348      * @return the queue of runnables for this view
18349      */
getRunQueue()18350     private HandlerActionQueue getRunQueue() {
18351         if (mRunQueue == null) {
18352             mRunQueue = new HandlerActionQueue();
18353         }
18354         return mRunQueue;
18355     }
18356 
18357     /**
18358      * Gets the view root associated with the View.
18359      * @return The view root, or null if none.
18360      * @hide
18361      */
18362     @UnsupportedAppUsage
getViewRootImpl()18363     public ViewRootImpl getViewRootImpl() {
18364         if (mAttachInfo != null) {
18365             return mAttachInfo.mViewRootImpl;
18366         }
18367         return null;
18368     }
18369 
18370     /**
18371      * @hide
18372      */
18373     @UnsupportedAppUsage
getThreadedRenderer()18374     public ThreadedRenderer getThreadedRenderer() {
18375         return mAttachInfo != null ? mAttachInfo.mThreadedRenderer : null;
18376     }
18377 
18378     /**
18379      * <p>Causes the Runnable to be added to the message queue.
18380      * The runnable will be run on the user interface thread.</p>
18381      *
18382      * @param action The Runnable that will be executed.
18383      *
18384      * @return Returns true if the Runnable was successfully placed in to the
18385      *         message queue.  Returns false on failure, usually because the
18386      *         looper processing the message queue is exiting.
18387      *
18388      * @see #postDelayed
18389      * @see #removeCallbacks
18390      */
post(Runnable action)18391     public boolean post(Runnable action) {
18392         final AttachInfo attachInfo = mAttachInfo;
18393         if (attachInfo != null) {
18394             return attachInfo.mHandler.post(action);
18395         }
18396 
18397         // Postpone the runnable until we know on which thread it needs to run.
18398         // Assume that the runnable will be successfully placed after attach.
18399         getRunQueue().post(action);
18400         return true;
18401     }
18402 
18403     /**
18404      * <p>Causes the Runnable to be added to the message queue, to be run
18405      * after the specified amount of time elapses.
18406      * The runnable will be run on the user interface thread.</p>
18407      *
18408      * @param action The Runnable that will be executed.
18409      * @param delayMillis The delay (in milliseconds) until the Runnable
18410      *        will be executed.
18411      *
18412      * @return true if the Runnable was successfully placed in to the
18413      *         message queue.  Returns false on failure, usually because the
18414      *         looper processing the message queue is exiting.  Note that a
18415      *         result of true does not mean the Runnable will be processed --
18416      *         if the looper is quit before the delivery time of the message
18417      *         occurs then the message will be dropped.
18418      *
18419      * @see #post
18420      * @see #removeCallbacks
18421      */
postDelayed(Runnable action, long delayMillis)18422     public boolean postDelayed(Runnable action, long delayMillis) {
18423         final AttachInfo attachInfo = mAttachInfo;
18424         if (attachInfo != null) {
18425             return attachInfo.mHandler.postDelayed(action, delayMillis);
18426         }
18427 
18428         // Postpone the runnable until we know on which thread it needs to run.
18429         // Assume that the runnable will be successfully placed after attach.
18430         getRunQueue().postDelayed(action, delayMillis);
18431         return true;
18432     }
18433 
18434     /**
18435      * <p>Causes the Runnable to execute on the next animation time step.
18436      * The runnable will be run on the user interface thread.</p>
18437      *
18438      * @param action The Runnable that will be executed.
18439      *
18440      * @see #postOnAnimationDelayed
18441      * @see #removeCallbacks
18442      */
postOnAnimation(Runnable action)18443     public void postOnAnimation(Runnable action) {
18444         final AttachInfo attachInfo = mAttachInfo;
18445         if (attachInfo != null) {
18446             attachInfo.mViewRootImpl.mChoreographer.postCallback(
18447                     Choreographer.CALLBACK_ANIMATION, action, null);
18448         } else {
18449             // Postpone the runnable until we know
18450             // on which thread it needs to run.
18451             getRunQueue().post(action);
18452         }
18453     }
18454 
18455     /**
18456      * <p>Causes the Runnable to execute on the next animation time step,
18457      * after the specified amount of time elapses.
18458      * The runnable will be run on the user interface thread.</p>
18459      *
18460      * @param action The Runnable that will be executed.
18461      * @param delayMillis The delay (in milliseconds) until the Runnable
18462      *        will be executed.
18463      *
18464      * @see #postOnAnimation
18465      * @see #removeCallbacks
18466      */
postOnAnimationDelayed(Runnable action, long delayMillis)18467     public void postOnAnimationDelayed(Runnable action, long delayMillis) {
18468         final AttachInfo attachInfo = mAttachInfo;
18469         if (attachInfo != null) {
18470             attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
18471                     Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
18472         } else {
18473             // Postpone the runnable until we know
18474             // on which thread it needs to run.
18475             getRunQueue().postDelayed(action, delayMillis);
18476         }
18477     }
18478 
18479     /**
18480      * <p>Removes the specified Runnable from the message queue.</p>
18481      *
18482      * @param action The Runnable to remove from the message handling queue
18483      *
18484      * @return true if this view could ask the Handler to remove the Runnable,
18485      *         false otherwise. When the returned value is true, the Runnable
18486      *         may or may not have been actually removed from the message queue
18487      *         (for instance, if the Runnable was not in the queue already.)
18488      *
18489      * @see #post
18490      * @see #postDelayed
18491      * @see #postOnAnimation
18492      * @see #postOnAnimationDelayed
18493      */
removeCallbacks(Runnable action)18494     public boolean removeCallbacks(Runnable action) {
18495         if (action != null) {
18496             final AttachInfo attachInfo = mAttachInfo;
18497             if (attachInfo != null) {
18498                 attachInfo.mHandler.removeCallbacks(action);
18499                 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
18500                         Choreographer.CALLBACK_ANIMATION, action, null);
18501             }
18502             getRunQueue().removeCallbacks(action);
18503         }
18504         return true;
18505     }
18506 
18507     /**
18508      * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
18509      * Use this to invalidate the View from a non-UI thread.</p>
18510      *
18511      * <p>This method can be invoked from outside of the UI thread
18512      * only when this View is attached to a window.</p>
18513      *
18514      * @see #invalidate()
18515      * @see #postInvalidateDelayed(long)
18516      */
postInvalidate()18517     public void postInvalidate() {
18518         postInvalidateDelayed(0);
18519     }
18520 
18521     /**
18522      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
18523      * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
18524      *
18525      * <p>This method can be invoked from outside of the UI thread
18526      * only when this View is attached to a window.</p>
18527      *
18528      * @param left The left coordinate of the rectangle to invalidate.
18529      * @param top The top coordinate of the rectangle to invalidate.
18530      * @param right The right coordinate of the rectangle to invalidate.
18531      * @param bottom The bottom coordinate of the rectangle to invalidate.
18532      *
18533      * @see #invalidate(int, int, int, int)
18534      * @see #invalidate(Rect)
18535      * @see #postInvalidateDelayed(long, int, int, int, int)
18536      */
postInvalidate(int left, int top, int right, int bottom)18537     public void postInvalidate(int left, int top, int right, int bottom) {
18538         postInvalidateDelayed(0, left, top, right, bottom);
18539     }
18540 
18541     /**
18542      * <p>Cause an invalidate to happen on a subsequent cycle through the event
18543      * loop. Waits for the specified amount of time.</p>
18544      *
18545      * <p>This method can be invoked from outside of the UI thread
18546      * only when this View is attached to a window.</p>
18547      *
18548      * @param delayMilliseconds the duration in milliseconds to delay the
18549      *         invalidation by
18550      *
18551      * @see #invalidate()
18552      * @see #postInvalidate()
18553      */
postInvalidateDelayed(long delayMilliseconds)18554     public void postInvalidateDelayed(long delayMilliseconds) {
18555         // We try only with the AttachInfo because there's no point in invalidating
18556         // if we are not attached to our window
18557         final AttachInfo attachInfo = mAttachInfo;
18558         if (attachInfo != null) {
18559             attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
18560         }
18561     }
18562 
18563     /**
18564      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
18565      * through the event loop. Waits for the specified amount of time.</p>
18566      *
18567      * <p>This method can be invoked from outside of the UI thread
18568      * only when this View is attached to a window.</p>
18569      *
18570      * @param delayMilliseconds the duration in milliseconds to delay the
18571      *         invalidation by
18572      * @param left The left coordinate of the rectangle to invalidate.
18573      * @param top The top coordinate of the rectangle to invalidate.
18574      * @param right The right coordinate of the rectangle to invalidate.
18575      * @param bottom The bottom coordinate of the rectangle to invalidate.
18576      *
18577      * @see #invalidate(int, int, int, int)
18578      * @see #invalidate(Rect)
18579      * @see #postInvalidate(int, int, int, int)
18580      */
postInvalidateDelayed(long delayMilliseconds, int left, int top, int right, int bottom)18581     public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
18582             int right, int bottom) {
18583 
18584         // We try only with the AttachInfo because there's no point in invalidating
18585         // if we are not attached to our window
18586         final AttachInfo attachInfo = mAttachInfo;
18587         if (attachInfo != null) {
18588             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
18589             info.target = this;
18590             info.left = left;
18591             info.top = top;
18592             info.right = right;
18593             info.bottom = bottom;
18594 
18595             attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
18596         }
18597     }
18598 
18599     /**
18600      * <p>Cause an invalidate to happen on the next animation time step, typically the
18601      * next display frame.</p>
18602      *
18603      * <p>This method can be invoked from outside of the UI thread
18604      * only when this View is attached to a window.</p>
18605      *
18606      * @see #invalidate()
18607      */
postInvalidateOnAnimation()18608     public void postInvalidateOnAnimation() {
18609         // We try only with the AttachInfo because there's no point in invalidating
18610         // if we are not attached to our window
18611         final AttachInfo attachInfo = mAttachInfo;
18612         if (attachInfo != null) {
18613             attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
18614         }
18615     }
18616 
18617     /**
18618      * <p>Cause an invalidate of the specified area to happen on the next animation
18619      * time step, typically the next display frame.</p>
18620      *
18621      * <p>This method can be invoked from outside of the UI thread
18622      * only when this View is attached to a window.</p>
18623      *
18624      * @param left The left coordinate of the rectangle to invalidate.
18625      * @param top The top coordinate of the rectangle to invalidate.
18626      * @param right The right coordinate of the rectangle to invalidate.
18627      * @param bottom The bottom coordinate of the rectangle to invalidate.
18628      *
18629      * @see #invalidate(int, int, int, int)
18630      * @see #invalidate(Rect)
18631      */
postInvalidateOnAnimation(int left, int top, int right, int bottom)18632     public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
18633         // We try only with the AttachInfo because there's no point in invalidating
18634         // if we are not attached to our window
18635         final AttachInfo attachInfo = mAttachInfo;
18636         if (attachInfo != null) {
18637             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
18638             info.target = this;
18639             info.left = left;
18640             info.top = top;
18641             info.right = right;
18642             info.bottom = bottom;
18643 
18644             attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
18645         }
18646     }
18647 
18648     /**
18649      * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
18650      * This event is sent at most once every
18651      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
18652      */
postSendViewScrolledAccessibilityEventCallback(int dx, int dy)18653     private void postSendViewScrolledAccessibilityEventCallback(int dx, int dy) {
18654         if (mSendViewScrolledAccessibilityEvent == null) {
18655             mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
18656         }
18657         mSendViewScrolledAccessibilityEvent.post(dx, dy);
18658     }
18659 
18660     /**
18661      * Called by a parent to request that a child update its values for mScrollX
18662      * and mScrollY if necessary. This will typically be done if the child is
18663      * animating a scroll using a {@link android.widget.Scroller Scroller}
18664      * object.
18665      */
computeScroll()18666     public void computeScroll() {
18667     }
18668 
18669     /**
18670      * <p>Indicate whether the horizontal edges are faded when the view is
18671      * scrolled horizontally.</p>
18672      *
18673      * @return true if the horizontal edges should are faded on scroll, false
18674      *         otherwise
18675      *
18676      * @see #setHorizontalFadingEdgeEnabled(boolean)
18677      *
18678      * @attr ref android.R.styleable#View_requiresFadingEdge
18679      */
isHorizontalFadingEdgeEnabled()18680     public boolean isHorizontalFadingEdgeEnabled() {
18681         return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
18682     }
18683 
18684     /**
18685      * <p>Define whether the horizontal edges should be faded when this view
18686      * is scrolled horizontally.</p>
18687      *
18688      * @param horizontalFadingEdgeEnabled true if the horizontal edges should
18689      *                                    be faded when the view is scrolled
18690      *                                    horizontally
18691      *
18692      * @see #isHorizontalFadingEdgeEnabled()
18693      *
18694      * @attr ref android.R.styleable#View_requiresFadingEdge
18695      */
setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled)18696     public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
18697         if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
18698             if (horizontalFadingEdgeEnabled) {
18699                 initScrollCache();
18700             }
18701 
18702             mViewFlags ^= FADING_EDGE_HORIZONTAL;
18703         }
18704     }
18705 
18706     /**
18707      * <p>Indicate whether the vertical edges are faded when the view is
18708      * scrolled horizontally.</p>
18709      *
18710      * @return true if the vertical edges should are faded on scroll, false
18711      *         otherwise
18712      *
18713      * @see #setVerticalFadingEdgeEnabled(boolean)
18714      *
18715      * @attr ref android.R.styleable#View_requiresFadingEdge
18716      */
isVerticalFadingEdgeEnabled()18717     public boolean isVerticalFadingEdgeEnabled() {
18718         return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
18719     }
18720 
18721     /**
18722      * <p>Define whether the vertical edges should be faded when this view
18723      * is scrolled vertically.</p>
18724      *
18725      * @param verticalFadingEdgeEnabled true if the vertical edges should
18726      *                                  be faded when the view is scrolled
18727      *                                  vertically
18728      *
18729      * @see #isVerticalFadingEdgeEnabled()
18730      *
18731      * @attr ref android.R.styleable#View_requiresFadingEdge
18732      */
setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled)18733     public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
18734         if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
18735             if (verticalFadingEdgeEnabled) {
18736                 initScrollCache();
18737             }
18738 
18739             mViewFlags ^= FADING_EDGE_VERTICAL;
18740         }
18741     }
18742 
18743     /**
18744      * Get the fading edge flags, used for inspection.
18745      *
18746      * @return One of {@link #FADING_EDGE_NONE}, {@link #FADING_EDGE_VERTICAL},
18747      *         or {@link #FADING_EDGE_HORIZONTAL}
18748      * @hide
18749      */
18750     @InspectableProperty(name = "requiresFadingEdge", flagMapping = {
18751             @FlagEntry(target = FADING_EDGE_NONE, mask = FADING_EDGE_MASK, name = "none"),
18752             @FlagEntry(target = FADING_EDGE_VERTICAL, name = "vertical"),
18753             @FlagEntry(target = FADING_EDGE_HORIZONTAL, name = "horizontal")
18754     })
getFadingEdge()18755     public int getFadingEdge() {
18756         return mViewFlags & FADING_EDGE_MASK;
18757     }
18758 
18759     /**
18760      * Get the fading edge length, used for inspection
18761      *
18762      * @return The fading edge length or 0
18763      * @hide
18764      */
18765     @InspectableProperty
getFadingEdgeLength()18766     public int getFadingEdgeLength() {
18767         if (mScrollCache != null && (mViewFlags & FADING_EDGE_MASK) != FADING_EDGE_NONE) {
18768             return mScrollCache.fadingEdgeLength;
18769         }
18770         return 0;
18771     }
18772 
18773     /**
18774      * Returns the strength, or intensity, of the top faded edge. The strength is
18775      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
18776      * returns 0.0 or 1.0 but no value in between.
18777      *
18778      * Subclasses should override this method to provide a smoother fade transition
18779      * when scrolling occurs.
18780      *
18781      * @return the intensity of the top fade as a float between 0.0f and 1.0f
18782      */
getTopFadingEdgeStrength()18783     protected float getTopFadingEdgeStrength() {
18784         return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
18785     }
18786 
18787     /**
18788      * Returns the strength, or intensity, of the bottom faded edge. The strength is
18789      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
18790      * returns 0.0 or 1.0 but no value in between.
18791      *
18792      * Subclasses should override this method to provide a smoother fade transition
18793      * when scrolling occurs.
18794      *
18795      * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
18796      */
getBottomFadingEdgeStrength()18797     protected float getBottomFadingEdgeStrength() {
18798         return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
18799                 computeVerticalScrollRange() ? 1.0f : 0.0f;
18800     }
18801 
18802     /**
18803      * Returns the strength, or intensity, of the left faded edge. The strength is
18804      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
18805      * returns 0.0 or 1.0 but no value in between.
18806      *
18807      * Subclasses should override this method to provide a smoother fade transition
18808      * when scrolling occurs.
18809      *
18810      * @return the intensity of the left fade as a float between 0.0f and 1.0f
18811      */
getLeftFadingEdgeStrength()18812     protected float getLeftFadingEdgeStrength() {
18813         return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
18814     }
18815 
18816     /**
18817      * Returns the strength, or intensity, of the right faded edge. The strength is
18818      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
18819      * returns 0.0 or 1.0 but no value in between.
18820      *
18821      * Subclasses should override this method to provide a smoother fade transition
18822      * when scrolling occurs.
18823      *
18824      * @return the intensity of the right fade as a float between 0.0f and 1.0f
18825      */
getRightFadingEdgeStrength()18826     protected float getRightFadingEdgeStrength() {
18827         return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
18828                 computeHorizontalScrollRange() ? 1.0f : 0.0f;
18829     }
18830 
18831     /**
18832      * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
18833      * scrollbar is not drawn by default.</p>
18834      *
18835      * @return true if the horizontal scrollbar should be painted, false
18836      *         otherwise
18837      *
18838      * @see #setHorizontalScrollBarEnabled(boolean)
18839      */
isHorizontalScrollBarEnabled()18840     public boolean isHorizontalScrollBarEnabled() {
18841         return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
18842     }
18843 
18844     /**
18845      * <p>Define whether the horizontal scrollbar should be drawn or not. The
18846      * scrollbar is not drawn by default.</p>
18847      *
18848      * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
18849      *                                   be painted
18850      *
18851      * @see #isHorizontalScrollBarEnabled()
18852      */
setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled)18853     public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
18854         if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
18855             mViewFlags ^= SCROLLBARS_HORIZONTAL;
18856             computeOpaqueFlags();
18857             resolvePadding();
18858         }
18859     }
18860 
18861     /**
18862      * <p>Indicate whether the vertical scrollbar should be drawn or not. The
18863      * scrollbar is not drawn by default.</p>
18864      *
18865      * @return true if the vertical scrollbar should be painted, false
18866      *         otherwise
18867      *
18868      * @see #setVerticalScrollBarEnabled(boolean)
18869      */
isVerticalScrollBarEnabled()18870     public boolean isVerticalScrollBarEnabled() {
18871         return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
18872     }
18873 
18874     /**
18875      * <p>Define whether the vertical scrollbar should be drawn or not. The
18876      * scrollbar is not drawn by default.</p>
18877      *
18878      * @param verticalScrollBarEnabled true if the vertical scrollbar should
18879      *                                 be painted
18880      *
18881      * @see #isVerticalScrollBarEnabled()
18882      */
setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled)18883     public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
18884         if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
18885             mViewFlags ^= SCROLLBARS_VERTICAL;
18886             computeOpaqueFlags();
18887             resolvePadding();
18888         }
18889     }
18890 
18891     /**
18892      * @hide
18893      */
18894     @UnsupportedAppUsage
recomputePadding()18895     protected void recomputePadding() {
18896         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
18897     }
18898 
18899     /**
18900      * Define whether scrollbars will fade when the view is not scrolling.
18901      *
18902      * @param fadeScrollbars whether to enable fading
18903      *
18904      * @attr ref android.R.styleable#View_fadeScrollbars
18905      */
setScrollbarFadingEnabled(boolean fadeScrollbars)18906     public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
18907         initScrollCache();
18908         final ScrollabilityCache scrollabilityCache = mScrollCache;
18909         scrollabilityCache.fadeScrollBars = fadeScrollbars;
18910         if (fadeScrollbars) {
18911             scrollabilityCache.state = ScrollabilityCache.OFF;
18912         } else {
18913             scrollabilityCache.state = ScrollabilityCache.ON;
18914         }
18915     }
18916 
18917     /**
18918      *
18919      * Returns true if scrollbars will fade when this view is not scrolling
18920      *
18921      * @return true if scrollbar fading is enabled
18922      *
18923      * @attr ref android.R.styleable#View_fadeScrollbars
18924      */
isScrollbarFadingEnabled()18925     public boolean isScrollbarFadingEnabled() {
18926         return mScrollCache != null && mScrollCache.fadeScrollBars;
18927     }
18928 
18929     /**
18930      *
18931      * Returns the delay before scrollbars fade.
18932      *
18933      * @return the delay before scrollbars fade
18934      *
18935      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
18936      */
18937     @InspectableProperty(name = "scrollbarDefaultDelayBeforeFade")
getScrollBarDefaultDelayBeforeFade()18938     public int getScrollBarDefaultDelayBeforeFade() {
18939         return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
18940                 mScrollCache.scrollBarDefaultDelayBeforeFade;
18941     }
18942 
18943     /**
18944      * Define the delay before scrollbars fade.
18945      *
18946      * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
18947      *
18948      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
18949      */
setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade)18950     public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
18951         getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
18952     }
18953 
18954     /**
18955      *
18956      * Returns the scrollbar fade duration.
18957      *
18958      * @return the scrollbar fade duration, in milliseconds
18959      *
18960      * @attr ref android.R.styleable#View_scrollbarFadeDuration
18961      */
18962     @InspectableProperty(name = "scrollbarFadeDuration")
getScrollBarFadeDuration()18963     public int getScrollBarFadeDuration() {
18964         return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
18965                 mScrollCache.scrollBarFadeDuration;
18966     }
18967 
18968     /**
18969      * Define the scrollbar fade duration.
18970      *
18971      * @param scrollBarFadeDuration - the scrollbar fade duration, in milliseconds
18972      *
18973      * @attr ref android.R.styleable#View_scrollbarFadeDuration
18974      */
setScrollBarFadeDuration(int scrollBarFadeDuration)18975     public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
18976         getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
18977     }
18978 
18979     /**
18980      *
18981      * Returns the scrollbar size.
18982      *
18983      * @return the scrollbar size
18984      *
18985      * @attr ref android.R.styleable#View_scrollbarSize
18986      */
18987     @InspectableProperty(name = "scrollbarSize")
getScrollBarSize()18988     public int getScrollBarSize() {
18989         return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
18990                 mScrollCache.scrollBarSize;
18991     }
18992 
18993     /**
18994      * Define the scrollbar size.
18995      *
18996      * @param scrollBarSize - the scrollbar size
18997      *
18998      * @attr ref android.R.styleable#View_scrollbarSize
18999      */
setScrollBarSize(int scrollBarSize)19000     public void setScrollBarSize(int scrollBarSize) {
19001         getScrollCache().scrollBarSize = scrollBarSize;
19002     }
19003 
19004     /**
19005      * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
19006      * inset. When inset, they add to the padding of the view. And the scrollbars
19007      * can be drawn inside the padding area or on the edge of the view. For example,
19008      * if a view has a background drawable and you want to draw the scrollbars
19009      * inside the padding specified by the drawable, you can use
19010      * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
19011      * appear at the edge of the view, ignoring the padding, then you can use
19012      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
19013      * @param style the style of the scrollbars. Should be one of
19014      * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
19015      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
19016      * @see #SCROLLBARS_INSIDE_OVERLAY
19017      * @see #SCROLLBARS_INSIDE_INSET
19018      * @see #SCROLLBARS_OUTSIDE_OVERLAY
19019      * @see #SCROLLBARS_OUTSIDE_INSET
19020      *
19021      * @attr ref android.R.styleable#View_scrollbarStyle
19022      */
setScrollBarStyle(@crollBarStyle int style)19023     public void setScrollBarStyle(@ScrollBarStyle int style) {
19024         if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
19025             mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
19026             computeOpaqueFlags();
19027             resolvePadding();
19028         }
19029     }
19030 
19031     /**
19032      * <p>Returns the current scrollbar style.</p>
19033      * @return the current scrollbar style
19034      * @see #SCROLLBARS_INSIDE_OVERLAY
19035      * @see #SCROLLBARS_INSIDE_INSET
19036      * @see #SCROLLBARS_OUTSIDE_OVERLAY
19037      * @see #SCROLLBARS_OUTSIDE_INSET
19038      *
19039      * @attr ref android.R.styleable#View_scrollbarStyle
19040      */
19041     @ViewDebug.ExportedProperty(mapping = {
19042             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
19043             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
19044             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
19045             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
19046     })
19047     @InspectableProperty(name = "scrollbarStyle", enumMapping = {
19048             @EnumEntry(value = SCROLLBARS_INSIDE_OVERLAY, name = "insideOverlay"),
19049             @EnumEntry(value = SCROLLBARS_INSIDE_INSET, name = "insideInset"),
19050             @EnumEntry(value = SCROLLBARS_OUTSIDE_OVERLAY, name = "outsideOverlay"),
19051             @EnumEntry(value = SCROLLBARS_OUTSIDE_INSET, name = "outsideInset")
19052     })
19053     @ScrollBarStyle
getScrollBarStyle()19054     public int getScrollBarStyle() {
19055         return mViewFlags & SCROLLBARS_STYLE_MASK;
19056     }
19057 
19058     /**
19059      * <p>Compute the horizontal range that the horizontal scrollbar
19060      * represents.</p>
19061      *
19062      * <p>The range is expressed in arbitrary units that must be the same as the
19063      * units used by {@link #computeHorizontalScrollExtent()} and
19064      * {@link #computeHorizontalScrollOffset()}.</p>
19065      *
19066      * <p>The default range is the drawing width of this view.</p>
19067      *
19068      * @return the total horizontal range represented by the horizontal
19069      *         scrollbar
19070      *
19071      * @see #computeHorizontalScrollExtent()
19072      * @see #computeHorizontalScrollOffset()
19073      */
computeHorizontalScrollRange()19074     protected int computeHorizontalScrollRange() {
19075         return getWidth();
19076     }
19077 
19078     /**
19079      * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
19080      * within the horizontal range. This value is used to compute the position
19081      * of the thumb within the scrollbar's track.</p>
19082      *
19083      * <p>The range is expressed in arbitrary units that must be the same as the
19084      * units used by {@link #computeHorizontalScrollRange()} and
19085      * {@link #computeHorizontalScrollExtent()}.</p>
19086      *
19087      * <p>The default offset is the scroll offset of this view.</p>
19088      *
19089      * @return the horizontal offset of the scrollbar's thumb
19090      *
19091      * @see #computeHorizontalScrollRange()
19092      * @see #computeHorizontalScrollExtent()
19093      */
computeHorizontalScrollOffset()19094     protected int computeHorizontalScrollOffset() {
19095         return mScrollX;
19096     }
19097 
19098     /**
19099      * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
19100      * within the horizontal range. This value is used to compute the length
19101      * of the thumb within the scrollbar's track.</p>
19102      *
19103      * <p>The range is expressed in arbitrary units that must be the same as the
19104      * units used by {@link #computeHorizontalScrollRange()} and
19105      * {@link #computeHorizontalScrollOffset()}.</p>
19106      *
19107      * <p>The default extent is the drawing width of this view.</p>
19108      *
19109      * @return the horizontal extent of the scrollbar's thumb
19110      *
19111      * @see #computeHorizontalScrollRange()
19112      * @see #computeHorizontalScrollOffset()
19113      */
computeHorizontalScrollExtent()19114     protected int computeHorizontalScrollExtent() {
19115         return getWidth();
19116     }
19117 
19118     /**
19119      * <p>Compute the vertical range that the vertical scrollbar represents.</p>
19120      *
19121      * <p>The range is expressed in arbitrary units that must be the same as the
19122      * units used by {@link #computeVerticalScrollExtent()} and
19123      * {@link #computeVerticalScrollOffset()}.</p>
19124      *
19125      * @return the total vertical range represented by the vertical scrollbar
19126      *
19127      * <p>The default range is the drawing height of this view.</p>
19128      *
19129      * @see #computeVerticalScrollExtent()
19130      * @see #computeVerticalScrollOffset()
19131      */
computeVerticalScrollRange()19132     protected int computeVerticalScrollRange() {
19133         return getHeight();
19134     }
19135 
19136     /**
19137      * <p>Compute the vertical offset of the vertical scrollbar's thumb
19138      * within the horizontal range. This value is used to compute the position
19139      * of the thumb within the scrollbar's track.</p>
19140      *
19141      * <p>The range is expressed in arbitrary units that must be the same as the
19142      * units used by {@link #computeVerticalScrollRange()} and
19143      * {@link #computeVerticalScrollExtent()}.</p>
19144      *
19145      * <p>The default offset is the scroll offset of this view.</p>
19146      *
19147      * @return the vertical offset of the scrollbar's thumb
19148      *
19149      * @see #computeVerticalScrollRange()
19150      * @see #computeVerticalScrollExtent()
19151      */
computeVerticalScrollOffset()19152     protected int computeVerticalScrollOffset() {
19153         return mScrollY;
19154     }
19155 
19156     /**
19157      * <p>Compute the vertical extent of the vertical scrollbar's thumb
19158      * within the vertical range. This value is used to compute the length
19159      * of the thumb within the scrollbar's track.</p>
19160      *
19161      * <p>The range is expressed in arbitrary units that must be the same as the
19162      * units used by {@link #computeVerticalScrollRange()} and
19163      * {@link #computeVerticalScrollOffset()}.</p>
19164      *
19165      * <p>The default extent is the drawing height of this view.</p>
19166      *
19167      * @return the vertical extent of the scrollbar's thumb
19168      *
19169      * @see #computeVerticalScrollRange()
19170      * @see #computeVerticalScrollOffset()
19171      */
computeVerticalScrollExtent()19172     protected int computeVerticalScrollExtent() {
19173         return getHeight();
19174     }
19175 
19176     /**
19177      * Check if this view can be scrolled horizontally in a certain direction.
19178      *
19179      * @param direction Negative to check scrolling left, positive to check scrolling right.
19180      * @return true if this view can be scrolled in the specified direction, false otherwise.
19181      */
canScrollHorizontally(int direction)19182     public boolean canScrollHorizontally(int direction) {
19183         final int offset = computeHorizontalScrollOffset();
19184         final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
19185         if (range == 0) return false;
19186         if (direction < 0) {
19187             return offset > 0;
19188         } else {
19189             return offset < range - 1;
19190         }
19191     }
19192 
19193     /**
19194      * Check if this view can be scrolled vertically in a certain direction.
19195      *
19196      * @param direction Negative to check scrolling up, positive to check scrolling down.
19197      * @return true if this view can be scrolled in the specified direction, false otherwise.
19198      */
canScrollVertically(int direction)19199     public boolean canScrollVertically(int direction) {
19200         final int offset = computeVerticalScrollOffset();
19201         final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
19202         if (range == 0) return false;
19203         if (direction < 0) {
19204             return offset > 0;
19205         } else {
19206             return offset < range - 1;
19207         }
19208     }
19209 
getScrollIndicatorBounds(@onNull Rect out)19210     void getScrollIndicatorBounds(@NonNull Rect out) {
19211         out.left = mScrollX;
19212         out.right = mScrollX + mRight - mLeft;
19213         out.top = mScrollY;
19214         out.bottom = mScrollY + mBottom - mTop;
19215     }
19216 
onDrawScrollIndicators(Canvas c)19217     private void onDrawScrollIndicators(Canvas c) {
19218         if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
19219             // No scroll indicators enabled.
19220             return;
19221         }
19222 
19223         final Drawable dr = mScrollIndicatorDrawable;
19224         if (dr == null) {
19225             // Scroll indicators aren't supported here.
19226             return;
19227         }
19228 
19229         final int h = dr.getIntrinsicHeight();
19230         final int w = dr.getIntrinsicWidth();
19231         final Rect rect = mAttachInfo.mTmpInvalRect;
19232         getScrollIndicatorBounds(rect);
19233 
19234         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
19235             final boolean canScrollUp = canScrollVertically(-1);
19236             if (canScrollUp) {
19237                 dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
19238                 dr.draw(c);
19239             }
19240         }
19241 
19242         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
19243             final boolean canScrollDown = canScrollVertically(1);
19244             if (canScrollDown) {
19245                 dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
19246                 dr.draw(c);
19247             }
19248         }
19249 
19250         final int leftRtl;
19251         final int rightRtl;
19252         if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
19253             leftRtl = PFLAG3_SCROLL_INDICATOR_END;
19254             rightRtl = PFLAG3_SCROLL_INDICATOR_START;
19255         } else {
19256             leftRtl = PFLAG3_SCROLL_INDICATOR_START;
19257             rightRtl = PFLAG3_SCROLL_INDICATOR_END;
19258         }
19259 
19260         final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
19261         if ((mPrivateFlags3 & leftMask) != 0) {
19262             final boolean canScrollLeft = canScrollHorizontally(-1);
19263             if (canScrollLeft) {
19264                 dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
19265                 dr.draw(c);
19266             }
19267         }
19268 
19269         final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
19270         if ((mPrivateFlags3 & rightMask) != 0) {
19271             final boolean canScrollRight = canScrollHorizontally(1);
19272             if (canScrollRight) {
19273                 dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
19274                 dr.draw(c);
19275             }
19276         }
19277     }
19278 
getHorizontalScrollBarBounds(@ullable Rect drawBounds, @Nullable Rect touchBounds)19279     private void getHorizontalScrollBarBounds(@Nullable Rect drawBounds,
19280             @Nullable Rect touchBounds) {
19281         final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
19282         if (bounds == null) {
19283             return;
19284         }
19285         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
19286         final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
19287                 && !isVerticalScrollBarHidden();
19288         final int size = getHorizontalScrollbarHeight();
19289         final int verticalScrollBarGap = drawVerticalScrollBar ?
19290                 getVerticalScrollbarWidth() : 0;
19291         final int width = mRight - mLeft;
19292         final int height = mBottom - mTop;
19293         bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
19294         bounds.left = mScrollX + (mPaddingLeft & inside);
19295         bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
19296         bounds.bottom = bounds.top + size;
19297 
19298         if (touchBounds == null) {
19299             return;
19300         }
19301         if (touchBounds != bounds) {
19302             touchBounds.set(bounds);
19303         }
19304         final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
19305         if (touchBounds.height() < minTouchTarget) {
19306             final int adjust = (minTouchTarget - touchBounds.height()) / 2;
19307             touchBounds.bottom = Math.min(touchBounds.bottom + adjust, mScrollY + height);
19308             touchBounds.top = touchBounds.bottom - minTouchTarget;
19309         }
19310         if (touchBounds.width() < minTouchTarget) {
19311             final int adjust = (minTouchTarget - touchBounds.width()) / 2;
19312             touchBounds.left -= adjust;
19313             touchBounds.right = touchBounds.left + minTouchTarget;
19314         }
19315     }
19316 
getVerticalScrollBarBounds(@ullable Rect bounds, @Nullable Rect touchBounds)19317     private void getVerticalScrollBarBounds(@Nullable Rect bounds, @Nullable Rect touchBounds) {
19318         if (mRoundScrollbarRenderer == null) {
19319             getStraightVerticalScrollBarBounds(bounds, touchBounds);
19320         } else {
19321             getRoundVerticalScrollBarBounds(bounds != null ? bounds : touchBounds);
19322         }
19323     }
19324 
getRoundVerticalScrollBarBounds(Rect bounds)19325     private void getRoundVerticalScrollBarBounds(Rect bounds) {
19326         final int width = mRight - mLeft;
19327         final int height = mBottom - mTop;
19328         // Do not take padding into account as we always want the scrollbars
19329         // to hug the screen for round wearable devices.
19330         bounds.left = mScrollX;
19331         bounds.top = mScrollY;
19332         bounds.right = bounds.left + width;
19333         bounds.bottom = mScrollY + height;
19334     }
19335 
getStraightVerticalScrollBarBounds(@ullable Rect drawBounds, @Nullable Rect touchBounds)19336     private void getStraightVerticalScrollBarBounds(@Nullable Rect drawBounds,
19337             @Nullable Rect touchBounds) {
19338         final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
19339         if (bounds == null) {
19340             return;
19341         }
19342         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
19343         final int size = getVerticalScrollbarWidth();
19344         int verticalScrollbarPosition = mVerticalScrollbarPosition;
19345         if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
19346             verticalScrollbarPosition = isLayoutRtl() ?
19347                     SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
19348         }
19349         final int width = mRight - mLeft;
19350         final int height = mBottom - mTop;
19351         switch (verticalScrollbarPosition) {
19352             default:
19353             case SCROLLBAR_POSITION_RIGHT:
19354                 bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
19355                 break;
19356             case SCROLLBAR_POSITION_LEFT:
19357                 bounds.left = mScrollX + (mUserPaddingLeft & inside);
19358                 break;
19359         }
19360         bounds.top = mScrollY + (mPaddingTop & inside);
19361         bounds.right = bounds.left + size;
19362         bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
19363 
19364         if (touchBounds == null) {
19365             return;
19366         }
19367         if (touchBounds != bounds) {
19368             touchBounds.set(bounds);
19369         }
19370         final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
19371         if (touchBounds.width() < minTouchTarget) {
19372             final int adjust = (minTouchTarget - touchBounds.width()) / 2;
19373             if (verticalScrollbarPosition == SCROLLBAR_POSITION_RIGHT) {
19374                 touchBounds.right = Math.min(touchBounds.right + adjust, mScrollX + width);
19375                 touchBounds.left = touchBounds.right - minTouchTarget;
19376             } else {
19377                 touchBounds.left = Math.max(touchBounds.left + adjust, mScrollX);
19378                 touchBounds.right = touchBounds.left + minTouchTarget;
19379             }
19380         }
19381         if (touchBounds.height() < minTouchTarget) {
19382             final int adjust = (minTouchTarget - touchBounds.height()) / 2;
19383             touchBounds.top -= adjust;
19384             touchBounds.bottom = touchBounds.top + minTouchTarget;
19385         }
19386     }
19387 
19388     /**
19389      * <p>Request the drawing of the horizontal and the vertical scrollbar. The
19390      * scrollbars are painted only if they have been awakened first.</p>
19391      *
19392      * @param canvas the canvas on which to draw the scrollbars
19393      *
19394      * @see #awakenScrollBars(int)
19395      */
onDrawScrollBars(Canvas canvas)19396     protected final void onDrawScrollBars(Canvas canvas) {
19397         // scrollbars are drawn only when the animation is running
19398         final ScrollabilityCache cache = mScrollCache;
19399 
19400         if (cache != null) {
19401 
19402             int state = cache.state;
19403 
19404             if (state == ScrollabilityCache.OFF) {
19405                 return;
19406             }
19407 
19408             boolean invalidate = false;
19409 
19410             if (state == ScrollabilityCache.FADING) {
19411                 // We're fading -- get our fade interpolation
19412                 if (cache.interpolatorValues == null) {
19413                     cache.interpolatorValues = new float[1];
19414                 }
19415 
19416                 float[] values = cache.interpolatorValues;
19417 
19418                 // Stops the animation if we're done
19419                 if (cache.scrollBarInterpolator.timeToValues(values) ==
19420                         Interpolator.Result.FREEZE_END) {
19421                     cache.state = ScrollabilityCache.OFF;
19422                 } else {
19423                     cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
19424                 }
19425 
19426                 // This will make the scroll bars inval themselves after
19427                 // drawing. We only want this when we're fading so that
19428                 // we prevent excessive redraws
19429                 invalidate = true;
19430             } else {
19431                 // We're just on -- but we may have been fading before so
19432                 // reset alpha
19433                 cache.scrollBar.mutate().setAlpha(255);
19434             }
19435 
19436             final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
19437             final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
19438                     && !isVerticalScrollBarHidden();
19439 
19440             // Fork out the scroll bar drawing for round wearable devices.
19441             if (mRoundScrollbarRenderer != null) {
19442                 if (drawVerticalScrollBar) {
19443                     final Rect bounds = cache.mScrollBarBounds;
19444                     getVerticalScrollBarBounds(bounds, null);
19445                     mRoundScrollbarRenderer.drawRoundScrollbars(
19446                             canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
19447                     if (invalidate) {
19448                         invalidate();
19449                     }
19450                 }
19451                 // Do not draw horizontal scroll bars for round wearable devices.
19452             } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
19453                 final ScrollBarDrawable scrollBar = cache.scrollBar;
19454 
19455                 if (drawHorizontalScrollBar) {
19456                     scrollBar.setParameters(computeHorizontalScrollRange(),
19457                             computeHorizontalScrollOffset(),
19458                             computeHorizontalScrollExtent(), false);
19459                     final Rect bounds = cache.mScrollBarBounds;
19460                     getHorizontalScrollBarBounds(bounds, null);
19461                     onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
19462                             bounds.right, bounds.bottom);
19463                     if (invalidate) {
19464                         invalidate(bounds);
19465                     }
19466                 }
19467 
19468                 if (drawVerticalScrollBar) {
19469                     scrollBar.setParameters(computeVerticalScrollRange(),
19470                             computeVerticalScrollOffset(),
19471                             computeVerticalScrollExtent(), true);
19472                     final Rect bounds = cache.mScrollBarBounds;
19473                     getVerticalScrollBarBounds(bounds, null);
19474                     onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
19475                             bounds.right, bounds.bottom);
19476                     if (invalidate) {
19477                         invalidate(bounds);
19478                     }
19479                 }
19480             }
19481         }
19482     }
19483 
19484     /**
19485      * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
19486      * FastScroller is visible.
19487      * @return whether to temporarily hide the vertical scrollbar
19488      * @hide
19489      */
isVerticalScrollBarHidden()19490     protected boolean isVerticalScrollBarHidden() {
19491         return false;
19492     }
19493 
19494     /**
19495      * <p>Draw the horizontal scrollbar if
19496      * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
19497      *
19498      * @param canvas the canvas on which to draw the scrollbar
19499      * @param scrollBar the scrollbar's drawable
19500      *
19501      * @see #isHorizontalScrollBarEnabled()
19502      * @see #computeHorizontalScrollRange()
19503      * @see #computeHorizontalScrollExtent()
19504      * @see #computeHorizontalScrollOffset()
19505      * @hide
19506      */
19507     @UnsupportedAppUsage
onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t, int r, int b)19508     protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
19509             int l, int t, int r, int b) {
19510         scrollBar.setBounds(l, t, r, b);
19511         scrollBar.draw(canvas);
19512     }
19513 
19514     /**
19515      * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
19516      * returns true.</p>
19517      *
19518      * @param canvas the canvas on which to draw the scrollbar
19519      * @param scrollBar the scrollbar's drawable
19520      *
19521      * @see #isVerticalScrollBarEnabled()
19522      * @see #computeVerticalScrollRange()
19523      * @see #computeVerticalScrollExtent()
19524      * @see #computeVerticalScrollOffset()
19525      * @hide
19526      */
19527     @UnsupportedAppUsage
onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t, int r, int b)19528     protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
19529             int l, int t, int r, int b) {
19530         scrollBar.setBounds(l, t, r, b);
19531         scrollBar.draw(canvas);
19532     }
19533 
19534     /**
19535      * Implement this to do your drawing.
19536      *
19537      * @param canvas the canvas on which the background will be drawn
19538      */
onDraw(Canvas canvas)19539     protected void onDraw(Canvas canvas) {
19540     }
19541 
19542     /*
19543      * Caller is responsible for calling requestLayout if necessary.
19544      * (This allows addViewInLayout to not request a new layout.)
19545      */
19546     @UnsupportedAppUsage
assignParent(ViewParent parent)19547     void assignParent(ViewParent parent) {
19548         if (mParent == null) {
19549             mParent = parent;
19550         } else if (parent == null) {
19551             mParent = null;
19552         } else {
19553             throw new RuntimeException("view " + this + " being added, but"
19554                     + " it already has a parent");
19555         }
19556     }
19557 
19558     /**
19559      * This is called when the view is attached to a window.  At this point it
19560      * has a Surface and will start drawing.  Note that this function is
19561      * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
19562      * however it may be called any time before the first onDraw -- including
19563      * before or after {@link #onMeasure(int, int)}.
19564      *
19565      * @see #onDetachedFromWindow()
19566      */
19567     @CallSuper
onAttachedToWindow()19568     protected void onAttachedToWindow() {
19569         if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
19570             mParent.requestTransparentRegion(this);
19571         }
19572 
19573         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
19574 
19575         jumpDrawablesToCurrentState();
19576 
19577         AccessibilityNodeIdManager.getInstance().registerViewWithId(this, getAccessibilityViewId());
19578         resetSubtreeAccessibilityStateChanged();
19579 
19580         // rebuild, since Outline not maintained while View is detached
19581         rebuildOutline();
19582 
19583         if (isFocused()) {
19584             notifyFocusChangeToInputMethodManager(true /* hasFocus */);
19585         }
19586     }
19587 
19588     /**
19589      * Resolve all RTL related properties.
19590      *
19591      * @return true if resolution of RTL properties has been done
19592      *
19593      * @hide
19594      */
resolveRtlPropertiesIfNeeded()19595     public boolean resolveRtlPropertiesIfNeeded() {
19596         if (!needRtlPropertiesResolution()) return false;
19597 
19598         // Order is important here: LayoutDirection MUST be resolved first
19599         if (!isLayoutDirectionResolved()) {
19600             resolveLayoutDirection();
19601             resolveLayoutParams();
19602         }
19603         // ... then we can resolve the others properties depending on the resolved LayoutDirection.
19604         if (!isTextDirectionResolved()) {
19605             resolveTextDirection();
19606         }
19607         if (!isTextAlignmentResolved()) {
19608             resolveTextAlignment();
19609         }
19610         // Should resolve Drawables before Padding because we need the layout direction of the
19611         // Drawable to correctly resolve Padding.
19612         if (!areDrawablesResolved()) {
19613             resolveDrawables();
19614         }
19615         if (!isPaddingResolved()) {
19616             resolvePadding();
19617         }
19618         onRtlPropertiesChanged(getLayoutDirection());
19619         return true;
19620     }
19621 
19622     /**
19623      * Reset resolution of all RTL related properties.
19624      *
19625      * @hide
19626      */
19627     @TestApi
resetRtlProperties()19628     public void resetRtlProperties() {
19629         resetResolvedLayoutDirection();
19630         resetResolvedTextDirection();
19631         resetResolvedTextAlignment();
19632         resetResolvedPadding();
19633         resetResolvedDrawables();
19634     }
19635 
19636     /**
19637      * @see #onScreenStateChanged(int)
19638      */
dispatchScreenStateChanged(int screenState)19639     void dispatchScreenStateChanged(int screenState) {
19640         onScreenStateChanged(screenState);
19641     }
19642 
19643     /**
19644      * This method is called whenever the state of the screen this view is
19645      * attached to changes. A state change will usually occurs when the screen
19646      * turns on or off (whether it happens automatically or the user does it
19647      * manually.)
19648      *
19649      * @param screenState The new state of the screen. Can be either
19650      *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
19651      */
onScreenStateChanged(int screenState)19652     public void onScreenStateChanged(int screenState) {
19653     }
19654 
19655     /**
19656      * @see #onMovedToDisplay(int, Configuration)
19657      */
dispatchMovedToDisplay(Display display, Configuration config)19658     void dispatchMovedToDisplay(Display display, Configuration config) {
19659         mAttachInfo.mDisplay = display;
19660         mAttachInfo.mDisplayState = display.getState();
19661         onMovedToDisplay(display.getDisplayId(), config);
19662     }
19663 
19664     /**
19665      * Called by the system when the hosting activity is moved from one display to another without
19666      * recreation. This means that the activity is declared to handle all changes to configuration
19667      * that happened when it was switched to another display, so it wasn't destroyed and created
19668      * again.
19669      *
19670      * <p>This call will be followed by {@link #onConfigurationChanged(Configuration)} if the
19671      * applied configuration actually changed. It is up to app developer to choose whether to handle
19672      * the change in this method or in the following {@link #onConfigurationChanged(Configuration)}
19673      * call.
19674      *
19675      * <p>Use this callback to track changes to the displays if some functionality relies on an
19676      * association with some display properties.
19677      *
19678      * @param displayId The id of the display to which the view was moved.
19679      * @param config Configuration of the resources on new display after move.
19680      *
19681      * @see #onConfigurationChanged(Configuration)
19682      * @hide
19683      */
onMovedToDisplay(int displayId, Configuration config)19684     public void onMovedToDisplay(int displayId, Configuration config) {
19685     }
19686 
19687     /**
19688      * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
19689      */
19690     @UnsupportedAppUsage
hasRtlSupport()19691     private boolean hasRtlSupport() {
19692         return mContext.getApplicationInfo().hasRtlSupport();
19693     }
19694 
19695     /**
19696      * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
19697      * RTL not supported)
19698      */
isRtlCompatibilityMode()19699     private boolean isRtlCompatibilityMode() {
19700         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
19701         return targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1 || !hasRtlSupport();
19702     }
19703 
19704     /**
19705      * @return true if RTL properties need resolution.
19706      *
19707      */
needRtlPropertiesResolution()19708     private boolean needRtlPropertiesResolution() {
19709         return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
19710     }
19711 
19712     /**
19713      * Called when any RTL property (layout direction or text direction or text alignment) has
19714      * been changed.
19715      *
19716      * Subclasses need to override this method to take care of cached information that depends on the
19717      * resolved layout direction, or to inform child views that inherit their layout direction.
19718      *
19719      * The default implementation does nothing.
19720      *
19721      * @param layoutDirection the direction of the layout
19722      *
19723      * @see #LAYOUT_DIRECTION_LTR
19724      * @see #LAYOUT_DIRECTION_RTL
19725      */
onRtlPropertiesChanged(@esolvedLayoutDir int layoutDirection)19726     public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
19727     }
19728 
19729     /**
19730      * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
19731      * that the parent directionality can and will be resolved before its children.
19732      *
19733      * @return true if resolution has been done, false otherwise.
19734      *
19735      * @hide
19736      */
resolveLayoutDirection()19737     public boolean resolveLayoutDirection() {
19738         // Clear any previous layout direction resolution
19739         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
19740 
19741         if (hasRtlSupport()) {
19742             // Set resolved depending on layout direction
19743             switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
19744                     PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
19745                 case LAYOUT_DIRECTION_INHERIT:
19746                     // We cannot resolve yet. LTR is by default and let the resolution happen again
19747                     // later to get the correct resolved value
19748                     if (!canResolveLayoutDirection()) return false;
19749 
19750                     // Parent has not yet resolved, LTR is still the default
19751                     try {
19752                         if (!mParent.isLayoutDirectionResolved()) return false;
19753 
19754                         if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
19755                             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
19756                         }
19757                     } catch (AbstractMethodError e) {
19758                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19759                                 " does not fully implement ViewParent", e);
19760                     }
19761                     break;
19762                 case LAYOUT_DIRECTION_RTL:
19763                     mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
19764                     break;
19765                 case LAYOUT_DIRECTION_LOCALE:
19766                     if((LAYOUT_DIRECTION_RTL ==
19767                             TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
19768                         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
19769                     }
19770                     break;
19771                 default:
19772                     // Nothing to do, LTR by default
19773             }
19774         }
19775 
19776         // Set to resolved
19777         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
19778         return true;
19779     }
19780 
19781     /**
19782      * Check if layout direction resolution can be done.
19783      *
19784      * @return true if layout direction resolution can be done otherwise return false.
19785      */
canResolveLayoutDirection()19786     public boolean canResolveLayoutDirection() {
19787         switch (getRawLayoutDirection()) {
19788             case LAYOUT_DIRECTION_INHERIT:
19789                 if (mParent != null) {
19790                     try {
19791                         return mParent.canResolveLayoutDirection();
19792                     } catch (AbstractMethodError e) {
19793                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19794                                 " does not fully implement ViewParent", e);
19795                     }
19796                 }
19797                 return false;
19798 
19799             default:
19800                 return true;
19801         }
19802     }
19803 
19804     /**
19805      * Reset the resolved layout direction. Layout direction will be resolved during a call to
19806      * {@link #onMeasure(int, int)}.
19807      *
19808      * @hide
19809      */
19810     @TestApi
resetResolvedLayoutDirection()19811     public void resetResolvedLayoutDirection() {
19812         // Reset the current resolved bits
19813         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
19814     }
19815 
19816     /**
19817      * @return true if the layout direction is inherited.
19818      *
19819      * @hide
19820      */
isLayoutDirectionInherited()19821     public boolean isLayoutDirectionInherited() {
19822         return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
19823     }
19824 
19825     /**
19826      * @return true if layout direction has been resolved.
19827      */
isLayoutDirectionResolved()19828     public boolean isLayoutDirectionResolved() {
19829         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
19830     }
19831 
19832     /**
19833      * Return if padding has been resolved
19834      *
19835      * @hide
19836      */
19837     @UnsupportedAppUsage
isPaddingResolved()19838     boolean isPaddingResolved() {
19839         return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
19840     }
19841 
19842     /**
19843      * Resolves padding depending on layout direction, if applicable, and
19844      * recomputes internal padding values to adjust for scroll bars.
19845      *
19846      * @hide
19847      */
19848     @UnsupportedAppUsage
resolvePadding()19849     public void resolvePadding() {
19850         final int resolvedLayoutDirection = getLayoutDirection();
19851 
19852         if (!isRtlCompatibilityMode()) {
19853             // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
19854             // If start / end padding are defined, they will be resolved (hence overriding) to
19855             // left / right or right / left depending on the resolved layout direction.
19856             // If start / end padding are not defined, use the left / right ones.
19857             if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
19858                 Rect padding = sThreadLocal.get();
19859                 if (padding == null) {
19860                     padding = new Rect();
19861                     sThreadLocal.set(padding);
19862                 }
19863                 mBackground.getPadding(padding);
19864                 if (!mLeftPaddingDefined) {
19865                     mUserPaddingLeftInitial = padding.left;
19866                 }
19867                 if (!mRightPaddingDefined) {
19868                     mUserPaddingRightInitial = padding.right;
19869                 }
19870             }
19871             switch (resolvedLayoutDirection) {
19872                 case LAYOUT_DIRECTION_RTL:
19873                     if (mUserPaddingStart != UNDEFINED_PADDING) {
19874                         mUserPaddingRight = mUserPaddingStart;
19875                     } else {
19876                         mUserPaddingRight = mUserPaddingRightInitial;
19877                     }
19878                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
19879                         mUserPaddingLeft = mUserPaddingEnd;
19880                     } else {
19881                         mUserPaddingLeft = mUserPaddingLeftInitial;
19882                     }
19883                     break;
19884                 case LAYOUT_DIRECTION_LTR:
19885                 default:
19886                     if (mUserPaddingStart != UNDEFINED_PADDING) {
19887                         mUserPaddingLeft = mUserPaddingStart;
19888                     } else {
19889                         mUserPaddingLeft = mUserPaddingLeftInitial;
19890                     }
19891                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
19892                         mUserPaddingRight = mUserPaddingEnd;
19893                     } else {
19894                         mUserPaddingRight = mUserPaddingRightInitial;
19895                     }
19896             }
19897 
19898             mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
19899         }
19900 
19901         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
19902         onRtlPropertiesChanged(resolvedLayoutDirection);
19903 
19904         mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
19905     }
19906 
19907     /**
19908      * Reset the resolved layout direction.
19909      *
19910      * @hide
19911      */
19912     @TestApi
resetResolvedPadding()19913     public void resetResolvedPadding() {
19914         resetResolvedPaddingInternal();
19915     }
19916 
19917     /**
19918      * Used when we only want to reset *this* view's padding and not trigger overrides
19919      * in ViewGroup that reset children too.
19920      */
resetResolvedPaddingInternal()19921     void resetResolvedPaddingInternal() {
19922         mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
19923     }
19924 
19925     /**
19926      * This is called when the view is detached from a window.  At this point it
19927      * no longer has a surface for drawing.
19928      *
19929      * @see #onAttachedToWindow()
19930      */
19931     @CallSuper
onDetachedFromWindow()19932     protected void onDetachedFromWindow() {
19933     }
19934 
19935     /**
19936      * This is a framework-internal mirror of onDetachedFromWindow() that's called
19937      * after onDetachedFromWindow().
19938      *
19939      * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
19940      * The super method should be called at the end of the overridden method to ensure
19941      * subclasses are destroyed first
19942      *
19943      * @hide
19944      */
19945     @CallSuper
19946     @UnsupportedAppUsage
onDetachedFromWindowInternal()19947     protected void onDetachedFromWindowInternal() {
19948         mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
19949         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
19950         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
19951 
19952         removeUnsetPressCallback();
19953         removeLongPressCallback();
19954         removePerformClickCallback();
19955         cancel(mSendViewScrolledAccessibilityEvent);
19956         stopNestedScroll();
19957 
19958         // Anything that started animating right before detach should already
19959         // be in its final state when re-attached.
19960         jumpDrawablesToCurrentState();
19961 
19962         destroyDrawingCache();
19963 
19964         cleanupDraw();
19965         mCurrentAnimation = null;
19966 
19967         if ((mViewFlags & TOOLTIP) == TOOLTIP) {
19968             hideTooltip();
19969         }
19970 
19971         AccessibilityNodeIdManager.getInstance().unregisterViewWithId(getAccessibilityViewId());
19972     }
19973 
cleanupDraw()19974     private void cleanupDraw() {
19975         resetDisplayList();
19976         if (mAttachInfo != null) {
19977             mAttachInfo.mViewRootImpl.cancelInvalidate(this);
19978         }
19979     }
19980 
invalidateInheritedLayoutMode(int layoutModeOfRoot)19981     void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
19982     }
19983 
19984     /**
19985      * @return The number of times this view has been attached to a window
19986      */
getWindowAttachCount()19987     protected int getWindowAttachCount() {
19988         return mWindowAttachCount;
19989     }
19990 
19991     /**
19992      * Retrieve a unique token identifying the window this view is attached to.
19993      * @return Return the window's token for use in
19994      * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
19995      */
getWindowToken()19996     public IBinder getWindowToken() {
19997         return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
19998     }
19999 
20000     /**
20001      * Retrieve the {@link WindowId} for the window this view is
20002      * currently attached to.
20003      */
getWindowId()20004     public WindowId getWindowId() {
20005         AttachInfo ai = mAttachInfo;
20006         if (ai == null) {
20007             return null;
20008         }
20009         if (ai.mWindowId == null) {
20010             try {
20011                 ai.mIWindowId = ai.mSession.getWindowId(ai.mWindowToken);
20012                 if (ai.mIWindowId != null) {
20013                     ai.mWindowId = new WindowId(ai.mIWindowId);
20014                 }
20015             } catch (RemoteException e) {
20016             }
20017         }
20018         return ai.mWindowId;
20019     }
20020 
20021     /**
20022      * Retrieve a unique token identifying the top-level "real" window of
20023      * the window that this view is attached to.  That is, this is like
20024      * {@link #getWindowToken}, except if the window this view in is a panel
20025      * window (attached to another containing window), then the token of
20026      * the containing window is returned instead.
20027      *
20028      * @return Returns the associated window token, either
20029      * {@link #getWindowToken()} or the containing window's token.
20030      */
getApplicationWindowToken()20031     public IBinder getApplicationWindowToken() {
20032         AttachInfo ai = mAttachInfo;
20033         if (ai != null) {
20034             IBinder appWindowToken = ai.mPanelParentWindowToken;
20035             if (appWindowToken == null) {
20036                 appWindowToken = ai.mWindowToken;
20037             }
20038             return appWindowToken;
20039         }
20040         return null;
20041     }
20042 
20043     /**
20044      * Gets the logical display to which the view's window has been attached.
20045      *
20046      * @return The logical display, or null if the view is not currently attached to a window.
20047      */
getDisplay()20048     public Display getDisplay() {
20049         return mAttachInfo != null ? mAttachInfo.mDisplay : null;
20050     }
20051 
20052     /**
20053      * Retrieve private session object this view hierarchy is using to
20054      * communicate with the window manager.
20055      * @return the session object to communicate with the window manager
20056      */
20057     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
getWindowSession()20058     /*package*/ IWindowSession getWindowSession() {
20059         return mAttachInfo != null ? mAttachInfo.mSession : null;
20060     }
20061 
20062     /**
20063      * Return the window this view is currently attached to. Used in
20064      * {@link android.app.ActivityView} to communicate with WM.
20065      * @hide
20066      */
getWindow()20067     protected IWindow getWindow() {
20068         return mAttachInfo != null ? mAttachInfo.mWindow : null;
20069     }
20070 
20071     /**
20072      * Return the visibility value of the least visible component passed.
20073      */
combineVisibility(int vis1, int vis2)20074     int combineVisibility(int vis1, int vis2) {
20075         // This works because VISIBLE < INVISIBLE < GONE.
20076         return Math.max(vis1, vis2);
20077     }
20078 
20079     /**
20080      * @param info the {@link android.view.View.AttachInfo} to associated with
20081      *        this view
20082      */
20083     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
dispatchAttachedToWindow(AttachInfo info, int visibility)20084     void dispatchAttachedToWindow(AttachInfo info, int visibility) {
20085         mAttachInfo = info;
20086         if (mOverlay != null) {
20087             mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
20088         }
20089         mWindowAttachCount++;
20090         // We will need to evaluate the drawable state at least once.
20091         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
20092         if (mFloatingTreeObserver != null) {
20093             info.mTreeObserver.merge(mFloatingTreeObserver);
20094             mFloatingTreeObserver = null;
20095         }
20096 
20097         registerPendingFrameMetricsObservers();
20098 
20099         if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
20100             mAttachInfo.mScrollContainers.add(this);
20101             mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
20102         }
20103         // Transfer all pending runnables.
20104         if (mRunQueue != null) {
20105             mRunQueue.executeActions(info.mHandler);
20106             mRunQueue = null;
20107         }
20108         performCollectViewAttributes(mAttachInfo, visibility);
20109         onAttachedToWindow();
20110 
20111         ListenerInfo li = mListenerInfo;
20112         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
20113                 li != null ? li.mOnAttachStateChangeListeners : null;
20114         if (listeners != null && listeners.size() > 0) {
20115             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
20116             // perform the dispatching. The iterator is a safe guard against listeners that
20117             // could mutate the list by calling the various add/remove methods. This prevents
20118             // the array from being modified while we iterate it.
20119             for (OnAttachStateChangeListener listener : listeners) {
20120                 listener.onViewAttachedToWindow(this);
20121             }
20122         }
20123 
20124         int vis = info.mWindowVisibility;
20125         if (vis != GONE) {
20126             onWindowVisibilityChanged(vis);
20127             if (isShown()) {
20128                 // Calling onVisibilityAggregated directly here since the subtree will also
20129                 // receive dispatchAttachedToWindow and this same call
20130                 onVisibilityAggregated(vis == VISIBLE);
20131             }
20132         }
20133 
20134         // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
20135         // As all views in the subtree will already receive dispatchAttachedToWindow
20136         // traversing the subtree again here is not desired.
20137         onVisibilityChanged(this, visibility);
20138 
20139         if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
20140             // If nobody has evaluated the drawable state yet, then do it now.
20141             refreshDrawableState();
20142         }
20143         needGlobalAttributesUpdate(false);
20144 
20145         notifyEnterOrExitForAutoFillIfNeeded(true);
20146         notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
20147     }
20148 
20149     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
dispatchDetachedFromWindow()20150     void dispatchDetachedFromWindow() {
20151         AttachInfo info = mAttachInfo;
20152         if (info != null) {
20153             int vis = info.mWindowVisibility;
20154             if (vis != GONE) {
20155                 onWindowVisibilityChanged(GONE);
20156                 if (isShown()) {
20157                     // Invoking onVisibilityAggregated directly here since the subtree
20158                     // will also receive detached from window
20159                     onVisibilityAggregated(false);
20160                 }
20161             }
20162         }
20163 
20164         onDetachedFromWindow();
20165         onDetachedFromWindowInternal();
20166 
20167         InputMethodManager imm = getContext().getSystemService(InputMethodManager.class);
20168         if (imm != null) {
20169             imm.onViewDetachedFromWindow(this);
20170         }
20171 
20172         ListenerInfo li = mListenerInfo;
20173         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
20174                 li != null ? li.mOnAttachStateChangeListeners : null;
20175         if (listeners != null && listeners.size() > 0) {
20176             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
20177             // perform the dispatching. The iterator is a safe guard against listeners that
20178             // could mutate the list by calling the various add/remove methods. This prevents
20179             // the array from being modified while we iterate it.
20180             for (OnAttachStateChangeListener listener : listeners) {
20181                 listener.onViewDetachedFromWindow(this);
20182             }
20183         }
20184 
20185         if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
20186             mAttachInfo.mScrollContainers.remove(this);
20187             mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
20188         }
20189 
20190         mAttachInfo = null;
20191         if (mOverlay != null) {
20192             mOverlay.getOverlayView().dispatchDetachedFromWindow();
20193         }
20194 
20195         notifyEnterOrExitForAutoFillIfNeeded(false);
20196         notifyAppearedOrDisappearedForContentCaptureIfNeeded(false);
20197     }
20198 
20199     /**
20200      * Cancel any deferred high-level input events that were previously posted to the event queue.
20201      *
20202      * <p>Many views post high-level events such as click handlers to the event queue
20203      * to run deferred in order to preserve a desired user experience - clearing visible
20204      * pressed states before executing, etc. This method will abort any events of this nature
20205      * that are currently in flight.</p>
20206      *
20207      * <p>Custom views that generate their own high-level deferred input events should override
20208      * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
20209      *
20210      * <p>This will also cancel pending input events for any child views.</p>
20211      *
20212      * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
20213      * This will not impact newer events posted after this call that may occur as a result of
20214      * lower-level input events still waiting in the queue. If you are trying to prevent
20215      * double-submitted  events for the duration of some sort of asynchronous transaction
20216      * you should also take other steps to protect against unexpected double inputs e.g. calling
20217      * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
20218      * the transaction completes, tracking already submitted transaction IDs, etc.</p>
20219      */
cancelPendingInputEvents()20220     public final void cancelPendingInputEvents() {
20221         dispatchCancelPendingInputEvents();
20222     }
20223 
20224     /**
20225      * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
20226      * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
20227      */
dispatchCancelPendingInputEvents()20228     void dispatchCancelPendingInputEvents() {
20229         mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
20230         onCancelPendingInputEvents();
20231         if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
20232             throw new SuperNotCalledException("View " + getClass().getSimpleName() +
20233                     " did not call through to super.onCancelPendingInputEvents()");
20234         }
20235     }
20236 
20237     /**
20238      * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
20239      * a parent view.
20240      *
20241      * <p>This method is responsible for removing any pending high-level input events that were
20242      * posted to the event queue to run later. Custom view classes that post their own deferred
20243      * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
20244      * {@link android.os.Handler} should override this method, call
20245      * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
20246      * </p>
20247      */
onCancelPendingInputEvents()20248     public void onCancelPendingInputEvents() {
20249         removePerformClickCallback();
20250         cancelLongPress();
20251         mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
20252     }
20253 
20254     /**
20255      * Store this view hierarchy's frozen state into the given container.
20256      *
20257      * @param container The SparseArray in which to save the view's state.
20258      *
20259      * @see #restoreHierarchyState(android.util.SparseArray)
20260      * @see #dispatchSaveInstanceState(android.util.SparseArray)
20261      * @see #onSaveInstanceState()
20262      */
saveHierarchyState(SparseArray<Parcelable> container)20263     public void saveHierarchyState(SparseArray<Parcelable> container) {
20264         dispatchSaveInstanceState(container);
20265     }
20266 
20267     /**
20268      * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
20269      * this view and its children. May be overridden to modify how freezing happens to a
20270      * view's children; for example, some views may want to not store state for their children.
20271      *
20272      * @param container The SparseArray in which to save the view's state.
20273      *
20274      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
20275      * @see #saveHierarchyState(android.util.SparseArray)
20276      * @see #onSaveInstanceState()
20277      */
dispatchSaveInstanceState(SparseArray<Parcelable> container)20278     protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
20279         if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
20280             mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
20281             Parcelable state = onSaveInstanceState();
20282             if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
20283                 throw new IllegalStateException(
20284                         "Derived class did not call super.onSaveInstanceState()");
20285             }
20286             if (state != null) {
20287                 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
20288                 // + ": " + state);
20289                 container.put(mID, state);
20290             }
20291         }
20292     }
20293 
20294     /**
20295      * Hook allowing a view to generate a representation of its internal state
20296      * that can later be used to create a new instance with that same state.
20297      * This state should only contain information that is not persistent or can
20298      * not be reconstructed later. For example, you will never store your
20299      * current position on screen because that will be computed again when a
20300      * new instance of the view is placed in its view hierarchy.
20301      * <p>
20302      * Some examples of things you may store here: the current cursor position
20303      * in a text view (but usually not the text itself since that is stored in a
20304      * content provider or other persistent storage), the currently selected
20305      * item in a list view.
20306      *
20307      * @return Returns a Parcelable object containing the view's current dynamic
20308      *         state, or null if there is nothing interesting to save.
20309      * @see #onRestoreInstanceState(Parcelable)
20310      * @see #saveHierarchyState(SparseArray)
20311      * @see #dispatchSaveInstanceState(SparseArray)
20312      * @see #setSaveEnabled(boolean)
20313      */
20314     @CallSuper
onSaveInstanceState()20315     @Nullable protected Parcelable onSaveInstanceState() {
20316         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
20317         if (mStartActivityRequestWho != null || isAutofilled()
20318                 || mAutofillViewId > LAST_APP_AUTOFILL_ID) {
20319             BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
20320 
20321             if (mStartActivityRequestWho != null) {
20322                 state.mSavedData |= BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED;
20323             }
20324 
20325             if (isAutofilled()) {
20326                 state.mSavedData |= BaseSavedState.IS_AUTOFILLED;
20327             }
20328 
20329             if (mAutofillViewId > LAST_APP_AUTOFILL_ID) {
20330                 state.mSavedData |= BaseSavedState.AUTOFILL_ID;
20331             }
20332 
20333             state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
20334             state.mIsAutofilled = isAutofilled();
20335             state.mAutofillViewId = mAutofillViewId;
20336             return state;
20337         }
20338         return BaseSavedState.EMPTY_STATE;
20339     }
20340 
20341     /**
20342      * Restore this view hierarchy's frozen state from the given container.
20343      *
20344      * @param container The SparseArray which holds previously frozen states.
20345      *
20346      * @see #saveHierarchyState(android.util.SparseArray)
20347      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
20348      * @see #onRestoreInstanceState(android.os.Parcelable)
20349      */
restoreHierarchyState(SparseArray<Parcelable> container)20350     public void restoreHierarchyState(SparseArray<Parcelable> container) {
20351         dispatchRestoreInstanceState(container);
20352     }
20353 
20354     /**
20355      * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
20356      * state for this view and its children. May be overridden to modify how restoring
20357      * happens to a view's children; for example, some views may want to not store state
20358      * for their children.
20359      *
20360      * @param container The SparseArray which holds previously saved state.
20361      *
20362      * @see #dispatchSaveInstanceState(android.util.SparseArray)
20363      * @see #restoreHierarchyState(android.util.SparseArray)
20364      * @see #onRestoreInstanceState(android.os.Parcelable)
20365      */
dispatchRestoreInstanceState(SparseArray<Parcelable> container)20366     protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
20367         if (mID != NO_ID) {
20368             Parcelable state = container.get(mID);
20369             if (state != null) {
20370                 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
20371                 // + ": " + state);
20372                 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
20373                 onRestoreInstanceState(state);
20374                 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
20375                     throw new IllegalStateException(
20376                             "Derived class did not call super.onRestoreInstanceState()");
20377                 }
20378             }
20379         }
20380     }
20381 
20382     /**
20383      * Hook allowing a view to re-apply a representation of its internal state that had previously
20384      * been generated by {@link #onSaveInstanceState}. This function will never be called with a
20385      * null state.
20386      *
20387      * @param state The frozen state that had previously been returned by
20388      *        {@link #onSaveInstanceState}.
20389      *
20390      * @see #onSaveInstanceState()
20391      * @see #restoreHierarchyState(android.util.SparseArray)
20392      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
20393      */
20394     @CallSuper
onRestoreInstanceState(Parcelable state)20395     protected void onRestoreInstanceState(Parcelable state) {
20396         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
20397         if (state != null && !(state instanceof AbsSavedState)) {
20398             throw new IllegalArgumentException("Wrong state class, expecting View State but "
20399                     + "received " + state.getClass().toString() + " instead. This usually happens "
20400                     + "when two views of different type have the same id in the same hierarchy. "
20401                     + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
20402                     + "other views do not use the same id.");
20403         }
20404         if (state != null && state instanceof BaseSavedState) {
20405             BaseSavedState baseState = (BaseSavedState) state;
20406 
20407             if ((baseState.mSavedData & BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED) != 0) {
20408                 mStartActivityRequestWho = baseState.mStartActivityRequestWhoSaved;
20409             }
20410             if ((baseState.mSavedData & BaseSavedState.IS_AUTOFILLED) != 0) {
20411                 setAutofilled(baseState.mIsAutofilled);
20412             }
20413             if ((baseState.mSavedData & BaseSavedState.AUTOFILL_ID) != 0) {
20414                 // It can happen that views have the same view id and the restoration path will not
20415                 // be able to distinguish between them. The autofill id needs to be unique though.
20416                 // Hence prevent the same autofill view id from being restored multiple times.
20417                 ((BaseSavedState) state).mSavedData &= ~BaseSavedState.AUTOFILL_ID;
20418 
20419                 if ((mPrivateFlags3 & PFLAG3_AUTOFILLID_EXPLICITLY_SET) != 0) {
20420                     // Ignore when view already set it through setAutofillId();
20421                     if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.DEBUG)) {
20422                         Log.d(AUTOFILL_LOG_TAG, "onRestoreInstanceState(): not setting autofillId "
20423                                 + "to " + baseState.mAutofillViewId + " because view explicitly set"
20424                                 + " it to " + mAutofillId);
20425                     }
20426                 } else {
20427                     mAutofillViewId = baseState.mAutofillViewId;
20428                     mAutofillId = null; // will be set on demand by getAutofillId()
20429                 }
20430             }
20431         }
20432     }
20433 
20434     /**
20435      * <p>Return the time at which the drawing of the view hierarchy started.</p>
20436      *
20437      * @return the drawing start time in milliseconds
20438      */
getDrawingTime()20439     public long getDrawingTime() {
20440         return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
20441     }
20442 
20443     /**
20444      * <p>Enables or disables the duplication of the parent's state into this view. When
20445      * duplication is enabled, this view gets its drawable state from its parent rather
20446      * than from its own internal properties.</p>
20447      *
20448      * <p>Note: in the current implementation, setting this property to true after the
20449      * view was added to a ViewGroup might have no effect at all. This property should
20450      * always be used from XML or set to true before adding this view to a ViewGroup.</p>
20451      *
20452      * <p>Note: if this view's parent addStateFromChildren property is enabled and this
20453      * property is enabled, an exception will be thrown.</p>
20454      *
20455      * <p>Note: if the child view uses and updates additional states which are unknown to the
20456      * parent, these states should not be affected by this method.</p>
20457      *
20458      * @param enabled True to enable duplication of the parent's drawable state, false
20459      *                to disable it.
20460      *
20461      * @see #getDrawableState()
20462      * @see #isDuplicateParentStateEnabled()
20463      */
setDuplicateParentStateEnabled(boolean enabled)20464     public void setDuplicateParentStateEnabled(boolean enabled) {
20465         setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
20466     }
20467 
20468     /**
20469      * <p>Indicates whether this duplicates its drawable state from its parent.</p>
20470      *
20471      * @return True if this view's drawable state is duplicated from the parent,
20472      *         false otherwise
20473      *
20474      * @see #getDrawableState()
20475      * @see #setDuplicateParentStateEnabled(boolean)
20476      */
20477     @InspectableProperty(name = "duplicateParentState")
isDuplicateParentStateEnabled()20478     public boolean isDuplicateParentStateEnabled() {
20479         return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
20480     }
20481 
20482     /**
20483      * <p>Specifies the type of layer backing this view. The layer can be
20484      * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
20485      * {@link #LAYER_TYPE_HARDWARE}.</p>
20486      *
20487      * <p>A layer is associated with an optional {@link android.graphics.Paint}
20488      * instance that controls how the layer is composed on screen. The following
20489      * properties of the paint are taken into account when composing the layer:</p>
20490      * <ul>
20491      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
20492      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
20493      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
20494      * </ul>
20495      *
20496      * <p>If this view has an alpha value set to < 1.0 by calling
20497      * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
20498      * by this view's alpha value.</p>
20499      *
20500      * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
20501      * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
20502      * for more information on when and how to use layers.</p>
20503      *
20504      * @param layerType The type of layer to use with this view, must be one of
20505      *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
20506      *        {@link #LAYER_TYPE_HARDWARE}
20507      * @param paint The paint used to compose the layer. This argument is optional
20508      *        and can be null. It is ignored when the layer type is
20509      *        {@link #LAYER_TYPE_NONE}
20510      *
20511      * @see #getLayerType()
20512      * @see #LAYER_TYPE_NONE
20513      * @see #LAYER_TYPE_SOFTWARE
20514      * @see #LAYER_TYPE_HARDWARE
20515      * @see #setAlpha(float)
20516      *
20517      * @attr ref android.R.styleable#View_layerType
20518      */
setLayerType(@ayerType int layerType, @Nullable Paint paint)20519     public void setLayerType(@LayerType int layerType, @Nullable Paint paint) {
20520         if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
20521             throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
20522                     + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
20523         }
20524 
20525         boolean typeChanged = mRenderNode.setLayerType(layerType);
20526 
20527         if (!typeChanged) {
20528             setLayerPaint(paint);
20529             return;
20530         }
20531 
20532         if (layerType != LAYER_TYPE_SOFTWARE) {
20533             // Destroy any previous software drawing cache if present
20534             // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
20535             // drawing cache created in View#draw when drawing to a SW canvas.
20536             destroyDrawingCache();
20537         }
20538 
20539         mLayerType = layerType;
20540         mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
20541         mRenderNode.setLayerPaint(mLayerPaint);
20542 
20543         // draw() behaves differently if we are on a layer, so we need to
20544         // invalidate() here
20545         invalidateParentCaches();
20546         invalidate(true);
20547     }
20548 
20549     /**
20550      * Updates the {@link Paint} object used with the current layer (used only if the current
20551      * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
20552      * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
20553      * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
20554      * ensure that the view gets redrawn immediately.
20555      *
20556      * <p>A layer is associated with an optional {@link android.graphics.Paint}
20557      * instance that controls how the layer is composed on screen. The following
20558      * properties of the paint are taken into account when composing the layer:</p>
20559      * <ul>
20560      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
20561      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
20562      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
20563      * </ul>
20564      *
20565      * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
20566      * alpha value of the layer's paint is superseded by this view's alpha value.</p>
20567      *
20568      * @param paint The paint used to compose the layer. This argument is optional
20569      *        and can be null. It is ignored when the layer type is
20570      *        {@link #LAYER_TYPE_NONE}
20571      *
20572      * @see #setLayerType(int, android.graphics.Paint)
20573      */
setLayerPaint(@ullable Paint paint)20574     public void setLayerPaint(@Nullable Paint paint) {
20575         int layerType = getLayerType();
20576         if (layerType != LAYER_TYPE_NONE) {
20577             mLayerPaint = paint;
20578             if (layerType == LAYER_TYPE_HARDWARE) {
20579                 if (mRenderNode.setLayerPaint(paint)) {
20580                     invalidateViewProperty(false, false);
20581                 }
20582             } else {
20583                 invalidate();
20584             }
20585         }
20586     }
20587 
20588     /**
20589      * Indicates what type of layer is currently associated with this view. By default
20590      * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
20591      * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
20592      * for more information on the different types of layers.
20593      *
20594      * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
20595      *         {@link #LAYER_TYPE_HARDWARE}
20596      *
20597      * @see #setLayerType(int, android.graphics.Paint)
20598      * @see #buildLayer()
20599      * @see #LAYER_TYPE_NONE
20600      * @see #LAYER_TYPE_SOFTWARE
20601      * @see #LAYER_TYPE_HARDWARE
20602      */
20603     @InspectableProperty(enumMapping = {
20604             @EnumEntry(value = LAYER_TYPE_NONE, name = "none"),
20605             @EnumEntry(value = LAYER_TYPE_SOFTWARE, name = "software"),
20606             @EnumEntry(value = LAYER_TYPE_HARDWARE, name = "hardware")
20607     })
20608     @LayerType
getLayerType()20609     public int getLayerType() {
20610         return mLayerType;
20611     }
20612 
20613     /**
20614      * Forces this view's layer to be created and this view to be rendered
20615      * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
20616      * invoking this method will have no effect.
20617      *
20618      * This method can for instance be used to render a view into its layer before
20619      * starting an animation. If this view is complex, rendering into the layer
20620      * before starting the animation will avoid skipping frames.
20621      *
20622      * @throws IllegalStateException If this view is not attached to a window
20623      *
20624      * @see #setLayerType(int, android.graphics.Paint)
20625      */
buildLayer()20626     public void buildLayer() {
20627         if (mLayerType == LAYER_TYPE_NONE) return;
20628 
20629         final AttachInfo attachInfo = mAttachInfo;
20630         if (attachInfo == null) {
20631             throw new IllegalStateException("This view must be attached to a window first");
20632         }
20633 
20634         if (getWidth() == 0 || getHeight() == 0) {
20635             return;
20636         }
20637 
20638         switch (mLayerType) {
20639             case LAYER_TYPE_HARDWARE:
20640                 updateDisplayListIfDirty();
20641                 if (attachInfo.mThreadedRenderer != null && mRenderNode.hasDisplayList()) {
20642                     attachInfo.mThreadedRenderer.buildLayer(mRenderNode);
20643                 }
20644                 break;
20645             case LAYER_TYPE_SOFTWARE:
20646                 buildDrawingCache(true);
20647                 break;
20648         }
20649     }
20650 
20651     /**
20652      * Destroys all hardware rendering resources. This method is invoked
20653      * when the system needs to reclaim resources. Upon execution of this
20654      * method, you should free any OpenGL resources created by the view.
20655      *
20656      * Note: you <strong>must</strong> call
20657      * <code>super.destroyHardwareResources()</code> when overriding
20658      * this method.
20659      *
20660      * @hide
20661      */
20662     @CallSuper
20663     @UnsupportedAppUsage
destroyHardwareResources()20664     protected void destroyHardwareResources() {
20665         if (mOverlay != null) {
20666             mOverlay.getOverlayView().destroyHardwareResources();
20667         }
20668         if (mGhostView != null) {
20669             mGhostView.destroyHardwareResources();
20670         }
20671     }
20672 
20673     /**
20674      * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
20675      * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
20676      * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
20677      * the cache is enabled. To benefit from the cache, you must request the drawing cache by
20678      * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
20679      * null.</p>
20680      *
20681      * <p>Enabling the drawing cache is similar to
20682      * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
20683      * acceleration is turned off. When hardware acceleration is turned on, enabling the
20684      * drawing cache has no effect on rendering because the system uses a different mechanism
20685      * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
20686      * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
20687      * for information on how to enable software and hardware layers.</p>
20688      *
20689      * <p>This API can be used to manually generate
20690      * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
20691      * {@link #getDrawingCache()}.</p>
20692      *
20693      * @param enabled true to enable the drawing cache, false otherwise
20694      *
20695      * @see #isDrawingCacheEnabled()
20696      * @see #getDrawingCache()
20697      * @see #buildDrawingCache()
20698      * @see #setLayerType(int, android.graphics.Paint)
20699      *
20700      * @deprecated The view drawing cache was largely made obsolete with the introduction of
20701      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
20702      * layers are largely unnecessary and can easily result in a net loss in performance due to the
20703      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
20704      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
20705      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
20706      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
20707      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
20708      * software-rendered usages are discouraged and have compatibility issues with hardware-only
20709      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
20710      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
20711      * reports or unit testing the {@link PixelCopy} API is recommended.
20712      */
20713     @Deprecated
setDrawingCacheEnabled(boolean enabled)20714     public void setDrawingCacheEnabled(boolean enabled) {
20715         mCachingFailed = false;
20716         setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
20717     }
20718 
20719     /**
20720      * <p>Indicates whether the drawing cache is enabled for this view.</p>
20721      *
20722      * @return true if the drawing cache is enabled
20723      *
20724      * @see #setDrawingCacheEnabled(boolean)
20725      * @see #getDrawingCache()
20726      *
20727      * @deprecated The view drawing cache was largely made obsolete with the introduction of
20728      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
20729      * layers are largely unnecessary and can easily result in a net loss in performance due to the
20730      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
20731      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
20732      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
20733      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
20734      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
20735      * software-rendered usages are discouraged and have compatibility issues with hardware-only
20736      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
20737      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
20738      * reports or unit testing the {@link PixelCopy} API is recommended.
20739      */
20740     @Deprecated
20741     @ViewDebug.ExportedProperty(category = "drawing")
isDrawingCacheEnabled()20742     public boolean isDrawingCacheEnabled() {
20743         return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
20744     }
20745 
20746     /**
20747      * Debugging utility which recursively outputs the dirty state of a view and its
20748      * descendants.
20749      *
20750      * @hide
20751      */
20752     @SuppressWarnings({"UnusedDeclaration"})
outputDirtyFlags(String indent, boolean clear, int clearMask)20753     public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
20754         Log.d(VIEW_LOG_TAG, indent + this + "             DIRTY("
20755                 + (mPrivateFlags & View.PFLAG_DIRTY_MASK)
20756                 + ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID("
20757                 + (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID)
20758                 + ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
20759         if (clear) {
20760             mPrivateFlags &= clearMask;
20761         }
20762         if (this instanceof ViewGroup) {
20763             ViewGroup parent = (ViewGroup) this;
20764             final int count = parent.getChildCount();
20765             for (int i = 0; i < count; i++) {
20766                 final View child = parent.getChildAt(i);
20767                 child.outputDirtyFlags(indent + "  ", clear, clearMask);
20768             }
20769         }
20770     }
20771 
20772     /**
20773      * This method is used by ViewGroup to cause its children to restore or recreate their
20774      * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
20775      * to recreate its own display list, which would happen if it went through the normal
20776      * draw/dispatchDraw mechanisms.
20777      *
20778      * @hide
20779      */
dispatchGetDisplayList()20780     protected void dispatchGetDisplayList() {}
20781 
20782     /**
20783      * A view that is not attached or hardware accelerated cannot create a display list.
20784      * This method checks these conditions and returns the appropriate result.
20785      *
20786      * @return true if view has the ability to create a display list, false otherwise.
20787      *
20788      * @hide
20789      */
canHaveDisplayList()20790     public boolean canHaveDisplayList() {
20791         return !(mAttachInfo == null || mAttachInfo.mThreadedRenderer == null);
20792     }
20793 
20794     /**
20795      * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
20796      * @hide
20797      */
20798     @NonNull
20799     @UnsupportedAppUsage
updateDisplayListIfDirty()20800     public RenderNode updateDisplayListIfDirty() {
20801         final RenderNode renderNode = mRenderNode;
20802         if (!canHaveDisplayList()) {
20803             // can't populate RenderNode, don't try
20804             return renderNode;
20805         }
20806 
20807         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
20808                 || !renderNode.hasDisplayList()
20809                 || (mRecreateDisplayList)) {
20810             // Don't need to recreate the display list, just need to tell our
20811             // children to restore/recreate theirs
20812             if (renderNode.hasDisplayList()
20813                     && !mRecreateDisplayList) {
20814                 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
20815                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
20816                 dispatchGetDisplayList();
20817 
20818                 return renderNode; // no work needed
20819             }
20820 
20821             // If we got here, we're recreating it. Mark it as such to ensure that
20822             // we copy in child display lists into ours in drawChild()
20823             mRecreateDisplayList = true;
20824 
20825             int width = mRight - mLeft;
20826             int height = mBottom - mTop;
20827             int layerType = getLayerType();
20828 
20829             final RecordingCanvas canvas = renderNode.beginRecording(width, height);
20830 
20831             try {
20832                 if (layerType == LAYER_TYPE_SOFTWARE) {
20833                     buildDrawingCache(true);
20834                     Bitmap cache = getDrawingCache(true);
20835                     if (cache != null) {
20836                         canvas.drawBitmap(cache, 0, 0, mLayerPaint);
20837                     }
20838                 } else {
20839                     computeScroll();
20840 
20841                     canvas.translate(-mScrollX, -mScrollY);
20842                     mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
20843                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
20844 
20845                     // Fast path for layouts with no backgrounds
20846                     if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
20847                         dispatchDraw(canvas);
20848                         drawAutofilledHighlight(canvas);
20849                         if (mOverlay != null && !mOverlay.isEmpty()) {
20850                             mOverlay.getOverlayView().draw(canvas);
20851                         }
20852                         if (debugDraw()) {
20853                             debugDrawFocus(canvas);
20854                         }
20855                     } else {
20856                         draw(canvas);
20857                     }
20858                 }
20859             } finally {
20860                 renderNode.endRecording();
20861                 setDisplayListProperties(renderNode);
20862             }
20863         } else {
20864             mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
20865             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
20866         }
20867         return renderNode;
20868     }
20869 
20870     @UnsupportedAppUsage
resetDisplayList()20871     private void resetDisplayList() {
20872         mRenderNode.discardDisplayList();
20873         if (mBackgroundRenderNode != null) {
20874             mBackgroundRenderNode.discardDisplayList();
20875         }
20876     }
20877 
20878     /**
20879      * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
20880      *
20881      * @return A non-scaled bitmap representing this view or null if cache is disabled.
20882      *
20883      * @see #getDrawingCache(boolean)
20884      *
20885      * @deprecated The view drawing cache was largely made obsolete with the introduction of
20886      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
20887      * layers are largely unnecessary and can easily result in a net loss in performance due to the
20888      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
20889      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
20890      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
20891      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
20892      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
20893      * software-rendered usages are discouraged and have compatibility issues with hardware-only
20894      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
20895      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
20896      * reports or unit testing the {@link PixelCopy} API is recommended.
20897      */
20898     @Deprecated
getDrawingCache()20899     public Bitmap getDrawingCache() {
20900         return getDrawingCache(false);
20901     }
20902 
20903     /**
20904      * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
20905      * is null when caching is disabled. If caching is enabled and the cache is not ready,
20906      * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
20907      * draw from the cache when the cache is enabled. To benefit from the cache, you must
20908      * request the drawing cache by calling this method and draw it on screen if the
20909      * returned bitmap is not null.</p>
20910      *
20911      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
20912      * this method will create a bitmap of the same size as this view. Because this bitmap
20913      * will be drawn scaled by the parent ViewGroup, the result on screen might show
20914      * scaling artifacts. To avoid such artifacts, you should call this method by setting
20915      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
20916      * size than the view. This implies that your application must be able to handle this
20917      * size.</p>
20918      *
20919      * @param autoScale Indicates whether the generated bitmap should be scaled based on
20920      *        the current density of the screen when the application is in compatibility
20921      *        mode.
20922      *
20923      * @return A bitmap representing this view or null if cache is disabled.
20924      *
20925      * @see #setDrawingCacheEnabled(boolean)
20926      * @see #isDrawingCacheEnabled()
20927      * @see #buildDrawingCache(boolean)
20928      * @see #destroyDrawingCache()
20929      *
20930      * @deprecated The view drawing cache was largely made obsolete with the introduction of
20931      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
20932      * layers are largely unnecessary and can easily result in a net loss in performance due to the
20933      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
20934      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
20935      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
20936      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
20937      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
20938      * software-rendered usages are discouraged and have compatibility issues with hardware-only
20939      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
20940      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
20941      * reports or unit testing the {@link PixelCopy} API is recommended.
20942      */
20943     @Deprecated
getDrawingCache(boolean autoScale)20944     public Bitmap getDrawingCache(boolean autoScale) {
20945         if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
20946             return null;
20947         }
20948         if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
20949             buildDrawingCache(autoScale);
20950         }
20951         return autoScale ? mDrawingCache : mUnscaledDrawingCache;
20952     }
20953 
20954     /**
20955      * <p>Frees the resources used by the drawing cache. If you call
20956      * {@link #buildDrawingCache()} manually without calling
20957      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
20958      * should cleanup the cache with this method afterwards.</p>
20959      *
20960      * @see #setDrawingCacheEnabled(boolean)
20961      * @see #buildDrawingCache()
20962      * @see #getDrawingCache()
20963      *
20964      * @deprecated The view drawing cache was largely made obsolete with the introduction of
20965      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
20966      * layers are largely unnecessary and can easily result in a net loss in performance due to the
20967      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
20968      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
20969      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
20970      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
20971      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
20972      * software-rendered usages are discouraged and have compatibility issues with hardware-only
20973      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
20974      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
20975      * reports or unit testing the {@link PixelCopy} API is recommended.
20976      */
20977     @Deprecated
destroyDrawingCache()20978     public void destroyDrawingCache() {
20979         if (mDrawingCache != null) {
20980             mDrawingCache.recycle();
20981             mDrawingCache = null;
20982         }
20983         if (mUnscaledDrawingCache != null) {
20984             mUnscaledDrawingCache.recycle();
20985             mUnscaledDrawingCache = null;
20986         }
20987     }
20988 
20989     /**
20990      * Setting a solid background color for the drawing cache's bitmaps will improve
20991      * performance and memory usage. Note, though that this should only be used if this
20992      * view will always be drawn on top of a solid color.
20993      *
20994      * @param color The background color to use for the drawing cache's bitmap
20995      *
20996      * @see #setDrawingCacheEnabled(boolean)
20997      * @see #buildDrawingCache()
20998      * @see #getDrawingCache()
20999      *
21000      * @deprecated The view drawing cache was largely made obsolete with the introduction of
21001      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
21002      * layers are largely unnecessary and can easily result in a net loss in performance due to the
21003      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
21004      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
21005      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
21006      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
21007      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
21008      * software-rendered usages are discouraged and have compatibility issues with hardware-only
21009      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
21010      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
21011      * reports or unit testing the {@link PixelCopy} API is recommended.
21012      */
21013     @Deprecated
setDrawingCacheBackgroundColor(@olorInt int color)21014     public void setDrawingCacheBackgroundColor(@ColorInt int color) {
21015         if (color != mDrawingCacheBackgroundColor) {
21016             mDrawingCacheBackgroundColor = color;
21017             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
21018         }
21019     }
21020 
21021     /**
21022      * @see #setDrawingCacheBackgroundColor(int)
21023      *
21024      * @return The background color to used for the drawing cache's bitmap
21025      *
21026      * @deprecated The view drawing cache was largely made obsolete with the introduction of
21027      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
21028      * layers are largely unnecessary and can easily result in a net loss in performance due to the
21029      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
21030      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
21031      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
21032      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
21033      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
21034      * software-rendered usages are discouraged and have compatibility issues with hardware-only
21035      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
21036      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
21037      * reports or unit testing the {@link PixelCopy} API is recommended.
21038      */
21039     @Deprecated
21040     @ColorInt
getDrawingCacheBackgroundColor()21041     public int getDrawingCacheBackgroundColor() {
21042         return mDrawingCacheBackgroundColor;
21043     }
21044 
21045     /**
21046      * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
21047      *
21048      * @see #buildDrawingCache(boolean)
21049      *
21050      * @deprecated The view drawing cache was largely made obsolete with the introduction of
21051      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
21052      * layers are largely unnecessary and can easily result in a net loss in performance due to the
21053      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
21054      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
21055      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
21056      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
21057      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
21058      * software-rendered usages are discouraged and have compatibility issues with hardware-only
21059      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
21060      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
21061      * reports or unit testing the {@link PixelCopy} API is recommended.
21062      */
21063     @Deprecated
buildDrawingCache()21064     public void buildDrawingCache() {
21065         buildDrawingCache(false);
21066     }
21067 
21068     /**
21069      * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
21070      *
21071      * <p>If you call {@link #buildDrawingCache()} manually without calling
21072      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
21073      * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
21074      *
21075      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
21076      * this method will create a bitmap of the same size as this view. Because this bitmap
21077      * will be drawn scaled by the parent ViewGroup, the result on screen might show
21078      * scaling artifacts. To avoid such artifacts, you should call this method by setting
21079      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
21080      * size than the view. This implies that your application must be able to handle this
21081      * size.</p>
21082      *
21083      * <p>You should avoid calling this method when hardware acceleration is enabled. If
21084      * you do not need the drawing cache bitmap, calling this method will increase memory
21085      * usage and cause the view to be rendered in software once, thus negatively impacting
21086      * performance.</p>
21087      *
21088      * @see #getDrawingCache()
21089      * @see #destroyDrawingCache()
21090      *
21091      * @deprecated The view drawing cache was largely made obsolete with the introduction of
21092      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
21093      * layers are largely unnecessary and can easily result in a net loss in performance due to the
21094      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
21095      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
21096      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
21097      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
21098      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
21099      * software-rendered usages are discouraged and have compatibility issues with hardware-only
21100      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
21101      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
21102      * reports or unit testing the {@link PixelCopy} API is recommended.
21103      */
21104     @Deprecated
buildDrawingCache(boolean autoScale)21105     public void buildDrawingCache(boolean autoScale) {
21106         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
21107                 mDrawingCache == null : mUnscaledDrawingCache == null)) {
21108             if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
21109                 Trace.traceBegin(Trace.TRACE_TAG_VIEW,
21110                         "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
21111             }
21112             try {
21113                 buildDrawingCacheImpl(autoScale);
21114             } finally {
21115                 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
21116             }
21117         }
21118     }
21119 
21120     /**
21121      * private, internal implementation of buildDrawingCache, used to enable tracing
21122      */
buildDrawingCacheImpl(boolean autoScale)21123     private void buildDrawingCacheImpl(boolean autoScale) {
21124         mCachingFailed = false;
21125 
21126         int width = mRight - mLeft;
21127         int height = mBottom - mTop;
21128 
21129         final AttachInfo attachInfo = mAttachInfo;
21130         final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
21131 
21132         if (autoScale && scalingRequired) {
21133             width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
21134             height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
21135         }
21136 
21137         final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
21138         final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
21139         final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
21140 
21141         final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
21142         final long drawingCacheSize =
21143                 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
21144         if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
21145             if (width > 0 && height > 0) {
21146                 Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
21147                         + " too large to fit into a software layer (or drawing cache), needs "
21148                         + projectedBitmapSize + " bytes, only "
21149                         + drawingCacheSize + " available");
21150             }
21151             destroyDrawingCache();
21152             mCachingFailed = true;
21153             return;
21154         }
21155 
21156         boolean clear = true;
21157         Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
21158 
21159         if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
21160             Bitmap.Config quality;
21161             if (!opaque) {
21162                 // Never pick ARGB_4444 because it looks awful
21163                 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
21164                 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
21165                     case DRAWING_CACHE_QUALITY_AUTO:
21166                     case DRAWING_CACHE_QUALITY_LOW:
21167                     case DRAWING_CACHE_QUALITY_HIGH:
21168                     default:
21169                         quality = Bitmap.Config.ARGB_8888;
21170                         break;
21171                 }
21172             } else {
21173                 // Optimization for translucent windows
21174                 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
21175                 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
21176             }
21177 
21178             // Try to cleanup memory
21179             if (bitmap != null) bitmap.recycle();
21180 
21181             try {
21182                 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
21183                         width, height, quality);
21184                 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
21185                 if (autoScale) {
21186                     mDrawingCache = bitmap;
21187                 } else {
21188                     mUnscaledDrawingCache = bitmap;
21189                 }
21190                 if (opaque && use32BitCache) bitmap.setHasAlpha(false);
21191             } catch (OutOfMemoryError e) {
21192                 // If there is not enough memory to create the bitmap cache, just
21193                 // ignore the issue as bitmap caches are not required to draw the
21194                 // view hierarchy
21195                 if (autoScale) {
21196                     mDrawingCache = null;
21197                 } else {
21198                     mUnscaledDrawingCache = null;
21199                 }
21200                 mCachingFailed = true;
21201                 return;
21202             }
21203 
21204             clear = drawingCacheBackgroundColor != 0;
21205         }
21206 
21207         Canvas canvas;
21208         if (attachInfo != null) {
21209             canvas = attachInfo.mCanvas;
21210             if (canvas == null) {
21211                 canvas = new Canvas();
21212             }
21213             canvas.setBitmap(bitmap);
21214             // Temporarily clobber the cached Canvas in case one of our children
21215             // is also using a drawing cache. Without this, the children would
21216             // steal the canvas by attaching their own bitmap to it and bad, bad
21217             // thing would happen (invisible views, corrupted drawings, etc.)
21218             attachInfo.mCanvas = null;
21219         } else {
21220             // This case should hopefully never or seldom happen
21221             canvas = new Canvas(bitmap);
21222         }
21223 
21224         if (clear) {
21225             bitmap.eraseColor(drawingCacheBackgroundColor);
21226         }
21227 
21228         computeScroll();
21229         final int restoreCount = canvas.save();
21230 
21231         if (autoScale && scalingRequired) {
21232             final float scale = attachInfo.mApplicationScale;
21233             canvas.scale(scale, scale);
21234         }
21235 
21236         canvas.translate(-mScrollX, -mScrollY);
21237 
21238         mPrivateFlags |= PFLAG_DRAWN;
21239         if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
21240                 mLayerType != LAYER_TYPE_NONE) {
21241             mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
21242         }
21243 
21244         // Fast path for layouts with no backgrounds
21245         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
21246             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
21247             dispatchDraw(canvas);
21248             drawAutofilledHighlight(canvas);
21249             if (mOverlay != null && !mOverlay.isEmpty()) {
21250                 mOverlay.getOverlayView().draw(canvas);
21251             }
21252         } else {
21253             draw(canvas);
21254         }
21255 
21256         canvas.restoreToCount(restoreCount);
21257         canvas.setBitmap(null);
21258 
21259         if (attachInfo != null) {
21260             // Restore the cached Canvas for our siblings
21261             attachInfo.mCanvas = canvas;
21262         }
21263     }
21264 
21265     /**
21266      * Create a snapshot of the view into a bitmap.  We should probably make
21267      * some form of this public, but should think about the API.
21268      *
21269      * @hide
21270      */
21271     @UnsupportedAppUsage
createSnapshot(ViewDebug.CanvasProvider canvasProvider, boolean skipChildren)21272     public Bitmap createSnapshot(ViewDebug.CanvasProvider canvasProvider, boolean skipChildren) {
21273         int width = mRight - mLeft;
21274         int height = mBottom - mTop;
21275 
21276         final AttachInfo attachInfo = mAttachInfo;
21277         final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
21278         width = (int) ((width * scale) + 0.5f);
21279         height = (int) ((height * scale) + 0.5f);
21280 
21281         Canvas oldCanvas = null;
21282         try {
21283             Canvas canvas = canvasProvider.getCanvas(this,
21284                     width > 0 ? width : 1, height > 0 ? height : 1);
21285 
21286             if (attachInfo != null) {
21287                 oldCanvas = attachInfo.mCanvas;
21288                 // Temporarily clobber the cached Canvas in case one of our children
21289                 // is also using a drawing cache. Without this, the children would
21290                 // steal the canvas by attaching their own bitmap to it and bad, bad
21291                 // things would happen (invisible views, corrupted drawings, etc.)
21292                 attachInfo.mCanvas = null;
21293             }
21294 
21295             computeScroll();
21296             final int restoreCount = canvas.save();
21297             canvas.scale(scale, scale);
21298             canvas.translate(-mScrollX, -mScrollY);
21299 
21300             // Temporarily remove the dirty mask
21301             int flags = mPrivateFlags;
21302             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
21303 
21304             // Fast path for layouts with no backgrounds
21305             if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
21306                 dispatchDraw(canvas);
21307                 drawAutofilledHighlight(canvas);
21308                 if (mOverlay != null && !mOverlay.isEmpty()) {
21309                     mOverlay.getOverlayView().draw(canvas);
21310                 }
21311             } else {
21312                 draw(canvas);
21313             }
21314 
21315             mPrivateFlags = flags;
21316             canvas.restoreToCount(restoreCount);
21317             return canvasProvider.createBitmap();
21318         } finally {
21319             if (oldCanvas != null) {
21320                 attachInfo.mCanvas = oldCanvas;
21321             }
21322         }
21323     }
21324 
21325     /**
21326      * Indicates whether this View is currently in edit mode. A View is usually
21327      * in edit mode when displayed within a developer tool. For instance, if
21328      * this View is being drawn by a visual user interface builder, this method
21329      * should return true.
21330      *
21331      * Subclasses should check the return value of this method to provide
21332      * different behaviors if their normal behavior might interfere with the
21333      * host environment. For instance: the class spawns a thread in its
21334      * constructor, the drawing code relies on device-specific features, etc.
21335      *
21336      * This method is usually checked in the drawing code of custom widgets.
21337      *
21338      * @return True if this View is in edit mode, false otherwise.
21339      */
isInEditMode()21340     public boolean isInEditMode() {
21341         return false;
21342     }
21343 
21344     /**
21345      * If the View draws content inside its padding and enables fading edges,
21346      * it needs to support padding offsets. Padding offsets are added to the
21347      * fading edges to extend the length of the fade so that it covers pixels
21348      * drawn inside the padding.
21349      *
21350      * Subclasses of this class should override this method if they need
21351      * to draw content inside the padding.
21352      *
21353      * @return True if padding offset must be applied, false otherwise.
21354      *
21355      * @see #getLeftPaddingOffset()
21356      * @see #getRightPaddingOffset()
21357      * @see #getTopPaddingOffset()
21358      * @see #getBottomPaddingOffset()
21359      *
21360      * @since CURRENT
21361      */
isPaddingOffsetRequired()21362     protected boolean isPaddingOffsetRequired() {
21363         return false;
21364     }
21365 
21366     /**
21367      * Amount by which to extend the left fading region. Called only when
21368      * {@link #isPaddingOffsetRequired()} returns true.
21369      *
21370      * @return The left padding offset in pixels.
21371      *
21372      * @see #isPaddingOffsetRequired()
21373      *
21374      * @since CURRENT
21375      */
getLeftPaddingOffset()21376     protected int getLeftPaddingOffset() {
21377         return 0;
21378     }
21379 
21380     /**
21381      * Amount by which to extend the right fading region. Called only when
21382      * {@link #isPaddingOffsetRequired()} returns true.
21383      *
21384      * @return The right padding offset in pixels.
21385      *
21386      * @see #isPaddingOffsetRequired()
21387      *
21388      * @since CURRENT
21389      */
getRightPaddingOffset()21390     protected int getRightPaddingOffset() {
21391         return 0;
21392     }
21393 
21394     /**
21395      * Amount by which to extend the top fading region. Called only when
21396      * {@link #isPaddingOffsetRequired()} returns true.
21397      *
21398      * @return The top padding offset in pixels.
21399      *
21400      * @see #isPaddingOffsetRequired()
21401      *
21402      * @since CURRENT
21403      */
getTopPaddingOffset()21404     protected int getTopPaddingOffset() {
21405         return 0;
21406     }
21407 
21408     /**
21409      * Amount by which to extend the bottom fading region. Called only when
21410      * {@link #isPaddingOffsetRequired()} returns true.
21411      *
21412      * @return The bottom padding offset in pixels.
21413      *
21414      * @see #isPaddingOffsetRequired()
21415      *
21416      * @since CURRENT
21417      */
getBottomPaddingOffset()21418     protected int getBottomPaddingOffset() {
21419         return 0;
21420     }
21421 
21422     /**
21423      * @hide
21424      * @param offsetRequired
21425      */
getFadeTop(boolean offsetRequired)21426     protected int getFadeTop(boolean offsetRequired) {
21427         int top = mPaddingTop;
21428         if (offsetRequired) top += getTopPaddingOffset();
21429         return top;
21430     }
21431 
21432     /**
21433      * @hide
21434      * @param offsetRequired
21435      */
getFadeHeight(boolean offsetRequired)21436     protected int getFadeHeight(boolean offsetRequired) {
21437         int padding = mPaddingTop;
21438         if (offsetRequired) padding += getTopPaddingOffset();
21439         return mBottom - mTop - mPaddingBottom - padding;
21440     }
21441 
21442     /**
21443      * <p>Indicates whether this view is attached to a hardware accelerated
21444      * window or not.</p>
21445      *
21446      * <p>Even if this method returns true, it does not mean that every call
21447      * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
21448      * accelerated {@link android.graphics.Canvas}. For instance, if this view
21449      * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
21450      * window is hardware accelerated,
21451      * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
21452      * return false, and this method will return true.</p>
21453      *
21454      * @return True if the view is attached to a window and the window is
21455      *         hardware accelerated; false in any other case.
21456      */
21457     @ViewDebug.ExportedProperty(category = "drawing")
isHardwareAccelerated()21458     public boolean isHardwareAccelerated() {
21459         return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
21460     }
21461 
21462     /**
21463      * Sets a rectangular area on this view to which the view will be clipped
21464      * when it is drawn. Setting the value to null will remove the clip bounds
21465      * and the view will draw normally, using its full bounds.
21466      *
21467      * @param clipBounds The rectangular area, in the local coordinates of
21468      * this view, to which future drawing operations will be clipped.
21469      */
setClipBounds(Rect clipBounds)21470     public void setClipBounds(Rect clipBounds) {
21471         if (clipBounds == mClipBounds
21472                 || (clipBounds != null && clipBounds.equals(mClipBounds))) {
21473             return;
21474         }
21475         if (clipBounds != null) {
21476             if (mClipBounds == null) {
21477                 mClipBounds = new Rect(clipBounds);
21478             } else {
21479                 mClipBounds.set(clipBounds);
21480             }
21481         } else {
21482             mClipBounds = null;
21483         }
21484         mRenderNode.setClipRect(mClipBounds);
21485         invalidateViewProperty(false, false);
21486     }
21487 
21488     /**
21489      * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
21490      *
21491      * @return A copy of the current clip bounds if clip bounds are set,
21492      * otherwise null.
21493      */
getClipBounds()21494     public Rect getClipBounds() {
21495         return (mClipBounds != null) ? new Rect(mClipBounds) : null;
21496     }
21497 
21498 
21499     /**
21500      * Populates an output rectangle with the clip bounds of the view,
21501      * returning {@code true} if successful or {@code false} if the view's
21502      * clip bounds are {@code null}.
21503      *
21504      * @param outRect rectangle in which to place the clip bounds of the view
21505      * @return {@code true} if successful or {@code false} if the view's
21506      *         clip bounds are {@code null}
21507      */
getClipBounds(Rect outRect)21508     public boolean getClipBounds(Rect outRect) {
21509         if (mClipBounds != null) {
21510             outRect.set(mClipBounds);
21511             return true;
21512         }
21513         return false;
21514     }
21515 
21516     /**
21517      * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
21518      * case of an active Animation being run on the view.
21519      */
applyLegacyAnimation(ViewGroup parent, long drawingTime, Animation a, boolean scalingRequired)21520     private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
21521             Animation a, boolean scalingRequired) {
21522         Transformation invalidationTransform;
21523         final int flags = parent.mGroupFlags;
21524         final boolean initialized = a.isInitialized();
21525         if (!initialized) {
21526             a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
21527             a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
21528             if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
21529             onAnimationStart();
21530         }
21531 
21532         final Transformation t = parent.getChildTransformation();
21533         boolean more = a.getTransformation(drawingTime, t, 1f);
21534         if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
21535             if (parent.mInvalidationTransformation == null) {
21536                 parent.mInvalidationTransformation = new Transformation();
21537             }
21538             invalidationTransform = parent.mInvalidationTransformation;
21539             a.getTransformation(drawingTime, invalidationTransform, 1f);
21540         } else {
21541             invalidationTransform = t;
21542         }
21543 
21544         if (more) {
21545             if (!a.willChangeBounds()) {
21546                 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
21547                         ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
21548                     parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
21549                 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
21550                     // The child need to draw an animation, potentially offscreen, so
21551                     // make sure we do not cancel invalidate requests
21552                     parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
21553                     parent.invalidate(mLeft, mTop, mRight, mBottom);
21554                 }
21555             } else {
21556                 if (parent.mInvalidateRegion == null) {
21557                     parent.mInvalidateRegion = new RectF();
21558                 }
21559                 final RectF region = parent.mInvalidateRegion;
21560                 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
21561                         invalidationTransform);
21562 
21563                 // The child need to draw an animation, potentially offscreen, so
21564                 // make sure we do not cancel invalidate requests
21565                 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
21566 
21567                 final int left = mLeft + (int) region.left;
21568                 final int top = mTop + (int) region.top;
21569                 parent.invalidate(left, top, left + (int) (region.width() + .5f),
21570                         top + (int) (region.height() + .5f));
21571             }
21572         }
21573         return more;
21574     }
21575 
21576     /**
21577      * This method is called by getDisplayList() when a display list is recorded for a View.
21578      * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
21579      */
setDisplayListProperties(RenderNode renderNode)21580     void setDisplayListProperties(RenderNode renderNode) {
21581         if (renderNode != null) {
21582             renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
21583             renderNode.setClipToBounds(mParent instanceof ViewGroup
21584                     && ((ViewGroup) mParent).getClipChildren());
21585 
21586             float alpha = 1;
21587             if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
21588                     ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
21589                 ViewGroup parentVG = (ViewGroup) mParent;
21590                 final Transformation t = parentVG.getChildTransformation();
21591                 if (parentVG.getChildStaticTransformation(this, t)) {
21592                     final int transformType = t.getTransformationType();
21593                     if (transformType != Transformation.TYPE_IDENTITY) {
21594                         if ((transformType & Transformation.TYPE_ALPHA) != 0) {
21595                             alpha = t.getAlpha();
21596                         }
21597                         if ((transformType & Transformation.TYPE_MATRIX) != 0) {
21598                             renderNode.setStaticMatrix(t.getMatrix());
21599                         }
21600                     }
21601                 }
21602             }
21603             if (mTransformationInfo != null) {
21604                 alpha *= getFinalAlpha();
21605                 if (alpha < 1) {
21606                     final int multipliedAlpha = (int) (255 * alpha);
21607                     if (onSetAlpha(multipliedAlpha)) {
21608                         alpha = 1;
21609                     }
21610                 }
21611                 renderNode.setAlpha(alpha);
21612             } else if (alpha < 1) {
21613                 renderNode.setAlpha(alpha);
21614             }
21615         }
21616     }
21617 
21618     /**
21619      * This method is called by ViewGroup.drawChild() to have each child view draw itself.
21620      *
21621      * This is where the View specializes rendering behavior based on layer type,
21622      * and hardware acceleration.
21623      */
draw(Canvas canvas, ViewGroup parent, long drawingTime)21624     boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
21625         final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
21626         /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
21627          *
21628          * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
21629          * HW accelerated, it can't handle drawing RenderNodes.
21630          */
21631         boolean drawingWithRenderNode = mAttachInfo != null
21632                 && mAttachInfo.mHardwareAccelerated
21633                 && hardwareAcceleratedCanvas;
21634 
21635         boolean more = false;
21636         final boolean childHasIdentityMatrix = hasIdentityMatrix();
21637         final int parentFlags = parent.mGroupFlags;
21638 
21639         if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
21640             parent.getChildTransformation().clear();
21641             parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
21642         }
21643 
21644         Transformation transformToApply = null;
21645         boolean concatMatrix = false;
21646         final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
21647         final Animation a = getAnimation();
21648         if (a != null) {
21649             more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
21650             concatMatrix = a.willChangeTransformationMatrix();
21651             if (concatMatrix) {
21652                 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
21653             }
21654             transformToApply = parent.getChildTransformation();
21655         } else {
21656             if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
21657                 // No longer animating: clear out old animation matrix
21658                 mRenderNode.setAnimationMatrix(null);
21659                 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
21660             }
21661             if (!drawingWithRenderNode
21662                     && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
21663                 final Transformation t = parent.getChildTransformation();
21664                 final boolean hasTransform = parent.getChildStaticTransformation(this, t);
21665                 if (hasTransform) {
21666                     final int transformType = t.getTransformationType();
21667                     transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
21668                     concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
21669                 }
21670             }
21671         }
21672 
21673         concatMatrix |= !childHasIdentityMatrix;
21674 
21675         // Sets the flag as early as possible to allow draw() implementations
21676         // to call invalidate() successfully when doing animations
21677         mPrivateFlags |= PFLAG_DRAWN;
21678 
21679         if (!concatMatrix &&
21680                 (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
21681                         ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
21682                 canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
21683                 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
21684             mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
21685             return more;
21686         }
21687         mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
21688 
21689         if (hardwareAcceleratedCanvas) {
21690             // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
21691             // retain the flag's value temporarily in the mRecreateDisplayList flag
21692             mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
21693             mPrivateFlags &= ~PFLAG_INVALIDATED;
21694         }
21695 
21696         RenderNode renderNode = null;
21697         Bitmap cache = null;
21698         int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
21699         if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
21700              if (layerType != LAYER_TYPE_NONE) {
21701                  // If not drawing with RenderNode, treat HW layers as SW
21702                  layerType = LAYER_TYPE_SOFTWARE;
21703                  buildDrawingCache(true);
21704             }
21705             cache = getDrawingCache(true);
21706         }
21707 
21708         if (drawingWithRenderNode) {
21709             // Delay getting the display list until animation-driven alpha values are
21710             // set up and possibly passed on to the view
21711             renderNode = updateDisplayListIfDirty();
21712             if (!renderNode.hasDisplayList()) {
21713                 // Uncommon, but possible. If a view is removed from the hierarchy during the call
21714                 // to getDisplayList(), the display list will be marked invalid and we should not
21715                 // try to use it again.
21716                 renderNode = null;
21717                 drawingWithRenderNode = false;
21718             }
21719         }
21720 
21721         int sx = 0;
21722         int sy = 0;
21723         if (!drawingWithRenderNode) {
21724             computeScroll();
21725             sx = mScrollX;
21726             sy = mScrollY;
21727         }
21728 
21729         final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
21730         final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
21731 
21732         int restoreTo = -1;
21733         if (!drawingWithRenderNode || transformToApply != null) {
21734             restoreTo = canvas.save();
21735         }
21736         if (offsetForScroll) {
21737             canvas.translate(mLeft - sx, mTop - sy);
21738         } else {
21739             if (!drawingWithRenderNode) {
21740                 canvas.translate(mLeft, mTop);
21741             }
21742             if (scalingRequired) {
21743                 if (drawingWithRenderNode) {
21744                     // TODO: Might not need this if we put everything inside the DL
21745                     restoreTo = canvas.save();
21746                 }
21747                 // mAttachInfo cannot be null, otherwise scalingRequired == false
21748                 final float scale = 1.0f / mAttachInfo.mApplicationScale;
21749                 canvas.scale(scale, scale);
21750             }
21751         }
21752 
21753         float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
21754         if (transformToApply != null
21755                 || alpha < 1
21756                 || !hasIdentityMatrix()
21757                 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
21758             if (transformToApply != null || !childHasIdentityMatrix) {
21759                 int transX = 0;
21760                 int transY = 0;
21761 
21762                 if (offsetForScroll) {
21763                     transX = -sx;
21764                     transY = -sy;
21765                 }
21766 
21767                 if (transformToApply != null) {
21768                     if (concatMatrix) {
21769                         if (drawingWithRenderNode) {
21770                             renderNode.setAnimationMatrix(transformToApply.getMatrix());
21771                         } else {
21772                             // Undo the scroll translation, apply the transformation matrix,
21773                             // then redo the scroll translate to get the correct result.
21774                             canvas.translate(-transX, -transY);
21775                             canvas.concat(transformToApply.getMatrix());
21776                             canvas.translate(transX, transY);
21777                         }
21778                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
21779                     }
21780 
21781                     float transformAlpha = transformToApply.getAlpha();
21782                     if (transformAlpha < 1) {
21783                         alpha *= transformAlpha;
21784                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
21785                     }
21786                 }
21787 
21788                 if (!childHasIdentityMatrix && !drawingWithRenderNode) {
21789                     canvas.translate(-transX, -transY);
21790                     canvas.concat(getMatrix());
21791                     canvas.translate(transX, transY);
21792                 }
21793             }
21794 
21795             // Deal with alpha if it is or used to be <1
21796             if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
21797                 if (alpha < 1) {
21798                     mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
21799                 } else {
21800                     mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
21801                 }
21802                 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
21803                 if (!drawingWithDrawingCache) {
21804                     final int multipliedAlpha = (int) (255 * alpha);
21805                     if (!onSetAlpha(multipliedAlpha)) {
21806                         if (drawingWithRenderNode) {
21807                             renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
21808                         } else if (layerType == LAYER_TYPE_NONE) {
21809                             canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
21810                                     multipliedAlpha);
21811                         }
21812                     } else {
21813                         // Alpha is handled by the child directly, clobber the layer's alpha
21814                         mPrivateFlags |= PFLAG_ALPHA_SET;
21815                     }
21816                 }
21817             }
21818         } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
21819             onSetAlpha(255);
21820             mPrivateFlags &= ~PFLAG_ALPHA_SET;
21821         }
21822 
21823         if (!drawingWithRenderNode) {
21824             // apply clips directly, since RenderNode won't do it for this draw
21825             if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
21826                 if (offsetForScroll) {
21827                     canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
21828                 } else {
21829                     if (!scalingRequired || cache == null) {
21830                         canvas.clipRect(0, 0, getWidth(), getHeight());
21831                     } else {
21832                         canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
21833                     }
21834                 }
21835             }
21836 
21837             if (mClipBounds != null) {
21838                 // clip bounds ignore scroll
21839                 canvas.clipRect(mClipBounds);
21840             }
21841         }
21842 
21843         if (!drawingWithDrawingCache) {
21844             if (drawingWithRenderNode) {
21845                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
21846                 ((RecordingCanvas) canvas).drawRenderNode(renderNode);
21847             } else {
21848                 // Fast path for layouts with no backgrounds
21849                 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
21850                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
21851                     dispatchDraw(canvas);
21852                 } else {
21853                     draw(canvas);
21854                 }
21855             }
21856         } else if (cache != null) {
21857             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
21858             if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
21859                 // no layer paint, use temporary paint to draw bitmap
21860                 Paint cachePaint = parent.mCachePaint;
21861                 if (cachePaint == null) {
21862                     cachePaint = new Paint();
21863                     cachePaint.setDither(false);
21864                     parent.mCachePaint = cachePaint;
21865                 }
21866                 cachePaint.setAlpha((int) (alpha * 255));
21867                 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
21868             } else {
21869                 // use layer paint to draw the bitmap, merging the two alphas, but also restore
21870                 int layerPaintAlpha = mLayerPaint.getAlpha();
21871                 if (alpha < 1) {
21872                     mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
21873                 }
21874                 canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
21875                 if (alpha < 1) {
21876                     mLayerPaint.setAlpha(layerPaintAlpha);
21877                 }
21878             }
21879         }
21880 
21881         if (restoreTo >= 0) {
21882             canvas.restoreToCount(restoreTo);
21883         }
21884 
21885         if (a != null && !more) {
21886             if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
21887                 onSetAlpha(255);
21888             }
21889             parent.finishAnimatingView(this, a);
21890         }
21891 
21892         if (more && hardwareAcceleratedCanvas) {
21893             if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
21894                 // alpha animations should cause the child to recreate its display list
21895                 invalidate(true);
21896             }
21897         }
21898 
21899         mRecreateDisplayList = false;
21900 
21901         return more;
21902     }
21903 
getDebugPaint()21904     static Paint getDebugPaint() {
21905         if (sDebugPaint == null) {
21906             sDebugPaint = new Paint();
21907             sDebugPaint.setAntiAlias(false);
21908         }
21909         return sDebugPaint;
21910     }
21911 
dipsToPixels(int dips)21912     final int dipsToPixels(int dips) {
21913         float scale = getContext().getResources().getDisplayMetrics().density;
21914         return (int) (dips * scale + 0.5f);
21915     }
21916 
debugDrawFocus(Canvas canvas)21917     final private void debugDrawFocus(Canvas canvas) {
21918         if (isFocused()) {
21919             final int cornerSquareSize = dipsToPixels(DEBUG_CORNERS_SIZE_DIP);
21920             final int l = mScrollX;
21921             final int r = l + mRight - mLeft;
21922             final int t = mScrollY;
21923             final int b = t + mBottom - mTop;
21924 
21925             final Paint paint = getDebugPaint();
21926             paint.setColor(DEBUG_CORNERS_COLOR);
21927 
21928             // Draw squares in corners.
21929             paint.setStyle(Paint.Style.FILL);
21930             canvas.drawRect(l, t, l + cornerSquareSize, t + cornerSquareSize, paint);
21931             canvas.drawRect(r - cornerSquareSize, t, r, t + cornerSquareSize, paint);
21932             canvas.drawRect(l, b - cornerSquareSize, l + cornerSquareSize, b, paint);
21933             canvas.drawRect(r - cornerSquareSize, b - cornerSquareSize, r, b, paint);
21934 
21935             // Draw big X across the view.
21936             paint.setStyle(Paint.Style.STROKE);
21937             canvas.drawLine(l, t, r, b, paint);
21938             canvas.drawLine(l, b, r, t, paint);
21939         }
21940     }
21941 
21942     /**
21943      * Manually render this view (and all of its children) to the given Canvas.
21944      * The view must have already done a full layout before this function is
21945      * called.  When implementing a view, implement
21946      * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
21947      * If you do need to override this method, call the superclass version.
21948      *
21949      * @param canvas The Canvas to which the View is rendered.
21950      */
21951     @CallSuper
draw(Canvas canvas)21952     public void draw(Canvas canvas) {
21953         final int privateFlags = mPrivateFlags;
21954         mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
21955 
21956         /*
21957          * Draw traversal performs several drawing steps which must be executed
21958          * in the appropriate order:
21959          *
21960          *      1. Draw the background
21961          *      2. If necessary, save the canvas' layers to prepare for fading
21962          *      3. Draw view's content
21963          *      4. Draw children
21964          *      5. If necessary, draw the fading edges and restore layers
21965          *      6. Draw decorations (scrollbars for instance)
21966          */
21967 
21968         // Step 1, draw the background, if needed
21969         int saveCount;
21970 
21971         drawBackground(canvas);
21972 
21973         // skip step 2 & 5 if possible (common case)
21974         final int viewFlags = mViewFlags;
21975         boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
21976         boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
21977         if (!verticalEdges && !horizontalEdges) {
21978             // Step 3, draw the content
21979             onDraw(canvas);
21980 
21981             // Step 4, draw the children
21982             dispatchDraw(canvas);
21983 
21984             drawAutofilledHighlight(canvas);
21985 
21986             // Overlay is part of the content and draws beneath Foreground
21987             if (mOverlay != null && !mOverlay.isEmpty()) {
21988                 mOverlay.getOverlayView().dispatchDraw(canvas);
21989             }
21990 
21991             // Step 6, draw decorations (foreground, scrollbars)
21992             onDrawForeground(canvas);
21993 
21994             // Step 7, draw the default focus highlight
21995             drawDefaultFocusHighlight(canvas);
21996 
21997             if (debugDraw()) {
21998                 debugDrawFocus(canvas);
21999             }
22000 
22001             // we're done...
22002             return;
22003         }
22004 
22005         /*
22006          * Here we do the full fledged routine...
22007          * (this is an uncommon case where speed matters less,
22008          * this is why we repeat some of the tests that have been
22009          * done above)
22010          */
22011 
22012         boolean drawTop = false;
22013         boolean drawBottom = false;
22014         boolean drawLeft = false;
22015         boolean drawRight = false;
22016 
22017         float topFadeStrength = 0.0f;
22018         float bottomFadeStrength = 0.0f;
22019         float leftFadeStrength = 0.0f;
22020         float rightFadeStrength = 0.0f;
22021 
22022         // Step 2, save the canvas' layers
22023         int paddingLeft = mPaddingLeft;
22024 
22025         final boolean offsetRequired = isPaddingOffsetRequired();
22026         if (offsetRequired) {
22027             paddingLeft += getLeftPaddingOffset();
22028         }
22029 
22030         int left = mScrollX + paddingLeft;
22031         int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
22032         int top = mScrollY + getFadeTop(offsetRequired);
22033         int bottom = top + getFadeHeight(offsetRequired);
22034 
22035         if (offsetRequired) {
22036             right += getRightPaddingOffset();
22037             bottom += getBottomPaddingOffset();
22038         }
22039 
22040         final ScrollabilityCache scrollabilityCache = mScrollCache;
22041         final float fadeHeight = scrollabilityCache.fadingEdgeLength;
22042         int length = (int) fadeHeight;
22043 
22044         // clip the fade length if top and bottom fades overlap
22045         // overlapping fades produce odd-looking artifacts
22046         if (verticalEdges && (top + length > bottom - length)) {
22047             length = (bottom - top) / 2;
22048         }
22049 
22050         // also clip horizontal fades if necessary
22051         if (horizontalEdges && (left + length > right - length)) {
22052             length = (right - left) / 2;
22053         }
22054 
22055         if (verticalEdges) {
22056             topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
22057             drawTop = topFadeStrength * fadeHeight > 1.0f;
22058             bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
22059             drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
22060         }
22061 
22062         if (horizontalEdges) {
22063             leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
22064             drawLeft = leftFadeStrength * fadeHeight > 1.0f;
22065             rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
22066             drawRight = rightFadeStrength * fadeHeight > 1.0f;
22067         }
22068 
22069         saveCount = canvas.getSaveCount();
22070         int topSaveCount = -1;
22071         int bottomSaveCount = -1;
22072         int leftSaveCount = -1;
22073         int rightSaveCount = -1;
22074 
22075         int solidColor = getSolidColor();
22076         if (solidColor == 0) {
22077             if (drawTop) {
22078                 topSaveCount = canvas.saveUnclippedLayer(left, top, right, top + length);
22079             }
22080 
22081             if (drawBottom) {
22082                 bottomSaveCount = canvas.saveUnclippedLayer(left, bottom - length, right, bottom);
22083             }
22084 
22085             if (drawLeft) {
22086                 leftSaveCount = canvas.saveUnclippedLayer(left, top, left + length, bottom);
22087             }
22088 
22089             if (drawRight) {
22090                 rightSaveCount = canvas.saveUnclippedLayer(right - length, top, right, bottom);
22091             }
22092         } else {
22093             scrollabilityCache.setFadeColor(solidColor);
22094         }
22095 
22096         // Step 3, draw the content
22097         onDraw(canvas);
22098 
22099         // Step 4, draw the children
22100         dispatchDraw(canvas);
22101 
22102         // Step 5, draw the fade effect and restore layers
22103         final Paint p = scrollabilityCache.paint;
22104         final Matrix matrix = scrollabilityCache.matrix;
22105         final Shader fade = scrollabilityCache.shader;
22106 
22107         // must be restored in the reverse order that they were saved
22108         if (drawRight) {
22109             matrix.setScale(1, fadeHeight * rightFadeStrength);
22110             matrix.postRotate(90);
22111             matrix.postTranslate(right, top);
22112             fade.setLocalMatrix(matrix);
22113             p.setShader(fade);
22114             if (solidColor == 0) {
22115                 canvas.restoreUnclippedLayer(rightSaveCount, p);
22116 
22117             } else {
22118                 canvas.drawRect(right - length, top, right, bottom, p);
22119             }
22120         }
22121 
22122         if (drawLeft) {
22123             matrix.setScale(1, fadeHeight * leftFadeStrength);
22124             matrix.postRotate(-90);
22125             matrix.postTranslate(left, top);
22126             fade.setLocalMatrix(matrix);
22127             p.setShader(fade);
22128             if (solidColor == 0) {
22129                 canvas.restoreUnclippedLayer(leftSaveCount, p);
22130             } else {
22131                 canvas.drawRect(left, top, left + length, bottom, p);
22132             }
22133         }
22134 
22135         if (drawBottom) {
22136             matrix.setScale(1, fadeHeight * bottomFadeStrength);
22137             matrix.postRotate(180);
22138             matrix.postTranslate(left, bottom);
22139             fade.setLocalMatrix(matrix);
22140             p.setShader(fade);
22141             if (solidColor == 0) {
22142                 canvas.restoreUnclippedLayer(bottomSaveCount, p);
22143             } else {
22144                 canvas.drawRect(left, bottom - length, right, bottom, p);
22145             }
22146         }
22147 
22148         if (drawTop) {
22149             matrix.setScale(1, fadeHeight * topFadeStrength);
22150             matrix.postTranslate(left, top);
22151             fade.setLocalMatrix(matrix);
22152             p.setShader(fade);
22153             if (solidColor == 0) {
22154                 canvas.restoreUnclippedLayer(topSaveCount, p);
22155             } else {
22156                 canvas.drawRect(left, top, right, top + length, p);
22157             }
22158         }
22159 
22160         canvas.restoreToCount(saveCount);
22161 
22162         drawAutofilledHighlight(canvas);
22163 
22164         // Overlay is part of the content and draws beneath Foreground
22165         if (mOverlay != null && !mOverlay.isEmpty()) {
22166             mOverlay.getOverlayView().dispatchDraw(canvas);
22167         }
22168 
22169         // Step 6, draw decorations (foreground, scrollbars)
22170         onDrawForeground(canvas);
22171 
22172         if (debugDraw()) {
22173             debugDrawFocus(canvas);
22174         }
22175     }
22176 
22177     /**
22178      * Draws the background onto the specified canvas.
22179      *
22180      * @param canvas Canvas on which to draw the background
22181      */
22182     @UnsupportedAppUsage
drawBackground(Canvas canvas)22183     private void drawBackground(Canvas canvas) {
22184         final Drawable background = mBackground;
22185         if (background == null) {
22186             return;
22187         }
22188 
22189         setBackgroundBounds();
22190 
22191         // Attempt to use a display list if requested.
22192         if (canvas.isHardwareAccelerated() && mAttachInfo != null
22193                 && mAttachInfo.mThreadedRenderer != null) {
22194             mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
22195 
22196             final RenderNode renderNode = mBackgroundRenderNode;
22197             if (renderNode != null && renderNode.hasDisplayList()) {
22198                 setBackgroundRenderNodeProperties(renderNode);
22199                 ((RecordingCanvas) canvas).drawRenderNode(renderNode);
22200                 return;
22201             }
22202         }
22203 
22204         final int scrollX = mScrollX;
22205         final int scrollY = mScrollY;
22206         if ((scrollX | scrollY) == 0) {
22207             background.draw(canvas);
22208         } else {
22209             canvas.translate(scrollX, scrollY);
22210             background.draw(canvas);
22211             canvas.translate(-scrollX, -scrollY);
22212         }
22213     }
22214 
22215     /**
22216      * Sets the correct background bounds and rebuilds the outline, if needed.
22217      * <p/>
22218      * This is called by LayoutLib.
22219      */
setBackgroundBounds()22220     void setBackgroundBounds() {
22221         if (mBackgroundSizeChanged && mBackground != null) {
22222             mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
22223             mBackgroundSizeChanged = false;
22224             rebuildOutline();
22225         }
22226     }
22227 
setBackgroundRenderNodeProperties(RenderNode renderNode)22228     private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
22229         renderNode.setTranslationX(mScrollX);
22230         renderNode.setTranslationY(mScrollY);
22231     }
22232 
22233     /**
22234      * Creates a new display list or updates the existing display list for the
22235      * specified Drawable.
22236      *
22237      * @param drawable Drawable for which to create a display list
22238      * @param renderNode Existing RenderNode, or {@code null}
22239      * @return A valid display list for the specified drawable
22240      */
getDrawableRenderNode(Drawable drawable, RenderNode renderNode)22241     private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
22242         if (renderNode == null) {
22243             renderNode = RenderNode.create(drawable.getClass().getName(),
22244                     new ViewAnimationHostBridge(this));
22245             renderNode.setUsageHint(RenderNode.USAGE_BACKGROUND);
22246         }
22247 
22248         final Rect bounds = drawable.getBounds();
22249         final int width = bounds.width();
22250         final int height = bounds.height();
22251         final RecordingCanvas canvas = renderNode.beginRecording(width, height);
22252 
22253         // Reverse left/top translation done by drawable canvas, which will
22254         // instead be applied by rendernode's LTRB bounds below. This way, the
22255         // drawable's bounds match with its rendernode bounds and its content
22256         // will lie within those bounds in the rendernode tree.
22257         canvas.translate(-bounds.left, -bounds.top);
22258 
22259         try {
22260             drawable.draw(canvas);
22261         } finally {
22262             renderNode.endRecording();
22263         }
22264 
22265         // Set up drawable properties that are view-independent.
22266         renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
22267         renderNode.setProjectBackwards(drawable.isProjected());
22268         renderNode.setProjectionReceiver(true);
22269         renderNode.setClipToBounds(false);
22270         return renderNode;
22271     }
22272 
22273     /**
22274      * Returns the overlay for this view, creating it if it does not yet exist.
22275      * Adding drawables to the overlay will cause them to be displayed whenever
22276      * the view itself is redrawn. Objects in the overlay should be actively
22277      * managed: remove them when they should not be displayed anymore. The
22278      * overlay will always have the same size as its host view.
22279      *
22280      * <p>Note: Overlays do not currently work correctly with {@link
22281      * SurfaceView} or {@link TextureView}; contents in overlays for these
22282      * types of views may not display correctly.</p>
22283      *
22284      * @return The ViewOverlay object for this view.
22285      * @see ViewOverlay
22286      */
getOverlay()22287     public ViewOverlay getOverlay() {
22288         if (mOverlay == null) {
22289             mOverlay = new ViewOverlay(mContext, this);
22290         }
22291         return mOverlay;
22292     }
22293 
22294     /**
22295      * Override this if your view is known to always be drawn on top of a solid color background,
22296      * and needs to draw fading edges. Returning a non-zero color enables the view system to
22297      * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
22298      * should be set to 0xFF.
22299      *
22300      * @see #setVerticalFadingEdgeEnabled(boolean)
22301      * @see #setHorizontalFadingEdgeEnabled(boolean)
22302      *
22303      * @return The known solid color background for this view, or 0 if the color may vary
22304      */
22305     @ViewDebug.ExportedProperty(category = "drawing")
22306     @InspectableProperty
22307     @ColorInt
getSolidColor()22308     public int getSolidColor() {
22309         return 0;
22310     }
22311 
22312     /**
22313      * Build a human readable string representation of the specified view flags.
22314      *
22315      * @param flags the view flags to convert to a string
22316      * @return a String representing the supplied flags
22317      */
printFlags(int flags)22318     private static String printFlags(int flags) {
22319         String output = "";
22320         int numFlags = 0;
22321         if ((flags & FOCUSABLE) == FOCUSABLE) {
22322             output += "TAKES_FOCUS";
22323             numFlags++;
22324         }
22325 
22326         switch (flags & VISIBILITY_MASK) {
22327         case INVISIBLE:
22328             if (numFlags > 0) {
22329                 output += " ";
22330             }
22331             output += "INVISIBLE";
22332             // USELESS HERE numFlags++;
22333             break;
22334         case GONE:
22335             if (numFlags > 0) {
22336                 output += " ";
22337             }
22338             output += "GONE";
22339             // USELESS HERE numFlags++;
22340             break;
22341         default:
22342             break;
22343         }
22344         return output;
22345     }
22346 
22347     /**
22348      * Build a human readable string representation of the specified private
22349      * view flags.
22350      *
22351      * @param privateFlags the private view flags to convert to a string
22352      * @return a String representing the supplied flags
22353      */
printPrivateFlags(int privateFlags)22354     private static String printPrivateFlags(int privateFlags) {
22355         String output = "";
22356         int numFlags = 0;
22357 
22358         if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
22359             output += "WANTS_FOCUS";
22360             numFlags++;
22361         }
22362 
22363         if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
22364             if (numFlags > 0) {
22365                 output += " ";
22366             }
22367             output += "FOCUSED";
22368             numFlags++;
22369         }
22370 
22371         if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
22372             if (numFlags > 0) {
22373                 output += " ";
22374             }
22375             output += "SELECTED";
22376             numFlags++;
22377         }
22378 
22379         if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
22380             if (numFlags > 0) {
22381                 output += " ";
22382             }
22383             output += "IS_ROOT_NAMESPACE";
22384             numFlags++;
22385         }
22386 
22387         if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
22388             if (numFlags > 0) {
22389                 output += " ";
22390             }
22391             output += "HAS_BOUNDS";
22392             numFlags++;
22393         }
22394 
22395         if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
22396             if (numFlags > 0) {
22397                 output += " ";
22398             }
22399             output += "DRAWN";
22400             // USELESS HERE numFlags++;
22401         }
22402         return output;
22403     }
22404 
22405     /**
22406      * <p>Indicates whether or not this view's layout will be requested during
22407      * the next hierarchy layout pass.</p>
22408      *
22409      * @return true if the layout will be forced during next layout pass
22410      */
isLayoutRequested()22411     public boolean isLayoutRequested() {
22412         return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
22413     }
22414 
22415     /**
22416      * Return true if o is a ViewGroup that is laying out using optical bounds.
22417      * @hide
22418      */
isLayoutModeOptical(Object o)22419     public static boolean isLayoutModeOptical(Object o) {
22420         return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
22421     }
22422 
setOpticalFrame(int left, int top, int right, int bottom)22423     private boolean setOpticalFrame(int left, int top, int right, int bottom) {
22424         Insets parentInsets = mParent instanceof View ?
22425                 ((View) mParent).getOpticalInsets() : Insets.NONE;
22426         Insets childInsets = getOpticalInsets();
22427         return setFrame(
22428                 left   + parentInsets.left - childInsets.left,
22429                 top    + parentInsets.top  - childInsets.top,
22430                 right  + parentInsets.left + childInsets.right,
22431                 bottom + parentInsets.top  + childInsets.bottom);
22432     }
22433 
22434     /**
22435      * Assign a size and position to a view and all of its
22436      * descendants
22437      *
22438      * <p>This is the second phase of the layout mechanism.
22439      * (The first is measuring). In this phase, each parent calls
22440      * layout on all of its children to position them.
22441      * This is typically done using the child measurements
22442      * that were stored in the measure pass().</p>
22443      *
22444      * <p>Derived classes should not override this method.
22445      * Derived classes with children should override
22446      * onLayout. In that method, they should
22447      * call layout on each of their children.</p>
22448      *
22449      * @param l Left position, relative to parent
22450      * @param t Top position, relative to parent
22451      * @param r Right position, relative to parent
22452      * @param b Bottom position, relative to parent
22453      */
22454     @SuppressWarnings({"unchecked"})
layout(int l, int t, int r, int b)22455     public void layout(int l, int t, int r, int b) {
22456         if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
22457             onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
22458             mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
22459         }
22460 
22461         int oldL = mLeft;
22462         int oldT = mTop;
22463         int oldB = mBottom;
22464         int oldR = mRight;
22465 
22466         boolean changed = isLayoutModeOptical(mParent) ?
22467                 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
22468 
22469         if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
22470             onLayout(changed, l, t, r, b);
22471 
22472             if (shouldDrawRoundScrollbar()) {
22473                 if(mRoundScrollbarRenderer == null) {
22474                     mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
22475                 }
22476             } else {
22477                 mRoundScrollbarRenderer = null;
22478             }
22479 
22480             mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
22481 
22482             ListenerInfo li = mListenerInfo;
22483             if (li != null && li.mOnLayoutChangeListeners != null) {
22484                 ArrayList<OnLayoutChangeListener> listenersCopy =
22485                         (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
22486                 int numListeners = listenersCopy.size();
22487                 for (int i = 0; i < numListeners; ++i) {
22488                     listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
22489                 }
22490             }
22491         }
22492 
22493         final boolean wasLayoutValid = isLayoutValid();
22494 
22495         mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
22496         mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
22497 
22498         if (!wasLayoutValid && isFocused()) {
22499             mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
22500             if (canTakeFocus()) {
22501                 // We have a robust focus, so parents should no longer be wanting focus.
22502                 clearParentsWantFocus();
22503             } else if (getViewRootImpl() == null || !getViewRootImpl().isInLayout()) {
22504                 // This is a weird case. Most-likely the user, rather than ViewRootImpl, called
22505                 // layout. In this case, there's no guarantee that parent layouts will be evaluated
22506                 // and thus the safest action is to clear focus here.
22507                 clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
22508                 clearParentsWantFocus();
22509             } else if (!hasParentWantsFocus()) {
22510                 // original requestFocus was likely on this view directly, so just clear focus
22511                 clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
22512             }
22513             // otherwise, we let parents handle re-assigning focus during their layout passes.
22514         } else if ((mPrivateFlags & PFLAG_WANTS_FOCUS) != 0) {
22515             mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
22516             View focused = findFocus();
22517             if (focused != null) {
22518                 // Try to restore focus as close as possible to our starting focus.
22519                 if (!restoreDefaultFocus() && !hasParentWantsFocus()) {
22520                     // Give up and clear focus once we've reached the top-most parent which wants
22521                     // focus.
22522                     focused.clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
22523                 }
22524             }
22525         }
22526 
22527         if ((mPrivateFlags3 & PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT) != 0) {
22528             mPrivateFlags3 &= ~PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
22529             notifyEnterOrExitForAutoFillIfNeeded(true);
22530         }
22531 
22532         notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
22533     }
22534 
hasParentWantsFocus()22535     private boolean hasParentWantsFocus() {
22536         ViewParent parent = mParent;
22537         while (parent instanceof ViewGroup) {
22538             ViewGroup pv = (ViewGroup) parent;
22539             if ((pv.mPrivateFlags & PFLAG_WANTS_FOCUS) != 0) {
22540                 return true;
22541             }
22542             parent = pv.mParent;
22543         }
22544         return false;
22545     }
22546 
22547     /**
22548      * Called from layout when this view should
22549      * assign a size and position to each of its children.
22550      *
22551      * Derived classes with children should override
22552      * this method and call layout on each of
22553      * their children.
22554      * @param changed This is a new size or position for this view
22555      * @param left Left position, relative to parent
22556      * @param top Top position, relative to parent
22557      * @param right Right position, relative to parent
22558      * @param bottom Bottom position, relative to parent
22559      */
onLayout(boolean changed, int left, int top, int right, int bottom)22560     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
22561     }
22562 
22563     /**
22564      * Assign a size and position to this view.
22565      *
22566      * This is called from layout.
22567      *
22568      * @param left Left position, relative to parent
22569      * @param top Top position, relative to parent
22570      * @param right Right position, relative to parent
22571      * @param bottom Bottom position, relative to parent
22572      * @return true if the new size and position are different than the
22573      *         previous ones
22574      * {@hide}
22575      */
22576     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
setFrame(int left, int top, int right, int bottom)22577     protected boolean setFrame(int left, int top, int right, int bottom) {
22578         boolean changed = false;
22579 
22580         if (DBG) {
22581             Log.d(VIEW_LOG_TAG, this + " View.setFrame(" + left + "," + top + ","
22582                     + right + "," + bottom + ")");
22583         }
22584 
22585         if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
22586             changed = true;
22587 
22588             // Remember our drawn bit
22589             int drawn = mPrivateFlags & PFLAG_DRAWN;
22590 
22591             int oldWidth = mRight - mLeft;
22592             int oldHeight = mBottom - mTop;
22593             int newWidth = right - left;
22594             int newHeight = bottom - top;
22595             boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
22596 
22597             // Invalidate our old position
22598             invalidate(sizeChanged);
22599 
22600             mLeft = left;
22601             mTop = top;
22602             mRight = right;
22603             mBottom = bottom;
22604             mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
22605 
22606             mPrivateFlags |= PFLAG_HAS_BOUNDS;
22607 
22608 
22609             if (sizeChanged) {
22610                 sizeChange(newWidth, newHeight, oldWidth, oldHeight);
22611             }
22612 
22613             if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
22614                 // If we are visible, force the DRAWN bit to on so that
22615                 // this invalidate will go through (at least to our parent).
22616                 // This is because someone may have invalidated this view
22617                 // before this call to setFrame came in, thereby clearing
22618                 // the DRAWN bit.
22619                 mPrivateFlags |= PFLAG_DRAWN;
22620                 invalidate(sizeChanged);
22621                 // parent display list may need to be recreated based on a change in the bounds
22622                 // of any child
22623                 invalidateParentCaches();
22624             }
22625 
22626             // Reset drawn bit to original value (invalidate turns it off)
22627             mPrivateFlags |= drawn;
22628 
22629             mBackgroundSizeChanged = true;
22630             mDefaultFocusHighlightSizeChanged = true;
22631             if (mForegroundInfo != null) {
22632                 mForegroundInfo.mBoundsChanged = true;
22633             }
22634 
22635             notifySubtreeAccessibilityStateChangedIfNeeded();
22636         }
22637         return changed;
22638     }
22639 
22640     /**
22641      * Assign a size and position to this view.
22642      *
22643      * This method is meant to be used in animations only as it applies this position and size
22644      * for the view only temporary and it can be changed back at any time by the layout.
22645      *
22646      * @param left Left position, relative to parent
22647      * @param top Top position, relative to parent
22648      * @param right Right position, relative to parent
22649      * @param bottom Bottom position, relative to parent
22650      *
22651      * @see #setLeft(int), #setRight(int), #setTop(int), #setBottom(int)
22652      */
setLeftTopRightBottom(int left, int top, int right, int bottom)22653     public final void setLeftTopRightBottom(int left, int top, int right, int bottom) {
22654         setFrame(left, top, right, bottom);
22655     }
22656 
sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight)22657     private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
22658         onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
22659         if (mOverlay != null) {
22660             mOverlay.getOverlayView().setRight(newWidth);
22661             mOverlay.getOverlayView().setBottom(newHeight);
22662         }
22663         // If this isn't laid out yet, focus assignment will be handled during the "deferment/
22664         // backtracking" of requestFocus during layout, so don't touch focus here.
22665         if (!sCanFocusZeroSized && isLayoutValid()
22666                 // Don't touch focus if animating
22667                 && !(mParent instanceof ViewGroup && ((ViewGroup) mParent).isLayoutSuppressed())) {
22668             if (newWidth <= 0 || newHeight <= 0) {
22669                 if (hasFocus()) {
22670                     clearFocus();
22671                     if (mParent instanceof ViewGroup) {
22672                         ((ViewGroup) mParent).clearFocusedInCluster();
22673                     }
22674                 }
22675                 clearAccessibilityFocus();
22676             } else if (oldWidth <= 0 || oldHeight <= 0) {
22677                 if (mParent != null && canTakeFocus()) {
22678                     mParent.focusableViewAvailable(this);
22679                 }
22680             }
22681         }
22682         rebuildOutline();
22683     }
22684 
22685     /**
22686      * Finalize inflating a view from XML.  This is called as the last phase
22687      * of inflation, after all child views have been added.
22688      *
22689      * <p>Even if the subclass overrides onFinishInflate, they should always be
22690      * sure to call the super method, so that we get called.
22691      */
22692     @CallSuper
onFinishInflate()22693     protected void onFinishInflate() {
22694     }
22695 
22696     /**
22697      * Returns the resources associated with this view.
22698      *
22699      * @return Resources object.
22700      */
getResources()22701     public Resources getResources() {
22702         return mResources;
22703     }
22704 
22705     /**
22706      * Invalidates the specified Drawable.
22707      *
22708      * @param drawable the drawable to invalidate
22709      */
22710     @Override
invalidateDrawable(@onNull Drawable drawable)22711     public void invalidateDrawable(@NonNull Drawable drawable) {
22712         if (verifyDrawable(drawable)) {
22713             final Rect dirty = drawable.getDirtyBounds();
22714             final int scrollX = mScrollX;
22715             final int scrollY = mScrollY;
22716 
22717             invalidate(dirty.left + scrollX, dirty.top + scrollY,
22718                     dirty.right + scrollX, dirty.bottom + scrollY);
22719             rebuildOutline();
22720         }
22721     }
22722 
22723     /**
22724      * Schedules an action on a drawable to occur at a specified time.
22725      *
22726      * @param who the recipient of the action
22727      * @param what the action to run on the drawable
22728      * @param when the time at which the action must occur. Uses the
22729      *        {@link SystemClock#uptimeMillis} timebase.
22730      */
22731     @Override
scheduleDrawable(@onNull Drawable who, @NonNull Runnable what, long when)22732     public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
22733         if (verifyDrawable(who) && what != null) {
22734             final long delay = when - SystemClock.uptimeMillis();
22735             if (mAttachInfo != null) {
22736                 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
22737                         Choreographer.CALLBACK_ANIMATION, what, who,
22738                         Choreographer.subtractFrameDelay(delay));
22739             } else {
22740                 // Postpone the runnable until we know
22741                 // on which thread it needs to run.
22742                 getRunQueue().postDelayed(what, delay);
22743             }
22744         }
22745     }
22746 
22747     /**
22748      * Cancels a scheduled action on a drawable.
22749      *
22750      * @param who the recipient of the action
22751      * @param what the action to cancel
22752      */
22753     @Override
unscheduleDrawable(@onNull Drawable who, @NonNull Runnable what)22754     public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
22755         if (verifyDrawable(who) && what != null) {
22756             if (mAttachInfo != null) {
22757                 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
22758                         Choreographer.CALLBACK_ANIMATION, what, who);
22759             }
22760             getRunQueue().removeCallbacks(what);
22761         }
22762     }
22763 
22764     /**
22765      * Unschedule any events associated with the given Drawable.  This can be
22766      * used when selecting a new Drawable into a view, so that the previous
22767      * one is completely unscheduled.
22768      *
22769      * @param who The Drawable to unschedule.
22770      *
22771      * @see #drawableStateChanged
22772      */
unscheduleDrawable(Drawable who)22773     public void unscheduleDrawable(Drawable who) {
22774         if (mAttachInfo != null && who != null) {
22775             mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
22776                     Choreographer.CALLBACK_ANIMATION, null, who);
22777         }
22778     }
22779 
22780     /**
22781      * Resolve the Drawables depending on the layout direction. This is implicitly supposing
22782      * that the View directionality can and will be resolved before its Drawables.
22783      *
22784      * Will call {@link View#onResolveDrawables} when resolution is done.
22785      *
22786      * @hide
22787      */
resolveDrawables()22788     protected void resolveDrawables() {
22789         // Drawables resolution may need to happen before resolving the layout direction (which is
22790         // done only during the measure() call).
22791         // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
22792         // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
22793         // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
22794         // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
22795         // direction to be resolved as its resolved value will be the same as its raw value.
22796         if (!isLayoutDirectionResolved() &&
22797                 getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
22798             return;
22799         }
22800 
22801         final int layoutDirection = isLayoutDirectionResolved() ?
22802                 getLayoutDirection() : getRawLayoutDirection();
22803 
22804         if (mBackground != null) {
22805             mBackground.setLayoutDirection(layoutDirection);
22806         }
22807         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
22808             mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
22809         }
22810         if (mDefaultFocusHighlight != null) {
22811             mDefaultFocusHighlight.setLayoutDirection(layoutDirection);
22812         }
22813         mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
22814         onResolveDrawables(layoutDirection);
22815     }
22816 
areDrawablesResolved()22817     boolean areDrawablesResolved() {
22818         return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
22819     }
22820 
22821     /**
22822      * Called when layout direction has been resolved.
22823      *
22824      * The default implementation does nothing.
22825      *
22826      * @param layoutDirection The resolved layout direction.
22827      *
22828      * @see #LAYOUT_DIRECTION_LTR
22829      * @see #LAYOUT_DIRECTION_RTL
22830      *
22831      * @hide
22832      */
onResolveDrawables(@esolvedLayoutDir int layoutDirection)22833     public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
22834     }
22835 
22836     /**
22837      * @hide
22838      */
22839     @TestApi
resetResolvedDrawables()22840     protected void resetResolvedDrawables() {
22841         resetResolvedDrawablesInternal();
22842     }
22843 
resetResolvedDrawablesInternal()22844     void resetResolvedDrawablesInternal() {
22845         mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
22846     }
22847 
22848     /**
22849      * If your view subclass is displaying its own Drawable objects, it should
22850      * override this function and return true for any Drawable it is
22851      * displaying.  This allows animations for those drawables to be
22852      * scheduled.
22853      *
22854      * <p>Be sure to call through to the super class when overriding this
22855      * function.
22856      *
22857      * @param who The Drawable to verify.  Return true if it is one you are
22858      *            displaying, else return the result of calling through to the
22859      *            super class.
22860      *
22861      * @return boolean If true than the Drawable is being displayed in the
22862      *         view; else false and it is not allowed to animate.
22863      *
22864      * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
22865      * @see #drawableStateChanged()
22866      */
22867     @CallSuper
verifyDrawable(@onNull Drawable who)22868     protected boolean verifyDrawable(@NonNull Drawable who) {
22869         // Avoid verifying the scroll bar drawable so that we don't end up in
22870         // an invalidation loop. This effectively prevents the scroll bar
22871         // drawable from triggering invalidations and scheduling runnables.
22872         return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who)
22873                 || (mDefaultFocusHighlight == who);
22874     }
22875 
22876     /**
22877      * This function is called whenever the state of the view changes in such
22878      * a way that it impacts the state of drawables being shown.
22879      * <p>
22880      * If the View has a StateListAnimator, it will also be called to run necessary state
22881      * change animations.
22882      * <p>
22883      * Be sure to call through to the superclass when overriding this function.
22884      *
22885      * @see Drawable#setState(int[])
22886      */
22887     @CallSuper
drawableStateChanged()22888     protected void drawableStateChanged() {
22889         final int[] state = getDrawableState();
22890         boolean changed = false;
22891 
22892         final Drawable bg = mBackground;
22893         if (bg != null && bg.isStateful()) {
22894             changed |= bg.setState(state);
22895         }
22896 
22897         final Drawable hl = mDefaultFocusHighlight;
22898         if (hl != null && hl.isStateful()) {
22899             changed |= hl.setState(state);
22900         }
22901 
22902         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
22903         if (fg != null && fg.isStateful()) {
22904             changed |= fg.setState(state);
22905         }
22906 
22907         if (mScrollCache != null) {
22908             final Drawable scrollBar = mScrollCache.scrollBar;
22909             if (scrollBar != null && scrollBar.isStateful()) {
22910                 changed |= scrollBar.setState(state)
22911                         && mScrollCache.state != ScrollabilityCache.OFF;
22912             }
22913         }
22914 
22915         if (mStateListAnimator != null) {
22916             mStateListAnimator.setState(state);
22917         }
22918 
22919         if (changed) {
22920             invalidate();
22921         }
22922     }
22923 
22924     /**
22925      * This function is called whenever the view hotspot changes and needs to
22926      * be propagated to drawables or child views managed by the view.
22927      * <p>
22928      * Dispatching to child views is handled by
22929      * {@link #dispatchDrawableHotspotChanged(float, float)}.
22930      * <p>
22931      * Be sure to call through to the superclass when overriding this function.
22932      *
22933      * @param x hotspot x coordinate
22934      * @param y hotspot y coordinate
22935      */
22936     @CallSuper
drawableHotspotChanged(float x, float y)22937     public void drawableHotspotChanged(float x, float y) {
22938         if (mBackground != null) {
22939             mBackground.setHotspot(x, y);
22940         }
22941         if (mDefaultFocusHighlight != null) {
22942             mDefaultFocusHighlight.setHotspot(x, y);
22943         }
22944         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
22945             mForegroundInfo.mDrawable.setHotspot(x, y);
22946         }
22947 
22948         dispatchDrawableHotspotChanged(x, y);
22949     }
22950 
22951     /**
22952      * Dispatches drawableHotspotChanged to all of this View's children.
22953      *
22954      * @param x hotspot x coordinate
22955      * @param y hotspot y coordinate
22956      * @see #drawableHotspotChanged(float, float)
22957      */
dispatchDrawableHotspotChanged(float x, float y)22958     public void dispatchDrawableHotspotChanged(float x, float y) {
22959     }
22960 
22961     /**
22962      * Call this to force a view to update its drawable state. This will cause
22963      * drawableStateChanged to be called on this view. Views that are interested
22964      * in the new state should call getDrawableState.
22965      *
22966      * @see #drawableStateChanged
22967      * @see #getDrawableState
22968      */
refreshDrawableState()22969     public void refreshDrawableState() {
22970         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
22971         drawableStateChanged();
22972 
22973         ViewParent parent = mParent;
22974         if (parent != null) {
22975             parent.childDrawableStateChanged(this);
22976         }
22977     }
22978 
22979     /**
22980      * Create a default focus highlight if it doesn't exist.
22981      * @return a default focus highlight.
22982      */
getDefaultFocusHighlightDrawable()22983     private Drawable getDefaultFocusHighlightDrawable() {
22984         if (mDefaultFocusHighlightCache == null) {
22985             if (mContext != null) {
22986                 final int[] attrs = new int[] { android.R.attr.selectableItemBackground };
22987                 final TypedArray ta = mContext.obtainStyledAttributes(attrs);
22988                 mDefaultFocusHighlightCache = ta.getDrawable(0);
22989                 ta.recycle();
22990             }
22991         }
22992         return mDefaultFocusHighlightCache;
22993     }
22994 
22995     /**
22996      * Set the current default focus highlight.
22997      * @param highlight the highlight drawable, or {@code null} if it's no longer needed.
22998      */
setDefaultFocusHighlight(Drawable highlight)22999     private void setDefaultFocusHighlight(Drawable highlight) {
23000         mDefaultFocusHighlight = highlight;
23001         mDefaultFocusHighlightSizeChanged = true;
23002         if (highlight != null) {
23003             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
23004                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
23005             }
23006             highlight.setLayoutDirection(getLayoutDirection());
23007             if (highlight.isStateful()) {
23008                 highlight.setState(getDrawableState());
23009             }
23010             if (isAttachedToWindow()) {
23011                 highlight.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
23012             }
23013             // Set callback last, since the view may still be initializing.
23014             highlight.setCallback(this);
23015         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
23016                 && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
23017             mPrivateFlags |= PFLAG_SKIP_DRAW;
23018         }
23019         invalidate();
23020     }
23021 
23022     /**
23023      * Check whether we need to draw a default focus highlight when this view gets focused,
23024      * which requires:
23025      * <ul>
23026      *     <li>In both background and foreground, {@link android.R.attr#state_focused}
23027      *         is not defined.</li>
23028      *     <li>This view is not in touch mode.</li>
23029      *     <li>This view doesn't opt out for a default focus highlight, via
23030      *         {@link #setDefaultFocusHighlightEnabled(boolean)}.</li>
23031      *     <li>This view is attached to window.</li>
23032      * </ul>
23033      * @return {@code true} if a default focus highlight is needed.
23034      * @hide
23035      */
23036     @TestApi
isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground)23037     public boolean isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground) {
23038         final boolean lackFocusState = (background == null || !background.isStateful()
23039                 || !background.hasFocusStateSpecified())
23040                 && (foreground == null || !foreground.isStateful()
23041                 || !foreground.hasFocusStateSpecified());
23042         return !isInTouchMode() && getDefaultFocusHighlightEnabled() && lackFocusState
23043                 && isAttachedToWindow() && sUseDefaultFocusHighlight;
23044     }
23045 
23046     /**
23047      * When this view is focused, switches on/off the default focused highlight.
23048      * <p>
23049      * This always happens when this view is focused, and only at this moment the default focus
23050      * highlight can be visible.
23051      */
switchDefaultFocusHighlight()23052     private void switchDefaultFocusHighlight() {
23053         if (isFocused()) {
23054             final boolean needed = isDefaultFocusHighlightNeeded(mBackground,
23055                     mForegroundInfo == null ? null : mForegroundInfo.mDrawable);
23056             final boolean active = mDefaultFocusHighlight != null;
23057             if (needed && !active) {
23058                 setDefaultFocusHighlight(getDefaultFocusHighlightDrawable());
23059             } else if (!needed && active) {
23060                 // The highlight is no longer needed, so tear it down.
23061                 setDefaultFocusHighlight(null);
23062             }
23063         }
23064     }
23065 
23066     /**
23067      * Draw the default focus highlight onto the canvas.
23068      * @param canvas the canvas where we're drawing the highlight.
23069      */
drawDefaultFocusHighlight(Canvas canvas)23070     private void drawDefaultFocusHighlight(Canvas canvas) {
23071         if (mDefaultFocusHighlight != null) {
23072             if (mDefaultFocusHighlightSizeChanged) {
23073                 mDefaultFocusHighlightSizeChanged = false;
23074                 final int l = mScrollX;
23075                 final int r = l + mRight - mLeft;
23076                 final int t = mScrollY;
23077                 final int b = t + mBottom - mTop;
23078                 mDefaultFocusHighlight.setBounds(l, t, r, b);
23079             }
23080             mDefaultFocusHighlight.draw(canvas);
23081         }
23082     }
23083 
23084     /**
23085      * Return an array of resource IDs of the drawable states representing the
23086      * current state of the view.
23087      *
23088      * @return The current drawable state
23089      *
23090      * @see Drawable#setState(int[])
23091      * @see #drawableStateChanged()
23092      * @see #onCreateDrawableState(int)
23093      */
getDrawableState()23094     public final int[] getDrawableState() {
23095         if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
23096             return mDrawableState;
23097         } else {
23098             mDrawableState = onCreateDrawableState(0);
23099             mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
23100             return mDrawableState;
23101         }
23102     }
23103 
23104     /**
23105      * Generate the new {@link android.graphics.drawable.Drawable} state for
23106      * this view. This is called by the view
23107      * system when the cached Drawable state is determined to be invalid.  To
23108      * retrieve the current state, you should use {@link #getDrawableState}.
23109      *
23110      * @param extraSpace if non-zero, this is the number of extra entries you
23111      * would like in the returned array in which you can place your own
23112      * states.
23113      *
23114      * @return Returns an array holding the current {@link Drawable} state of
23115      * the view.
23116      *
23117      * @see #mergeDrawableStates(int[], int[])
23118      */
onCreateDrawableState(int extraSpace)23119     protected int[] onCreateDrawableState(int extraSpace) {
23120         if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
23121                 mParent instanceof View) {
23122             return ((View) mParent).onCreateDrawableState(extraSpace);
23123         }
23124 
23125         int[] drawableState;
23126 
23127         int privateFlags = mPrivateFlags;
23128 
23129         int viewStateIndex = 0;
23130         if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
23131         if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
23132         if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
23133         if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
23134         if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
23135         if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
23136         if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
23137                 ThreadedRenderer.isAvailable()) {
23138             // This is set if HW acceleration is requested, even if the current
23139             // process doesn't allow it.  This is just to allow app preview
23140             // windows to better match their app.
23141             viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
23142         }
23143         if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
23144 
23145         final int privateFlags2 = mPrivateFlags2;
23146         if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
23147             viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
23148         }
23149         if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
23150             viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
23151         }
23152 
23153         drawableState = StateSet.get(viewStateIndex);
23154 
23155         //noinspection ConstantIfStatement
23156         if (false) {
23157             Log.i("View", "drawableStateIndex=" + viewStateIndex);
23158             Log.i("View", toString()
23159                     + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
23160                     + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
23161                     + " fo=" + hasFocus()
23162                     + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
23163                     + " wf=" + hasWindowFocus()
23164                     + ": " + Arrays.toString(drawableState));
23165         }
23166 
23167         if (extraSpace == 0) {
23168             return drawableState;
23169         }
23170 
23171         final int[] fullState;
23172         if (drawableState != null) {
23173             fullState = new int[drawableState.length + extraSpace];
23174             System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
23175         } else {
23176             fullState = new int[extraSpace];
23177         }
23178 
23179         return fullState;
23180     }
23181 
23182     /**
23183      * Merge your own state values in <var>additionalState</var> into the base
23184      * state values <var>baseState</var> that were returned by
23185      * {@link #onCreateDrawableState(int)}.
23186      *
23187      * @param baseState The base state values returned by
23188      * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
23189      * own additional state values.
23190      *
23191      * @param additionalState The additional state values you would like
23192      * added to <var>baseState</var>; this array is not modified.
23193      *
23194      * @return As a convenience, the <var>baseState</var> array you originally
23195      * passed into the function is returned.
23196      *
23197      * @see #onCreateDrawableState(int)
23198      */
mergeDrawableStates(int[] baseState, int[] additionalState)23199     protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
23200         final int N = baseState.length;
23201         int i = N - 1;
23202         while (i >= 0 && baseState[i] == 0) {
23203             i--;
23204         }
23205         System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
23206         return baseState;
23207     }
23208 
23209     /**
23210      * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
23211      * on all Drawable objects associated with this view.
23212      * <p>
23213      * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
23214      * attached to this view.
23215      */
23216     @CallSuper
jumpDrawablesToCurrentState()23217     public void jumpDrawablesToCurrentState() {
23218         if (mBackground != null) {
23219             mBackground.jumpToCurrentState();
23220         }
23221         if (mStateListAnimator != null) {
23222             mStateListAnimator.jumpToCurrentState();
23223         }
23224         if (mDefaultFocusHighlight != null) {
23225             mDefaultFocusHighlight.jumpToCurrentState();
23226         }
23227         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
23228             mForegroundInfo.mDrawable.jumpToCurrentState();
23229         }
23230     }
23231 
23232     /**
23233      * Sets the background color for this view.
23234      * @param color the color of the background
23235      */
23236     @RemotableViewMethod
setBackgroundColor(@olorInt int color)23237     public void setBackgroundColor(@ColorInt int color) {
23238         if (mBackground instanceof ColorDrawable) {
23239             ((ColorDrawable) mBackground.mutate()).setColor(color);
23240             computeOpaqueFlags();
23241             mBackgroundResource = 0;
23242         } else {
23243             setBackground(new ColorDrawable(color));
23244         }
23245     }
23246 
23247     /**
23248      * Set the background to a given resource. The resource should refer to
23249      * a Drawable object or 0 to remove the background.
23250      * @param resid The identifier of the resource.
23251      *
23252      * @attr ref android.R.styleable#View_background
23253      */
23254     @RemotableViewMethod
setBackgroundResource(@rawableRes int resid)23255     public void setBackgroundResource(@DrawableRes int resid) {
23256         if (resid != 0 && resid == mBackgroundResource) {
23257             return;
23258         }
23259 
23260         Drawable d = null;
23261         if (resid != 0) {
23262             d = mContext.getDrawable(resid);
23263         }
23264         setBackground(d);
23265 
23266         mBackgroundResource = resid;
23267     }
23268 
23269     /**
23270      * Set the background to a given Drawable, or remove the background. If the
23271      * background has padding, this View's padding is set to the background's
23272      * padding. However, when a background is removed, this View's padding isn't
23273      * touched. If setting the padding is desired, please use
23274      * {@link #setPadding(int, int, int, int)}.
23275      *
23276      * @param background The Drawable to use as the background, or null to remove the
23277      *        background
23278      */
setBackground(Drawable background)23279     public void setBackground(Drawable background) {
23280         //noinspection deprecation
23281         setBackgroundDrawable(background);
23282     }
23283 
23284     /**
23285      * @deprecated use {@link #setBackground(Drawable)} instead
23286      */
23287     @Deprecated
setBackgroundDrawable(Drawable background)23288     public void setBackgroundDrawable(Drawable background) {
23289         computeOpaqueFlags();
23290 
23291         if (background == mBackground) {
23292             return;
23293         }
23294 
23295         boolean requestLayout = false;
23296 
23297         mBackgroundResource = 0;
23298 
23299         /*
23300          * Regardless of whether we're setting a new background or not, we want
23301          * to clear the previous drawable. setVisible first while we still have the callback set.
23302          */
23303         if (mBackground != null) {
23304             if (isAttachedToWindow()) {
23305                 mBackground.setVisible(false, false);
23306             }
23307             mBackground.setCallback(null);
23308             unscheduleDrawable(mBackground);
23309         }
23310 
23311         if (background != null) {
23312             Rect padding = sThreadLocal.get();
23313             if (padding == null) {
23314                 padding = new Rect();
23315                 sThreadLocal.set(padding);
23316             }
23317             resetResolvedDrawablesInternal();
23318             background.setLayoutDirection(getLayoutDirection());
23319             if (background.getPadding(padding)) {
23320                 resetResolvedPaddingInternal();
23321                 switch (background.getLayoutDirection()) {
23322                     case LAYOUT_DIRECTION_RTL:
23323                         mUserPaddingLeftInitial = padding.right;
23324                         mUserPaddingRightInitial = padding.left;
23325                         internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
23326                         break;
23327                     case LAYOUT_DIRECTION_LTR:
23328                     default:
23329                         mUserPaddingLeftInitial = padding.left;
23330                         mUserPaddingRightInitial = padding.right;
23331                         internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
23332                 }
23333                 mLeftPaddingDefined = false;
23334                 mRightPaddingDefined = false;
23335             }
23336 
23337             // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
23338             // if it has a different minimum size, we should layout again
23339             if (mBackground == null
23340                     || mBackground.getMinimumHeight() != background.getMinimumHeight()
23341                     || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
23342                 requestLayout = true;
23343             }
23344 
23345             // Set mBackground before we set this as the callback and start making other
23346             // background drawable state change calls. In particular, the setVisible call below
23347             // can result in drawables attempting to start animations or otherwise invalidate,
23348             // which requires the view set as the callback (us) to recognize the drawable as
23349             // belonging to it as per verifyDrawable.
23350             mBackground = background;
23351             if (background.isStateful()) {
23352                 background.setState(getDrawableState());
23353             }
23354             if (isAttachedToWindow()) {
23355                 background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
23356             }
23357 
23358             applyBackgroundTint();
23359 
23360             // Set callback last, since the view may still be initializing.
23361             background.setCallback(this);
23362 
23363             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
23364                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
23365                 requestLayout = true;
23366             }
23367         } else {
23368             /* Remove the background */
23369             mBackground = null;
23370             if ((mViewFlags & WILL_NOT_DRAW) != 0
23371                     && (mDefaultFocusHighlight == null)
23372                     && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
23373                 mPrivateFlags |= PFLAG_SKIP_DRAW;
23374             }
23375 
23376             /*
23377              * When the background is set, we try to apply its padding to this
23378              * View. When the background is removed, we don't touch this View's
23379              * padding. This is noted in the Javadocs. Hence, we don't need to
23380              * requestLayout(), the invalidate() below is sufficient.
23381              */
23382 
23383             // The old background's minimum size could have affected this
23384             // View's layout, so let's requestLayout
23385             requestLayout = true;
23386         }
23387 
23388         computeOpaqueFlags();
23389 
23390         if (requestLayout) {
23391             requestLayout();
23392         }
23393 
23394         mBackgroundSizeChanged = true;
23395         invalidate(true);
23396         invalidateOutline();
23397     }
23398 
23399     /**
23400      * Gets the background drawable
23401      *
23402      * @return The drawable used as the background for this view, if any.
23403      *
23404      * @see #setBackground(Drawable)
23405      *
23406      * @attr ref android.R.styleable#View_background
23407      */
23408     @InspectableProperty
getBackground()23409     public Drawable getBackground() {
23410         return mBackground;
23411     }
23412 
23413     /**
23414      * Applies a tint to the background drawable. Does not modify the current tint
23415      * mode, which is {@link BlendMode#SRC_IN} by default.
23416      * <p>
23417      * Subsequent calls to {@link #setBackground(Drawable)} will automatically
23418      * mutate the drawable and apply the specified tint and tint mode using
23419      * {@link Drawable#setTintList(ColorStateList)}.
23420      *
23421      * @param tint the tint to apply, may be {@code null} to clear tint
23422      *
23423      * @attr ref android.R.styleable#View_backgroundTint
23424      * @see #getBackgroundTintList()
23425      * @see Drawable#setTintList(ColorStateList)
23426      */
setBackgroundTintList(@ullable ColorStateList tint)23427     public void setBackgroundTintList(@Nullable ColorStateList tint) {
23428         if (mBackgroundTint == null) {
23429             mBackgroundTint = new TintInfo();
23430         }
23431         mBackgroundTint.mTintList = tint;
23432         mBackgroundTint.mHasTintList = true;
23433 
23434         applyBackgroundTint();
23435     }
23436 
23437     /**
23438      * Return the tint applied to the background drawable, if specified.
23439      *
23440      * @return the tint applied to the background drawable
23441      * @attr ref android.R.styleable#View_backgroundTint
23442      * @see #setBackgroundTintList(ColorStateList)
23443      */
23444     @InspectableProperty(name = "backgroundTint")
23445     @Nullable
getBackgroundTintList()23446     public ColorStateList getBackgroundTintList() {
23447         return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
23448     }
23449 
23450     /**
23451      * Specifies the blending mode used to apply the tint specified by
23452      * {@link #setBackgroundTintList(ColorStateList)}} to the background
23453      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
23454      *
23455      * @param tintMode the blending mode used to apply the tint, may be
23456      *                 {@code null} to clear tint
23457      * @attr ref android.R.styleable#View_backgroundTintMode
23458      * @see #getBackgroundTintMode()
23459      * @see Drawable#setTintMode(PorterDuff.Mode)
23460      */
setBackgroundTintMode(@ullable PorterDuff.Mode tintMode)23461     public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
23462         BlendMode mode = null;
23463         if (tintMode != null) {
23464             mode = BlendMode.fromValue(tintMode.nativeInt);
23465         }
23466 
23467         setBackgroundTintBlendMode(mode);
23468     }
23469 
23470     /**
23471      * Specifies the blending mode used to apply the tint specified by
23472      * {@link #setBackgroundTintList(ColorStateList)}} to the background
23473      * drawable. The default mode is {@link BlendMode#SRC_IN}.
23474      *
23475      * @param blendMode the blending mode used to apply the tint, may be
23476      *                 {@code null} to clear tint
23477      * @attr ref android.R.styleable#View_backgroundTintMode
23478      * @see #getBackgroundTintMode()
23479      * @see Drawable#setTintBlendMode(BlendMode)
23480      */
setBackgroundTintBlendMode(@ullable BlendMode blendMode)23481     public void setBackgroundTintBlendMode(@Nullable BlendMode blendMode) {
23482         if (mBackgroundTint == null) {
23483             mBackgroundTint = new TintInfo();
23484         }
23485 
23486         mBackgroundTint.mBlendMode = blendMode;
23487         mBackgroundTint.mHasTintMode = true;
23488 
23489         applyBackgroundTint();
23490     }
23491 
23492     /**
23493      * Return the blending mode used to apply the tint to the background
23494      * drawable, if specified.
23495      *
23496      * @return the blending mode used to apply the tint to the background
23497      *         drawable
23498      * @attr ref android.R.styleable#View_backgroundTintMode
23499      * @see #setBackgroundTintBlendMode(BlendMode)
23500      *
23501      */
23502     @Nullable
23503     @InspectableProperty
getBackgroundTintMode()23504     public PorterDuff.Mode getBackgroundTintMode() {
23505         PorterDuff.Mode porterDuffMode;
23506         if (mBackgroundTint != null && mBackgroundTint.mBlendMode != null) {
23507             porterDuffMode = BlendMode.blendModeToPorterDuffMode(mBackgroundTint.mBlendMode);
23508         } else {
23509             porterDuffMode = null;
23510         }
23511         return porterDuffMode;
23512     }
23513 
23514     /**
23515      * Return the blending mode used to apply the tint to the background
23516      * drawable, if specified.
23517      *
23518      * @return the blending mode used to apply the tint to the background
23519      *         drawable, null if no blend has previously been configured
23520      * @attr ref android.R.styleable#View_backgroundTintMode
23521      * @see #setBackgroundTintBlendMode(BlendMode)
23522      */
getBackgroundTintBlendMode()23523     public @Nullable BlendMode getBackgroundTintBlendMode() {
23524         return mBackgroundTint != null ? mBackgroundTint.mBlendMode : null;
23525     }
23526 
applyBackgroundTint()23527     private void applyBackgroundTint() {
23528         if (mBackground != null && mBackgroundTint != null) {
23529             final TintInfo tintInfo = mBackgroundTint;
23530             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
23531                 mBackground = mBackground.mutate();
23532 
23533                 if (tintInfo.mHasTintList) {
23534                     mBackground.setTintList(tintInfo.mTintList);
23535                 }
23536 
23537                 if (tintInfo.mHasTintMode) {
23538                     mBackground.setTintBlendMode(tintInfo.mBlendMode);
23539                 }
23540 
23541                 // The drawable (or one of its children) may not have been
23542                 // stateful before applying the tint, so let's try again.
23543                 if (mBackground.isStateful()) {
23544                     mBackground.setState(getDrawableState());
23545                 }
23546             }
23547         }
23548     }
23549 
23550     /**
23551      * Returns the drawable used as the foreground of this View. The
23552      * foreground drawable, if non-null, is always drawn on top of the view's content.
23553      *
23554      * @return a Drawable or null if no foreground was set
23555      *
23556      * @see #onDrawForeground(Canvas)
23557      */
23558     @InspectableProperty
getForeground()23559     public Drawable getForeground() {
23560         return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
23561     }
23562 
23563     /**
23564      * Supply a Drawable that is to be rendered on top of all of the content in the view.
23565      *
23566      * @param foreground the Drawable to be drawn on top of the children
23567      *
23568      * @attr ref android.R.styleable#View_foreground
23569      */
setForeground(Drawable foreground)23570     public void setForeground(Drawable foreground) {
23571         if (mForegroundInfo == null) {
23572             if (foreground == null) {
23573                 // Nothing to do.
23574                 return;
23575             }
23576             mForegroundInfo = new ForegroundInfo();
23577         }
23578 
23579         if (foreground == mForegroundInfo.mDrawable) {
23580             // Nothing to do
23581             return;
23582         }
23583 
23584         if (mForegroundInfo.mDrawable != null) {
23585             if (isAttachedToWindow()) {
23586                 mForegroundInfo.mDrawable.setVisible(false, false);
23587             }
23588             mForegroundInfo.mDrawable.setCallback(null);
23589             unscheduleDrawable(mForegroundInfo.mDrawable);
23590         }
23591 
23592         mForegroundInfo.mDrawable = foreground;
23593         mForegroundInfo.mBoundsChanged = true;
23594         if (foreground != null) {
23595             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
23596                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
23597             }
23598             foreground.setLayoutDirection(getLayoutDirection());
23599             if (foreground.isStateful()) {
23600                 foreground.setState(getDrawableState());
23601             }
23602             applyForegroundTint();
23603             if (isAttachedToWindow()) {
23604                 foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
23605             }
23606             // Set callback last, since the view may still be initializing.
23607             foreground.setCallback(this);
23608         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
23609                 && (mDefaultFocusHighlight == null)) {
23610             mPrivateFlags |= PFLAG_SKIP_DRAW;
23611         }
23612         requestLayout();
23613         invalidate();
23614     }
23615 
23616     /**
23617      * Magic bit used to support features of framework-internal window decor implementation details.
23618      * This used to live exclusively in FrameLayout.
23619      *
23620      * @return true if the foreground should draw inside the padding region or false
23621      *         if it should draw inset by the view's padding
23622      * @hide internal use only; only used by FrameLayout and internal screen layouts.
23623      */
isForegroundInsidePadding()23624     public boolean isForegroundInsidePadding() {
23625         return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
23626     }
23627 
23628     /**
23629      * Describes how the foreground is positioned.
23630      *
23631      * @return foreground gravity.
23632      *
23633      * @see #setForegroundGravity(int)
23634      *
23635      * @attr ref android.R.styleable#View_foregroundGravity
23636      */
23637     @InspectableProperty(valueType = InspectableProperty.ValueType.GRAVITY)
getForegroundGravity()23638     public int getForegroundGravity() {
23639         return mForegroundInfo != null ? mForegroundInfo.mGravity
23640                 : Gravity.START | Gravity.TOP;
23641     }
23642 
23643     /**
23644      * Describes how the foreground is positioned. Defaults to START and TOP.
23645      *
23646      * @param gravity see {@link android.view.Gravity}
23647      *
23648      * @see #getForegroundGravity()
23649      *
23650      * @attr ref android.R.styleable#View_foregroundGravity
23651      */
setForegroundGravity(int gravity)23652     public void setForegroundGravity(int gravity) {
23653         if (mForegroundInfo == null) {
23654             mForegroundInfo = new ForegroundInfo();
23655         }
23656 
23657         if (mForegroundInfo.mGravity != gravity) {
23658             if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
23659                 gravity |= Gravity.START;
23660             }
23661 
23662             if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
23663                 gravity |= Gravity.TOP;
23664             }
23665 
23666             mForegroundInfo.mGravity = gravity;
23667             requestLayout();
23668         }
23669     }
23670 
23671     /**
23672      * Applies a tint to the foreground drawable. Does not modify the current tint
23673      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
23674      * <p>
23675      * Subsequent calls to {@link #setForeground(Drawable)} will automatically
23676      * mutate the drawable and apply the specified tint and tint mode using
23677      * {@link Drawable#setTintList(ColorStateList)}.
23678      *
23679      * @param tint the tint to apply, may be {@code null} to clear tint
23680      *
23681      * @attr ref android.R.styleable#View_foregroundTint
23682      * @see #getForegroundTintList()
23683      * @see Drawable#setTintList(ColorStateList)
23684      */
setForegroundTintList(@ullable ColorStateList tint)23685     public void setForegroundTintList(@Nullable ColorStateList tint) {
23686         if (mForegroundInfo == null) {
23687             mForegroundInfo = new ForegroundInfo();
23688         }
23689         if (mForegroundInfo.mTintInfo == null) {
23690             mForegroundInfo.mTintInfo = new TintInfo();
23691         }
23692         mForegroundInfo.mTintInfo.mTintList = tint;
23693         mForegroundInfo.mTintInfo.mHasTintList = true;
23694 
23695         applyForegroundTint();
23696     }
23697 
23698     /**
23699      * Return the tint applied to the foreground drawable, if specified.
23700      *
23701      * @return the tint applied to the foreground drawable
23702      * @attr ref android.R.styleable#View_foregroundTint
23703      * @see #setForegroundTintList(ColorStateList)
23704      */
23705     @InspectableProperty(name = "foregroundTint")
23706     @Nullable
getForegroundTintList()23707     public ColorStateList getForegroundTintList() {
23708         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
23709                 ? mForegroundInfo.mTintInfo.mTintList : null;
23710     }
23711 
23712     /**
23713      * Specifies the blending mode used to apply the tint specified by
23714      * {@link #setForegroundTintList(ColorStateList)}} to the background
23715      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
23716      *
23717      * @param tintMode the blending mode used to apply the tint, may be
23718      *                 {@code null} to clear tint
23719      * @attr ref android.R.styleable#View_foregroundTintMode
23720      * @see #getForegroundTintMode()
23721      * @see Drawable#setTintMode(PorterDuff.Mode)
23722      *
23723      */
setForegroundTintMode(@ullable PorterDuff.Mode tintMode)23724     public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
23725         BlendMode mode = null;
23726         if (tintMode != null) {
23727             mode = BlendMode.fromValue(tintMode.nativeInt);
23728         }
23729         setForegroundTintBlendMode(mode);
23730     }
23731 
23732     /**
23733      * Specifies the blending mode used to apply the tint specified by
23734      * {@link #setForegroundTintList(ColorStateList)}} to the background
23735      * drawable. The default mode is {@link BlendMode#SRC_IN}.
23736      *
23737      * @param blendMode the blending mode used to apply the tint, may be
23738      *                 {@code null} to clear tint
23739      * @attr ref android.R.styleable#View_foregroundTintMode
23740      * @see #getForegroundTintMode()
23741      * @see Drawable#setTintBlendMode(BlendMode)
23742      */
setForegroundTintBlendMode(@ullable BlendMode blendMode)23743     public void setForegroundTintBlendMode(@Nullable BlendMode blendMode) {
23744         if (mForegroundInfo == null) {
23745             mForegroundInfo = new ForegroundInfo();
23746         }
23747         if (mForegroundInfo.mTintInfo == null) {
23748             mForegroundInfo.mTintInfo = new TintInfo();
23749         }
23750         mForegroundInfo.mTintInfo.mBlendMode = blendMode;
23751         mForegroundInfo.mTintInfo.mHasTintMode = true;
23752 
23753         applyForegroundTint();
23754     }
23755 
23756     /**
23757      * Return the blending mode used to apply the tint to the foreground
23758      * drawable, if specified.
23759      *
23760      * @return the blending mode used to apply the tint to the foreground
23761      *         drawable
23762      * @attr ref android.R.styleable#View_foregroundTintMode
23763      * @see #setForegroundTintMode(PorterDuff.Mode)
23764      */
23765     @InspectableProperty
23766     @Nullable
getForegroundTintMode()23767     public PorterDuff.Mode getForegroundTintMode() {
23768         BlendMode blendMode = mForegroundInfo != null && mForegroundInfo.mTintInfo != null
23769                 ? mForegroundInfo.mTintInfo.mBlendMode : null;
23770         if (blendMode != null) {
23771             return BlendMode.blendModeToPorterDuffMode(blendMode);
23772         } else {
23773             return null;
23774         }
23775     }
23776 
23777     /**
23778      * Return the blending mode used to apply the tint to the foreground
23779      * drawable, if specified.
23780      *
23781      * @return the blending mode used to apply the tint to the foreground
23782      *         drawable
23783      * @attr ref android.R.styleable#View_foregroundTintMode
23784      * @see #setForegroundTintBlendMode(BlendMode)
23785      *
23786      */
getForegroundTintBlendMode()23787     public @Nullable BlendMode getForegroundTintBlendMode() {
23788         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
23789                 ? mForegroundInfo.mTintInfo.mBlendMode : null;
23790     }
23791 
applyForegroundTint()23792     private void applyForegroundTint() {
23793         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
23794                 && mForegroundInfo.mTintInfo != null) {
23795             final TintInfo tintInfo = mForegroundInfo.mTintInfo;
23796             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
23797                 mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
23798 
23799                 if (tintInfo.mHasTintList) {
23800                     mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
23801                 }
23802 
23803                 if (tintInfo.mHasTintMode) {
23804                     mForegroundInfo.mDrawable.setTintBlendMode(tintInfo.mBlendMode);
23805                 }
23806 
23807                 // The drawable (or one of its children) may not have been
23808                 // stateful before applying the tint, so let's try again.
23809                 if (mForegroundInfo.mDrawable.isStateful()) {
23810                     mForegroundInfo.mDrawable.setState(getDrawableState());
23811                 }
23812             }
23813         }
23814     }
23815 
23816     /**
23817      * Get the drawable to be overlayed when a view is autofilled
23818      *
23819      * @return The drawable
23820      *
23821      * @throws IllegalStateException if the drawable could not be found.
23822      */
getAutofilledDrawable()23823     @Nullable private Drawable getAutofilledDrawable() {
23824         if (mAttachInfo == null) {
23825             return null;
23826         }
23827         // Lazily load the isAutofilled drawable.
23828         if (mAttachInfo.mAutofilledDrawable == null) {
23829             Context rootContext = getRootView().getContext();
23830             TypedArray a = rootContext.getTheme().obtainStyledAttributes(AUTOFILL_HIGHLIGHT_ATTR);
23831             int attributeResourceId = a.getResourceId(0, 0);
23832             mAttachInfo.mAutofilledDrawable = rootContext.getDrawable(attributeResourceId);
23833             a.recycle();
23834         }
23835 
23836         return mAttachInfo.mAutofilledDrawable;
23837     }
23838 
23839     /**
23840      * Draw {@link View#isAutofilled()} highlight over view if the view is autofilled.
23841      *
23842      * @param canvas The canvas to draw on
23843      */
drawAutofilledHighlight(@onNull Canvas canvas)23844     private void drawAutofilledHighlight(@NonNull Canvas canvas) {
23845         if (isAutofilled()) {
23846             Drawable autofilledHighlight = getAutofilledDrawable();
23847 
23848             if (autofilledHighlight != null) {
23849                 autofilledHighlight.setBounds(0, 0, getWidth(), getHeight());
23850                 autofilledHighlight.draw(canvas);
23851             }
23852         }
23853     }
23854 
23855     /**
23856      * Draw any foreground content for this view.
23857      *
23858      * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
23859      * drawable or other view-specific decorations. The foreground is drawn on top of the
23860      * primary view content.</p>
23861      *
23862      * @param canvas canvas to draw into
23863      */
onDrawForeground(Canvas canvas)23864     public void onDrawForeground(Canvas canvas) {
23865         onDrawScrollIndicators(canvas);
23866         onDrawScrollBars(canvas);
23867 
23868         final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
23869         if (foreground != null) {
23870             if (mForegroundInfo.mBoundsChanged) {
23871                 mForegroundInfo.mBoundsChanged = false;
23872                 final Rect selfBounds = mForegroundInfo.mSelfBounds;
23873                 final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
23874 
23875                 if (mForegroundInfo.mInsidePadding) {
23876                     selfBounds.set(0, 0, getWidth(), getHeight());
23877                 } else {
23878                     selfBounds.set(getPaddingLeft(), getPaddingTop(),
23879                             getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
23880                 }
23881 
23882                 final int ld = getLayoutDirection();
23883                 Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
23884                         foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
23885                 foreground.setBounds(overlayBounds);
23886             }
23887 
23888             foreground.draw(canvas);
23889         }
23890     }
23891 
23892     /**
23893      * Sets the padding. The view may add on the space required to display
23894      * the scrollbars, depending on the style and visibility of the scrollbars.
23895      * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
23896      * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
23897      * from the values set in this call.
23898      *
23899      * @attr ref android.R.styleable#View_padding
23900      * @attr ref android.R.styleable#View_paddingBottom
23901      * @attr ref android.R.styleable#View_paddingLeft
23902      * @attr ref android.R.styleable#View_paddingRight
23903      * @attr ref android.R.styleable#View_paddingTop
23904      * @param left the left padding in pixels
23905      * @param top the top padding in pixels
23906      * @param right the right padding in pixels
23907      * @param bottom the bottom padding in pixels
23908      */
setPadding(int left, int top, int right, int bottom)23909     public void setPadding(int left, int top, int right, int bottom) {
23910         resetResolvedPaddingInternal();
23911 
23912         mUserPaddingStart = UNDEFINED_PADDING;
23913         mUserPaddingEnd = UNDEFINED_PADDING;
23914 
23915         mUserPaddingLeftInitial = left;
23916         mUserPaddingRightInitial = right;
23917 
23918         mLeftPaddingDefined = true;
23919         mRightPaddingDefined = true;
23920 
23921         internalSetPadding(left, top, right, bottom);
23922     }
23923 
23924     /**
23925      * @hide
23926      */
23927     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768420)
internalSetPadding(int left, int top, int right, int bottom)23928     protected void internalSetPadding(int left, int top, int right, int bottom) {
23929         mUserPaddingLeft = left;
23930         mUserPaddingRight = right;
23931         mUserPaddingBottom = bottom;
23932 
23933         final int viewFlags = mViewFlags;
23934         boolean changed = false;
23935 
23936         // Common case is there are no scroll bars.
23937         if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
23938             if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
23939                 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
23940                         ? 0 : getVerticalScrollbarWidth();
23941                 switch (mVerticalScrollbarPosition) {
23942                     case SCROLLBAR_POSITION_DEFAULT:
23943                         if (isLayoutRtl()) {
23944                             left += offset;
23945                         } else {
23946                             right += offset;
23947                         }
23948                         break;
23949                     case SCROLLBAR_POSITION_RIGHT:
23950                         right += offset;
23951                         break;
23952                     case SCROLLBAR_POSITION_LEFT:
23953                         left += offset;
23954                         break;
23955                 }
23956             }
23957             if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
23958                 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
23959                         ? 0 : getHorizontalScrollbarHeight();
23960             }
23961         }
23962 
23963         if (mPaddingLeft != left) {
23964             changed = true;
23965             mPaddingLeft = left;
23966         }
23967         if (mPaddingTop != top) {
23968             changed = true;
23969             mPaddingTop = top;
23970         }
23971         if (mPaddingRight != right) {
23972             changed = true;
23973             mPaddingRight = right;
23974         }
23975         if (mPaddingBottom != bottom) {
23976             changed = true;
23977             mPaddingBottom = bottom;
23978         }
23979 
23980         if (changed) {
23981             requestLayout();
23982             invalidateOutline();
23983         }
23984     }
23985 
23986     /**
23987      * Sets the relative padding. The view may add on the space required to display
23988      * the scrollbars, depending on the style and visibility of the scrollbars.
23989      * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
23990      * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
23991      * from the values set in this call.
23992      *
23993      * @attr ref android.R.styleable#View_padding
23994      * @attr ref android.R.styleable#View_paddingBottom
23995      * @attr ref android.R.styleable#View_paddingStart
23996      * @attr ref android.R.styleable#View_paddingEnd
23997      * @attr ref android.R.styleable#View_paddingTop
23998      * @param start the start padding in pixels
23999      * @param top the top padding in pixels
24000      * @param end the end padding in pixels
24001      * @param bottom the bottom padding in pixels
24002      */
setPaddingRelative(int start, int top, int end, int bottom)24003     public void setPaddingRelative(int start, int top, int end, int bottom) {
24004         resetResolvedPaddingInternal();
24005 
24006         mUserPaddingStart = start;
24007         mUserPaddingEnd = end;
24008         mLeftPaddingDefined = true;
24009         mRightPaddingDefined = true;
24010 
24011         switch(getLayoutDirection()) {
24012             case LAYOUT_DIRECTION_RTL:
24013                 mUserPaddingLeftInitial = end;
24014                 mUserPaddingRightInitial = start;
24015                 internalSetPadding(end, top, start, bottom);
24016                 break;
24017             case LAYOUT_DIRECTION_LTR:
24018             default:
24019                 mUserPaddingLeftInitial = start;
24020                 mUserPaddingRightInitial = end;
24021                 internalSetPadding(start, top, end, bottom);
24022         }
24023     }
24024 
24025     /**
24026      * A {@link View} can be inflated from an XML layout. For such Views this method returns the
24027      * resource ID of the source layout.
24028      *
24029      * @return The layout resource id if this view was inflated from XML, otherwise
24030      * {@link Resources#ID_NULL}.
24031      */
24032     @LayoutRes
getSourceLayoutResId()24033     public int getSourceLayoutResId() {
24034         return mSourceLayoutId;
24035     }
24036 
24037     /**
24038      * Returns the top padding of this view.
24039      *
24040      * @return the top padding in pixels
24041      */
24042     @InspectableProperty
getPaddingTop()24043     public int getPaddingTop() {
24044         return mPaddingTop;
24045     }
24046 
24047     /**
24048      * Returns the bottom padding of this view. If there are inset and enabled
24049      * scrollbars, this value may include the space required to display the
24050      * scrollbars as well.
24051      *
24052      * @return the bottom padding in pixels
24053      */
24054     @InspectableProperty
getPaddingBottom()24055     public int getPaddingBottom() {
24056         return mPaddingBottom;
24057     }
24058 
24059     /**
24060      * Returns the left padding of this view. If there are inset and enabled
24061      * scrollbars, this value may include the space required to display the
24062      * scrollbars as well.
24063      *
24064      * @return the left padding in pixels
24065      */
24066     @InspectableProperty
getPaddingLeft()24067     public int getPaddingLeft() {
24068         if (!isPaddingResolved()) {
24069             resolvePadding();
24070         }
24071         return mPaddingLeft;
24072     }
24073 
24074     /**
24075      * Returns the start padding of this view depending on its resolved layout direction.
24076      * If there are inset and enabled scrollbars, this value may include the space
24077      * required to display the scrollbars as well.
24078      *
24079      * @return the start padding in pixels
24080      */
getPaddingStart()24081     public int getPaddingStart() {
24082         if (!isPaddingResolved()) {
24083             resolvePadding();
24084         }
24085         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
24086                 mPaddingRight : mPaddingLeft;
24087     }
24088 
24089     /**
24090      * Returns the right padding of this view. If there are inset and enabled
24091      * scrollbars, this value may include the space required to display the
24092      * scrollbars as well.
24093      *
24094      * @return the right padding in pixels
24095      */
24096     @InspectableProperty
getPaddingRight()24097     public int getPaddingRight() {
24098         if (!isPaddingResolved()) {
24099             resolvePadding();
24100         }
24101         return mPaddingRight;
24102     }
24103 
24104     /**
24105      * Returns the end padding of this view depending on its resolved layout direction.
24106      * If there are inset and enabled scrollbars, this value may include the space
24107      * required to display the scrollbars as well.
24108      *
24109      * @return the end padding in pixels
24110      */
getPaddingEnd()24111     public int getPaddingEnd() {
24112         if (!isPaddingResolved()) {
24113             resolvePadding();
24114         }
24115         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
24116                 mPaddingLeft : mPaddingRight;
24117     }
24118 
24119     /**
24120      * Return if the padding has been set through relative values
24121      * {@link #setPaddingRelative(int, int, int, int)} or through
24122      * @attr ref android.R.styleable#View_paddingStart or
24123      * @attr ref android.R.styleable#View_paddingEnd
24124      *
24125      * @return true if the padding is relative or false if it is not.
24126      */
isPaddingRelative()24127     public boolean isPaddingRelative() {
24128         return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
24129     }
24130 
computeOpticalInsets()24131     Insets computeOpticalInsets() {
24132         return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
24133     }
24134 
24135     /**
24136      * @hide
24137      */
24138     @UnsupportedAppUsage
resetPaddingToInitialValues()24139     public void resetPaddingToInitialValues() {
24140         if (isRtlCompatibilityMode()) {
24141             mPaddingLeft = mUserPaddingLeftInitial;
24142             mPaddingRight = mUserPaddingRightInitial;
24143             return;
24144         }
24145         if (isLayoutRtl()) {
24146             mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
24147             mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
24148         } else {
24149             mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
24150             mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
24151         }
24152     }
24153 
24154     /**
24155      * @hide
24156      */
getOpticalInsets()24157     public Insets getOpticalInsets() {
24158         if (mLayoutInsets == null) {
24159             mLayoutInsets = computeOpticalInsets();
24160         }
24161         return mLayoutInsets;
24162     }
24163 
24164     /**
24165      * Set this view's optical insets.
24166      *
24167      * <p>This method should be treated similarly to setMeasuredDimension and not as a general
24168      * property. Views that compute their own optical insets should call it as part of measurement.
24169      * This method does not request layout. If you are setting optical insets outside of
24170      * measure/layout itself you will want to call requestLayout() yourself.
24171      * </p>
24172      * @hide
24173      */
setOpticalInsets(Insets insets)24174     public void setOpticalInsets(Insets insets) {
24175         mLayoutInsets = insets;
24176     }
24177 
24178     /**
24179      * Changes the selection state of this view. A view can be selected or not.
24180      * Note that selection is not the same as focus. Views are typically
24181      * selected in the context of an AdapterView like ListView or GridView;
24182      * the selected view is the view that is highlighted.
24183      *
24184      * @param selected true if the view must be selected, false otherwise
24185      */
setSelected(boolean selected)24186     public void setSelected(boolean selected) {
24187         //noinspection DoubleNegation
24188         if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
24189             mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
24190             if (!selected) resetPressedState();
24191             invalidate(true);
24192             refreshDrawableState();
24193             dispatchSetSelected(selected);
24194             if (selected) {
24195                 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
24196             } else {
24197                 notifyViewAccessibilityStateChangedIfNeeded(
24198                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
24199             }
24200         }
24201     }
24202 
24203     /**
24204      * Dispatch setSelected to all of this View's children.
24205      *
24206      * @see #setSelected(boolean)
24207      *
24208      * @param selected The new selected state
24209      */
dispatchSetSelected(boolean selected)24210     protected void dispatchSetSelected(boolean selected) {
24211     }
24212 
24213     /**
24214      * Indicates the selection state of this view.
24215      *
24216      * @return true if the view is selected, false otherwise
24217      */
24218     @ViewDebug.ExportedProperty
24219     @InspectableProperty(hasAttributeId = false)
isSelected()24220     public boolean isSelected() {
24221         return (mPrivateFlags & PFLAG_SELECTED) != 0;
24222     }
24223 
24224     /**
24225      * Changes the activated state of this view. A view can be activated or not.
24226      * Note that activation is not the same as selection.  Selection is
24227      * a transient property, representing the view (hierarchy) the user is
24228      * currently interacting with.  Activation is a longer-term state that the
24229      * user can move views in and out of.  For example, in a list view with
24230      * single or multiple selection enabled, the views in the current selection
24231      * set are activated.  (Um, yeah, we are deeply sorry about the terminology
24232      * here.)  The activated state is propagated down to children of the view it
24233      * is set on.
24234      *
24235      * @param activated true if the view must be activated, false otherwise
24236      */
setActivated(boolean activated)24237     public void setActivated(boolean activated) {
24238         //noinspection DoubleNegation
24239         if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
24240             mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
24241             invalidate(true);
24242             refreshDrawableState();
24243             dispatchSetActivated(activated);
24244         }
24245     }
24246 
24247     /**
24248      * Dispatch setActivated to all of this View's children.
24249      *
24250      * @see #setActivated(boolean)
24251      *
24252      * @param activated The new activated state
24253      */
dispatchSetActivated(boolean activated)24254     protected void dispatchSetActivated(boolean activated) {
24255     }
24256 
24257     /**
24258      * Indicates the activation state of this view.
24259      *
24260      * @return true if the view is activated, false otherwise
24261      */
24262     @ViewDebug.ExportedProperty
24263     @InspectableProperty(hasAttributeId = false)
isActivated()24264     public boolean isActivated() {
24265         return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
24266     }
24267 
24268     /**
24269      * Returns the ViewTreeObserver for this view's hierarchy. The view tree
24270      * observer can be used to get notifications when global events, like
24271      * layout, happen.
24272      *
24273      * The returned ViewTreeObserver observer is not guaranteed to remain
24274      * valid for the lifetime of this View. If the caller of this method keeps
24275      * a long-lived reference to ViewTreeObserver, it should always check for
24276      * the return value of {@link ViewTreeObserver#isAlive()}.
24277      *
24278      * @return The ViewTreeObserver for this view's hierarchy.
24279      */
getViewTreeObserver()24280     public ViewTreeObserver getViewTreeObserver() {
24281         if (mAttachInfo != null) {
24282             return mAttachInfo.mTreeObserver;
24283         }
24284         if (mFloatingTreeObserver == null) {
24285             mFloatingTreeObserver = new ViewTreeObserver(mContext);
24286         }
24287         return mFloatingTreeObserver;
24288     }
24289 
24290     /**
24291      * <p>Finds the topmost view in the current view hierarchy.</p>
24292      *
24293      * @return the topmost view containing this view
24294      */
getRootView()24295     public View getRootView() {
24296         if (mAttachInfo != null) {
24297             final View v = mAttachInfo.mRootView;
24298             if (v != null) {
24299                 return v;
24300             }
24301         }
24302 
24303         View parent = this;
24304 
24305         while (parent.mParent != null && parent.mParent instanceof View) {
24306             parent = (View) parent.mParent;
24307         }
24308 
24309         return parent;
24310     }
24311 
24312     /**
24313      * Transforms a motion event from view-local coordinates to on-screen
24314      * coordinates.
24315      *
24316      * @param ev the view-local motion event
24317      * @return false if the transformation could not be applied
24318      * @hide
24319      */
24320     @UnsupportedAppUsage
toGlobalMotionEvent(MotionEvent ev)24321     public boolean toGlobalMotionEvent(MotionEvent ev) {
24322         final AttachInfo info = mAttachInfo;
24323         if (info == null) {
24324             return false;
24325         }
24326 
24327         final Matrix m = info.mTmpMatrix;
24328         m.set(Matrix.IDENTITY_MATRIX);
24329         transformMatrixToGlobal(m);
24330         ev.transform(m);
24331         return true;
24332     }
24333 
24334     /**
24335      * Transforms a motion event from on-screen coordinates to view-local
24336      * coordinates.
24337      *
24338      * @param ev the on-screen motion event
24339      * @return false if the transformation could not be applied
24340      * @hide
24341      */
24342     @UnsupportedAppUsage
toLocalMotionEvent(MotionEvent ev)24343     public boolean toLocalMotionEvent(MotionEvent ev) {
24344         final AttachInfo info = mAttachInfo;
24345         if (info == null) {
24346             return false;
24347         }
24348 
24349         final Matrix m = info.mTmpMatrix;
24350         m.set(Matrix.IDENTITY_MATRIX);
24351         transformMatrixToLocal(m);
24352         ev.transform(m);
24353         return true;
24354     }
24355 
24356     /**
24357      * Modifies the input matrix such that it maps view-local coordinates to
24358      * on-screen coordinates.
24359      *
24360      * @param matrix input matrix to modify
24361      */
transformMatrixToGlobal(@onNull Matrix matrix)24362     public void transformMatrixToGlobal(@NonNull Matrix matrix) {
24363         final ViewParent parent = mParent;
24364         if (parent instanceof View) {
24365             final View vp = (View) parent;
24366             vp.transformMatrixToGlobal(matrix);
24367             matrix.preTranslate(-vp.mScrollX, -vp.mScrollY);
24368         } else if (parent instanceof ViewRootImpl) {
24369             final ViewRootImpl vr = (ViewRootImpl) parent;
24370             vr.transformMatrixToGlobal(matrix);
24371             matrix.preTranslate(0, -vr.mCurScrollY);
24372         }
24373 
24374         matrix.preTranslate(mLeft, mTop);
24375 
24376         if (!hasIdentityMatrix()) {
24377             matrix.preConcat(getMatrix());
24378         }
24379     }
24380 
24381     /**
24382      * Modifies the input matrix such that it maps on-screen coordinates to
24383      * view-local coordinates.
24384      *
24385      * @param matrix input matrix to modify
24386      */
transformMatrixToLocal(@onNull Matrix matrix)24387     public void transformMatrixToLocal(@NonNull Matrix matrix) {
24388         final ViewParent parent = mParent;
24389         if (parent instanceof View) {
24390             final View vp = (View) parent;
24391             vp.transformMatrixToLocal(matrix);
24392             matrix.postTranslate(vp.mScrollX, vp.mScrollY);
24393         } else if (parent instanceof ViewRootImpl) {
24394             final ViewRootImpl vr = (ViewRootImpl) parent;
24395             vr.transformMatrixToLocal(matrix);
24396             matrix.postTranslate(0, vr.mCurScrollY);
24397         }
24398 
24399         matrix.postTranslate(-mLeft, -mTop);
24400 
24401         if (!hasIdentityMatrix()) {
24402             matrix.postConcat(getInverseMatrix());
24403         }
24404     }
24405 
24406     /**
24407      * @hide
24408      */
24409     @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
24410             @ViewDebug.IntToString(from = 0, to = "x"),
24411             @ViewDebug.IntToString(from = 1, to = "y")
24412     })
24413     @UnsupportedAppUsage
getLocationOnScreen()24414     public int[] getLocationOnScreen() {
24415         int[] location = new int[2];
24416         getLocationOnScreen(location);
24417         return location;
24418     }
24419 
24420     /**
24421      * <p>Computes the coordinates of this view on the screen. The argument
24422      * must be an array of two integers. After the method returns, the array
24423      * contains the x and y location in that order.</p>
24424      *
24425      * @param outLocation an array of two integers in which to hold the coordinates
24426      */
getLocationOnScreen(@ize2) int[] outLocation)24427     public void getLocationOnScreen(@Size(2) int[] outLocation) {
24428         getLocationInWindow(outLocation);
24429 
24430         final AttachInfo info = mAttachInfo;
24431         if (info != null) {
24432             outLocation[0] += info.mWindowLeft;
24433             outLocation[1] += info.mWindowTop;
24434         }
24435     }
24436 
24437     /**
24438      * <p>Computes the coordinates of this view in its window. The argument
24439      * must be an array of two integers. After the method returns, the array
24440      * contains the x and y location in that order.</p>
24441      *
24442      * @param outLocation an array of two integers in which to hold the coordinates
24443      */
getLocationInWindow(@ize2) int[] outLocation)24444     public void getLocationInWindow(@Size(2) int[] outLocation) {
24445         if (outLocation == null || outLocation.length < 2) {
24446             throw new IllegalArgumentException("outLocation must be an array of two integers");
24447         }
24448 
24449         outLocation[0] = 0;
24450         outLocation[1] = 0;
24451 
24452         transformFromViewToWindowSpace(outLocation);
24453     }
24454 
24455     /** @hide */
transformFromViewToWindowSpace(@ize2) int[] inOutLocation)24456     public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
24457         if (inOutLocation == null || inOutLocation.length < 2) {
24458             throw new IllegalArgumentException("inOutLocation must be an array of two integers");
24459         }
24460 
24461         if (mAttachInfo == null) {
24462             // When the view is not attached to a window, this method does not make sense
24463             inOutLocation[0] = inOutLocation[1] = 0;
24464             return;
24465         }
24466 
24467         float position[] = mAttachInfo.mTmpTransformLocation;
24468         position[0] = inOutLocation[0];
24469         position[1] = inOutLocation[1];
24470 
24471         if (!hasIdentityMatrix()) {
24472             getMatrix().mapPoints(position);
24473         }
24474 
24475         position[0] += mLeft;
24476         position[1] += mTop;
24477 
24478         ViewParent viewParent = mParent;
24479         while (viewParent instanceof View) {
24480             final View view = (View) viewParent;
24481 
24482             position[0] -= view.mScrollX;
24483             position[1] -= view.mScrollY;
24484 
24485             if (!view.hasIdentityMatrix()) {
24486                 view.getMatrix().mapPoints(position);
24487             }
24488 
24489             position[0] += view.mLeft;
24490             position[1] += view.mTop;
24491 
24492             viewParent = view.mParent;
24493          }
24494 
24495         if (viewParent instanceof ViewRootImpl) {
24496             // *cough*
24497             final ViewRootImpl vr = (ViewRootImpl) viewParent;
24498             position[1] -= vr.mCurScrollY;
24499         }
24500 
24501         inOutLocation[0] = Math.round(position[0]);
24502         inOutLocation[1] = Math.round(position[1]);
24503     }
24504 
24505     /**
24506      * @param id the id of the view to be found
24507      * @return the view of the specified id, null if cannot be found
24508      * @hide
24509      */
findViewTraversal(@dRes int id)24510     protected <T extends View> T findViewTraversal(@IdRes int id) {
24511         if (id == mID) {
24512             return (T) this;
24513         }
24514         return null;
24515     }
24516 
24517     /**
24518      * @param tag the tag of the view to be found
24519      * @return the view of specified tag, null if cannot be found
24520      * @hide
24521      */
findViewWithTagTraversal(Object tag)24522     protected <T extends View> T findViewWithTagTraversal(Object tag) {
24523         if (tag != null && tag.equals(mTag)) {
24524             return (T) this;
24525         }
24526         return null;
24527     }
24528 
24529     /**
24530      * @param predicate The predicate to evaluate.
24531      * @param childToSkip If not null, ignores this child during the recursive traversal.
24532      * @return The first view that matches the predicate or null.
24533      * @hide
24534      */
findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip)24535     protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
24536             View childToSkip) {
24537         if (predicate.test(this)) {
24538             return (T) this;
24539         }
24540         return null;
24541     }
24542 
24543     /**
24544      * Finds the first descendant view with the given ID, the view itself if
24545      * the ID matches {@link #getId()}, or {@code null} if the ID is invalid
24546      * (< 0) or there is no matching view in the hierarchy.
24547      * <p>
24548      * <strong>Note:</strong> In most cases -- depending on compiler support --
24549      * the resulting view is automatically cast to the target class type. If
24550      * the target class type is unconstrained, an explicit cast may be
24551      * necessary.
24552      *
24553      * @param id the ID to search for
24554      * @return a view with given ID if found, or {@code null} otherwise
24555      * @see View#requireViewById(int)
24556      */
24557     @Nullable
findViewById(@dRes int id)24558     public final <T extends View> T findViewById(@IdRes int id) {
24559         if (id == NO_ID) {
24560             return null;
24561         }
24562         return findViewTraversal(id);
24563     }
24564 
24565     /**
24566      * Finds the first descendant view with the given ID, the view itself if the ID matches
24567      * {@link #getId()}, or throws an IllegalArgumentException if the ID is invalid or there is no
24568      * matching view in the hierarchy.
24569      * <p>
24570      * <strong>Note:</strong> In most cases -- depending on compiler support --
24571      * the resulting view is automatically cast to the target class type. If
24572      * the target class type is unconstrained, an explicit cast may be
24573      * necessary.
24574      *
24575      * @param id the ID to search for
24576      * @return a view with given ID
24577      * @see View#findViewById(int)
24578      */
24579     @NonNull
requireViewById(@dRes int id)24580     public final <T extends View> T requireViewById(@IdRes int id) {
24581         T view = findViewById(id);
24582         if (view == null) {
24583             throw new IllegalArgumentException("ID does not reference a View inside this View");
24584         }
24585         return view;
24586     }
24587 
24588     /**
24589      * Performs the traversal to find a view by its unique and stable accessibility id.
24590      *
24591      * <strong>Note:</strong>This method does not stop at the root namespace
24592      * boundary since the user can touch the screen at an arbitrary location
24593      * potentially crossing the root namespace boundary which will send an
24594      * accessibility event to accessibility services and they should be able
24595      * to obtain the event source. Also accessibility ids are guaranteed to be
24596      * unique in the window.
24597      *
24598      * @param accessibilityId The accessibility id.
24599      * @return The found view.
24600      * @hide
24601      */
findViewByAccessibilityIdTraversal(int accessibilityId)24602     public <T extends View> T findViewByAccessibilityIdTraversal(int accessibilityId) {
24603         if (getAccessibilityViewId() == accessibilityId) {
24604             return (T) this;
24605         }
24606         return null;
24607     }
24608 
24609     /**
24610      * Performs the traversal to find a view by its autofill id.
24611      *
24612      * <strong>Note:</strong>This method does not stop at the root namespace
24613      * boundary.
24614      *
24615      * @param autofillId The autofill id.
24616      * @return The found view.
24617      * @hide
24618      */
findViewByAutofillIdTraversal(int autofillId)24619     public <T extends View> T findViewByAutofillIdTraversal(int autofillId) {
24620         if (getAutofillViewId() == autofillId) {
24621             return (T) this;
24622         }
24623         return null;
24624     }
24625 
24626     /**
24627      * Look for a child view with the given tag.  If this view has the given
24628      * tag, return this view.
24629      *
24630      * @param tag The tag to search for, using "tag.equals(getTag())".
24631      * @return The View that has the given tag in the hierarchy or null
24632      */
findViewWithTag(Object tag)24633     public final <T extends View> T findViewWithTag(Object tag) {
24634         if (tag == null) {
24635             return null;
24636         }
24637         return findViewWithTagTraversal(tag);
24638     }
24639 
24640     /**
24641      * Look for a child view that matches the specified predicate.
24642      * If this view matches the predicate, return this view.
24643      *
24644      * @param predicate The predicate to evaluate.
24645      * @return The first view that matches the predicate or null.
24646      * @hide
24647      */
findViewByPredicate(Predicate<View> predicate)24648     public final <T extends View> T findViewByPredicate(Predicate<View> predicate) {
24649         return findViewByPredicateTraversal(predicate, null);
24650     }
24651 
24652     /**
24653      * Look for a child view that matches the specified predicate,
24654      * starting with the specified view and its descendents and then
24655      * recusively searching the ancestors and siblings of that view
24656      * until this view is reached.
24657      *
24658      * This method is useful in cases where the predicate does not match
24659      * a single unique view (perhaps multiple views use the same id)
24660      * and we are trying to find the view that is "closest" in scope to the
24661      * starting view.
24662      *
24663      * @param start The view to start from.
24664      * @param predicate The predicate to evaluate.
24665      * @return The first view that matches the predicate or null.
24666      * @hide
24667      */
findViewByPredicateInsideOut( View start, Predicate<View> predicate)24668     public final <T extends View> T findViewByPredicateInsideOut(
24669             View start, Predicate<View> predicate) {
24670         View childToSkip = null;
24671         for (;;) {
24672             T view = start.findViewByPredicateTraversal(predicate, childToSkip);
24673             if (view != null || start == this) {
24674                 return view;
24675             }
24676 
24677             ViewParent parent = start.getParent();
24678             if (parent == null || !(parent instanceof View)) {
24679                 return null;
24680             }
24681 
24682             childToSkip = start;
24683             start = (View) parent;
24684         }
24685     }
24686 
24687     /**
24688      * Sets the identifier for this view. The identifier does not have to be
24689      * unique in this view's hierarchy. The identifier should be a positive
24690      * number.
24691      *
24692      * @see #NO_ID
24693      * @see #getId()
24694      * @see #findViewById(int)
24695      *
24696      * @param id a number used to identify the view
24697      *
24698      * @attr ref android.R.styleable#View_id
24699      */
setId(@dRes int id)24700     public void setId(@IdRes int id) {
24701         mID = id;
24702         if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
24703             mID = generateViewId();
24704         }
24705     }
24706 
24707     /**
24708      * {@hide}
24709      *
24710      * @param isRoot true if the view belongs to the root namespace, false
24711      *        otherwise
24712      */
24713     @UnsupportedAppUsage
24714     @TestApi
setIsRootNamespace(boolean isRoot)24715     public void setIsRootNamespace(boolean isRoot) {
24716         if (isRoot) {
24717             mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
24718         } else {
24719             mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
24720         }
24721     }
24722 
24723     /**
24724      * {@hide}
24725      *
24726      * @return true if the view belongs to the root namespace, false otherwise
24727      */
24728     @UnsupportedAppUsage
isRootNamespace()24729     public boolean isRootNamespace() {
24730         return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
24731     }
24732 
24733     /**
24734      * Returns this view's identifier.
24735      *
24736      * @return a positive integer used to identify the view or {@link #NO_ID}
24737      *         if the view has no ID
24738      *
24739      * @see #setId(int)
24740      * @see #findViewById(int)
24741      * @attr ref android.R.styleable#View_id
24742      */
24743     @IdRes
24744     @ViewDebug.CapturedViewProperty
24745     @InspectableProperty
getId()24746     public int getId() {
24747         return mID;
24748     }
24749 
24750     /**
24751      * Get the identifier used for this view by the drawing system.
24752      *
24753      * @see RenderNode#getUniqueId()
24754      * @return A long that uniquely identifies this view's drawing component
24755      */
getUniqueDrawingId()24756     public long getUniqueDrawingId() {
24757         return mRenderNode.getUniqueId();
24758     }
24759 
24760     /**
24761      * Returns this view's tag.
24762      *
24763      * @return the Object stored in this view as a tag, or {@code null} if not
24764      *         set
24765      *
24766      * @see #setTag(Object)
24767      * @see #getTag(int)
24768      */
24769     @ViewDebug.ExportedProperty
24770     @InspectableProperty
getTag()24771     public Object getTag() {
24772         return mTag;
24773     }
24774 
24775     /**
24776      * Sets the tag associated with this view. A tag can be used to mark
24777      * a view in its hierarchy and does not have to be unique within the
24778      * hierarchy. Tags can also be used to store data within a view without
24779      * resorting to another data structure.
24780      *
24781      * @param tag an Object to tag the view with
24782      *
24783      * @see #getTag()
24784      * @see #setTag(int, Object)
24785      */
setTag(final Object tag)24786     public void setTag(final Object tag) {
24787         mTag = tag;
24788     }
24789 
24790     /**
24791      * Returns the tag associated with this view and the specified key.
24792      *
24793      * @param key The key identifying the tag
24794      *
24795      * @return the Object stored in this view as a tag, or {@code null} if not
24796      *         set
24797      *
24798      * @see #setTag(int, Object)
24799      * @see #getTag()
24800      */
getTag(int key)24801     public Object getTag(int key) {
24802         if (mKeyedTags != null) return mKeyedTags.get(key);
24803         return null;
24804     }
24805 
24806     /**
24807      * Sets a tag associated with this view and a key. A tag can be used
24808      * to mark a view in its hierarchy and does not have to be unique within
24809      * the hierarchy. Tags can also be used to store data within a view
24810      * without resorting to another data structure.
24811      *
24812      * The specified key should be an id declared in the resources of the
24813      * application to ensure it is unique (see the <a
24814      * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
24815      * Keys identified as belonging to
24816      * the Android framework or not associated with any package will cause
24817      * an {@link IllegalArgumentException} to be thrown.
24818      *
24819      * @param key The key identifying the tag
24820      * @param tag An Object to tag the view with
24821      *
24822      * @throws IllegalArgumentException If they specified key is not valid
24823      *
24824      * @see #setTag(Object)
24825      * @see #getTag(int)
24826      */
setTag(int key, final Object tag)24827     public void setTag(int key, final Object tag) {
24828         // If the package id is 0x00 or 0x01, it's either an undefined package
24829         // or a framework id
24830         if ((key >>> 24) < 2) {
24831             throw new IllegalArgumentException("The key must be an application-specific "
24832                     + "resource id.");
24833         }
24834 
24835         setKeyedTag(key, tag);
24836     }
24837 
24838     /**
24839      * Variation of {@link #setTag(int, Object)} that enforces the key to be a
24840      * framework id.
24841      *
24842      * @hide
24843      */
24844     @UnsupportedAppUsage
setTagInternal(int key, Object tag)24845     public void setTagInternal(int key, Object tag) {
24846         if ((key >>> 24) != 0x1) {
24847             throw new IllegalArgumentException("The key must be a framework-specific "
24848                     + "resource id.");
24849         }
24850 
24851         setKeyedTag(key, tag);
24852     }
24853 
setKeyedTag(int key, Object tag)24854     private void setKeyedTag(int key, Object tag) {
24855         if (mKeyedTags == null) {
24856             mKeyedTags = new SparseArray<Object>(2);
24857         }
24858 
24859         mKeyedTags.put(key, tag);
24860     }
24861 
24862     /**
24863      * Prints information about this view in the log output, with the tag
24864      * {@link #VIEW_LOG_TAG}.
24865      *
24866      * @hide
24867      */
24868     @UnsupportedAppUsage
debug()24869     public void debug() {
24870         debug(0);
24871     }
24872 
24873     /**
24874      * Prints information about this view in the log output, with the tag
24875      * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
24876      * indentation defined by the <code>depth</code>.
24877      *
24878      * @param depth the indentation level
24879      *
24880      * @hide
24881      */
24882     @UnsupportedAppUsage
debug(int depth)24883     protected void debug(int depth) {
24884         String output = debugIndent(depth - 1);
24885 
24886         output += "+ " + this;
24887         int id = getId();
24888         if (id != -1) {
24889             output += " (id=" + id + ")";
24890         }
24891         Object tag = getTag();
24892         if (tag != null) {
24893             output += " (tag=" + tag + ")";
24894         }
24895         Log.d(VIEW_LOG_TAG, output);
24896 
24897         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
24898             output = debugIndent(depth) + " FOCUSED";
24899             Log.d(VIEW_LOG_TAG, output);
24900         }
24901 
24902         output = debugIndent(depth);
24903         output += "frame={" + mLeft + ", " + mTop + ", " + mRight
24904                 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
24905                 + "} ";
24906         Log.d(VIEW_LOG_TAG, output);
24907 
24908         if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
24909                 || mPaddingBottom != 0) {
24910             output = debugIndent(depth);
24911             output += "padding={" + mPaddingLeft + ", " + mPaddingTop
24912                     + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
24913             Log.d(VIEW_LOG_TAG, output);
24914         }
24915 
24916         output = debugIndent(depth);
24917         output += "mMeasureWidth=" + mMeasuredWidth +
24918                 " mMeasureHeight=" + mMeasuredHeight;
24919         Log.d(VIEW_LOG_TAG, output);
24920 
24921         output = debugIndent(depth);
24922         if (mLayoutParams == null) {
24923             output += "BAD! no layout params";
24924         } else {
24925             output = mLayoutParams.debug(output);
24926         }
24927         Log.d(VIEW_LOG_TAG, output);
24928 
24929         output = debugIndent(depth);
24930         output += "flags={";
24931         output += View.printFlags(mViewFlags);
24932         output += "}";
24933         Log.d(VIEW_LOG_TAG, output);
24934 
24935         output = debugIndent(depth);
24936         output += "privateFlags={";
24937         output += View.printPrivateFlags(mPrivateFlags);
24938         output += "}";
24939         Log.d(VIEW_LOG_TAG, output);
24940     }
24941 
24942     /**
24943      * Creates a string of whitespaces used for indentation.
24944      *
24945      * @param depth the indentation level
24946      * @return a String containing (depth * 2 + 3) * 2 white spaces
24947      *
24948      * @hide
24949      */
debugIndent(int depth)24950     protected static String debugIndent(int depth) {
24951         StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
24952         for (int i = 0; i < (depth * 2) + 3; i++) {
24953             spaces.append(' ').append(' ');
24954         }
24955         return spaces.toString();
24956     }
24957 
24958     /**
24959      * <p>Return the offset of the widget's text baseline from the widget's top
24960      * boundary. If this widget does not support baseline alignment, this
24961      * method returns -1. </p>
24962      *
24963      * @return the offset of the baseline within the widget's bounds or -1
24964      *         if baseline alignment is not supported
24965      */
24966     @ViewDebug.ExportedProperty(category = "layout")
24967     @InspectableProperty
getBaseline()24968     public int getBaseline() {
24969         return -1;
24970     }
24971 
24972     /**
24973      * Returns whether the view hierarchy is currently undergoing a layout pass. This
24974      * information is useful to avoid situations such as calling {@link #requestLayout()} during
24975      * a layout pass.
24976      *
24977      * @return whether the view hierarchy is currently undergoing a layout pass
24978      */
isInLayout()24979     public boolean isInLayout() {
24980         ViewRootImpl viewRoot = getViewRootImpl();
24981         return (viewRoot != null && viewRoot.isInLayout());
24982     }
24983 
24984     /**
24985      * Call this when something has changed which has invalidated the
24986      * layout of this view. This will schedule a layout pass of the view
24987      * tree. This should not be called while the view hierarchy is currently in a layout
24988      * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
24989      * end of the current layout pass (and then layout will run again) or after the current
24990      * frame is drawn and the next layout occurs.
24991      *
24992      * <p>Subclasses which override this method should call the superclass method to
24993      * handle possible request-during-layout errors correctly.</p>
24994      */
24995     @CallSuper
requestLayout()24996     public void requestLayout() {
24997         if (mMeasureCache != null) mMeasureCache.clear();
24998 
24999         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
25000             // Only trigger request-during-layout logic if this is the view requesting it,
25001             // not the views in its parent hierarchy
25002             ViewRootImpl viewRoot = getViewRootImpl();
25003             if (viewRoot != null && viewRoot.isInLayout()) {
25004                 if (!viewRoot.requestLayoutDuringLayout(this)) {
25005                     return;
25006                 }
25007             }
25008             mAttachInfo.mViewRequestingLayout = this;
25009         }
25010 
25011         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
25012         mPrivateFlags |= PFLAG_INVALIDATED;
25013 
25014         if (mParent != null && !mParent.isLayoutRequested()) {
25015             mParent.requestLayout();
25016         }
25017         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
25018             mAttachInfo.mViewRequestingLayout = null;
25019         }
25020     }
25021 
25022     /**
25023      * Forces this view to be laid out during the next layout pass.
25024      * This method does not call requestLayout() or forceLayout()
25025      * on the parent.
25026      */
forceLayout()25027     public void forceLayout() {
25028         if (mMeasureCache != null) mMeasureCache.clear();
25029 
25030         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
25031         mPrivateFlags |= PFLAG_INVALIDATED;
25032     }
25033 
25034     /**
25035      * <p>
25036      * This is called to find out how big a view should be. The parent
25037      * supplies constraint information in the width and height parameters.
25038      * </p>
25039      *
25040      * <p>
25041      * The actual measurement work of a view is performed in
25042      * {@link #onMeasure(int, int)}, called by this method. Therefore, only
25043      * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
25044      * </p>
25045      *
25046      *
25047      * @param widthMeasureSpec Horizontal space requirements as imposed by the
25048      *        parent
25049      * @param heightMeasureSpec Vertical space requirements as imposed by the
25050      *        parent
25051      *
25052      * @see #onMeasure(int, int)
25053      */
measure(int widthMeasureSpec, int heightMeasureSpec)25054     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
25055         boolean optical = isLayoutModeOptical(this);
25056         if (optical != isLayoutModeOptical(mParent)) {
25057             Insets insets = getOpticalInsets();
25058             int oWidth  = insets.left + insets.right;
25059             int oHeight = insets.top  + insets.bottom;
25060             widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
25061             heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
25062         }
25063 
25064         // Suppress sign extension for the low bytes
25065         long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
25066         if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
25067 
25068         final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
25069 
25070         // Optimize layout by avoiding an extra EXACTLY pass when the view is
25071         // already measured as the correct size. In API 23 and below, this
25072         // extra pass is required to make LinearLayout re-distribute weight.
25073         final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
25074                 || heightMeasureSpec != mOldHeightMeasureSpec;
25075         final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
25076                 && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
25077         final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
25078                 && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
25079         final boolean needsLayout = specChanged
25080                 && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
25081 
25082         if (forceLayout || needsLayout) {
25083             // first clears the measured dimension flag
25084             mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
25085 
25086             resolveRtlPropertiesIfNeeded();
25087 
25088             int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
25089             if (cacheIndex < 0 || sIgnoreMeasureCache) {
25090                 // measure ourselves, this should set the measured dimension flag back
25091                 onMeasure(widthMeasureSpec, heightMeasureSpec);
25092                 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
25093             } else {
25094                 long value = mMeasureCache.valueAt(cacheIndex);
25095                 // Casting a long to int drops the high 32 bits, no mask needed
25096                 setMeasuredDimensionRaw((int) (value >> 32), (int) value);
25097                 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
25098             }
25099 
25100             // flag not set, setMeasuredDimension() was not invoked, we raise
25101             // an exception to warn the developer
25102             if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
25103                 throw new IllegalStateException("View with id " + getId() + ": "
25104                         + getClass().getName() + "#onMeasure() did not set the"
25105                         + " measured dimension by calling"
25106                         + " setMeasuredDimension()");
25107             }
25108 
25109             mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
25110         }
25111 
25112         mOldWidthMeasureSpec = widthMeasureSpec;
25113         mOldHeightMeasureSpec = heightMeasureSpec;
25114 
25115         mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
25116                 (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
25117     }
25118 
25119     /**
25120      * <p>
25121      * Measure the view and its content to determine the measured width and the
25122      * measured height. This method is invoked by {@link #measure(int, int)} and
25123      * should be overridden by subclasses to provide accurate and efficient
25124      * measurement of their contents.
25125      * </p>
25126      *
25127      * <p>
25128      * <strong>CONTRACT:</strong> When overriding this method, you
25129      * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
25130      * measured width and height of this view. Failure to do so will trigger an
25131      * <code>IllegalStateException</code>, thrown by
25132      * {@link #measure(int, int)}. Calling the superclass'
25133      * {@link #onMeasure(int, int)} is a valid use.
25134      * </p>
25135      *
25136      * <p>
25137      * The base class implementation of measure defaults to the background size,
25138      * unless a larger size is allowed by the MeasureSpec. Subclasses should
25139      * override {@link #onMeasure(int, int)} to provide better measurements of
25140      * their content.
25141      * </p>
25142      *
25143      * <p>
25144      * If this method is overridden, it is the subclass's responsibility to make
25145      * sure the measured height and width are at least the view's minimum height
25146      * and width ({@link #getSuggestedMinimumHeight()} and
25147      * {@link #getSuggestedMinimumWidth()}).
25148      * </p>
25149      *
25150      * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
25151      *                         The requirements are encoded with
25152      *                         {@link android.view.View.MeasureSpec}.
25153      * @param heightMeasureSpec vertical space requirements as imposed by the parent.
25154      *                         The requirements are encoded with
25155      *                         {@link android.view.View.MeasureSpec}.
25156      *
25157      * @see #getMeasuredWidth()
25158      * @see #getMeasuredHeight()
25159      * @see #setMeasuredDimension(int, int)
25160      * @see #getSuggestedMinimumHeight()
25161      * @see #getSuggestedMinimumWidth()
25162      * @see android.view.View.MeasureSpec#getMode(int)
25163      * @see android.view.View.MeasureSpec#getSize(int)
25164      */
onMeasure(int widthMeasureSpec, int heightMeasureSpec)25165     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
25166         setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
25167                 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
25168     }
25169 
25170     /**
25171      * <p>This method must be called by {@link #onMeasure(int, int)} to store the
25172      * measured width and measured height. Failing to do so will trigger an
25173      * exception at measurement time.</p>
25174      *
25175      * @param measuredWidth The measured width of this view.  May be a complex
25176      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
25177      * {@link #MEASURED_STATE_TOO_SMALL}.
25178      * @param measuredHeight The measured height of this view.  May be a complex
25179      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
25180      * {@link #MEASURED_STATE_TOO_SMALL}.
25181      */
setMeasuredDimension(int measuredWidth, int measuredHeight)25182     protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
25183         boolean optical = isLayoutModeOptical(this);
25184         if (optical != isLayoutModeOptical(mParent)) {
25185             Insets insets = getOpticalInsets();
25186             int opticalWidth  = insets.left + insets.right;
25187             int opticalHeight = insets.top  + insets.bottom;
25188 
25189             measuredWidth  += optical ? opticalWidth  : -opticalWidth;
25190             measuredHeight += optical ? opticalHeight : -opticalHeight;
25191         }
25192         setMeasuredDimensionRaw(measuredWidth, measuredHeight);
25193     }
25194 
25195     /**
25196      * Sets the measured dimension without extra processing for things like optical bounds.
25197      * Useful for reapplying consistent values that have already been cooked with adjustments
25198      * for optical bounds, etc. such as those from the measurement cache.
25199      *
25200      * @param measuredWidth The measured width of this view.  May be a complex
25201      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
25202      * {@link #MEASURED_STATE_TOO_SMALL}.
25203      * @param measuredHeight The measured height of this view.  May be a complex
25204      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
25205      * {@link #MEASURED_STATE_TOO_SMALL}.
25206      */
setMeasuredDimensionRaw(int measuredWidth, int measuredHeight)25207     private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
25208         mMeasuredWidth = measuredWidth;
25209         mMeasuredHeight = measuredHeight;
25210 
25211         mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
25212     }
25213 
25214     /**
25215      * Merge two states as returned by {@link #getMeasuredState()}.
25216      * @param curState The current state as returned from a view or the result
25217      * of combining multiple views.
25218      * @param newState The new view state to combine.
25219      * @return Returns a new integer reflecting the combination of the two
25220      * states.
25221      */
combineMeasuredStates(int curState, int newState)25222     public static int combineMeasuredStates(int curState, int newState) {
25223         return curState | newState;
25224     }
25225 
25226     /**
25227      * Version of {@link #resolveSizeAndState(int, int, int)}
25228      * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
25229      */
resolveSize(int size, int measureSpec)25230     public static int resolveSize(int size, int measureSpec) {
25231         return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
25232     }
25233 
25234     /**
25235      * Utility to reconcile a desired size and state, with constraints imposed
25236      * by a MeasureSpec. Will take the desired size, unless a different size
25237      * is imposed by the constraints. The returned value is a compound integer,
25238      * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
25239      * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
25240      * resulting size is smaller than the size the view wants to be.
25241      *
25242      * @param size How big the view wants to be.
25243      * @param measureSpec Constraints imposed by the parent.
25244      * @param childMeasuredState Size information bit mask for the view's
25245      *                           children.
25246      * @return Size information bit mask as defined by
25247      *         {@link #MEASURED_SIZE_MASK} and
25248      *         {@link #MEASURED_STATE_TOO_SMALL}.
25249      */
resolveSizeAndState(int size, int measureSpec, int childMeasuredState)25250     public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
25251         final int specMode = MeasureSpec.getMode(measureSpec);
25252         final int specSize = MeasureSpec.getSize(measureSpec);
25253         final int result;
25254         switch (specMode) {
25255             case MeasureSpec.AT_MOST:
25256                 if (specSize < size) {
25257                     result = specSize | MEASURED_STATE_TOO_SMALL;
25258                 } else {
25259                     result = size;
25260                 }
25261                 break;
25262             case MeasureSpec.EXACTLY:
25263                 result = specSize;
25264                 break;
25265             case MeasureSpec.UNSPECIFIED:
25266             default:
25267                 result = size;
25268         }
25269         return result | (childMeasuredState & MEASURED_STATE_MASK);
25270     }
25271 
25272     /**
25273      * Utility to return a default size. Uses the supplied size if the
25274      * MeasureSpec imposed no constraints. Will get larger if allowed
25275      * by the MeasureSpec.
25276      *
25277      * @param size Default size for this view
25278      * @param measureSpec Constraints imposed by the parent
25279      * @return The size this view should be.
25280      */
getDefaultSize(int size, int measureSpec)25281     public static int getDefaultSize(int size, int measureSpec) {
25282         int result = size;
25283         int specMode = MeasureSpec.getMode(measureSpec);
25284         int specSize = MeasureSpec.getSize(measureSpec);
25285 
25286         switch (specMode) {
25287         case MeasureSpec.UNSPECIFIED:
25288             result = size;
25289             break;
25290         case MeasureSpec.AT_MOST:
25291         case MeasureSpec.EXACTLY:
25292             result = specSize;
25293             break;
25294         }
25295         return result;
25296     }
25297 
25298     /**
25299      * Returns the suggested minimum height that the view should use. This
25300      * returns the maximum of the view's minimum height
25301      * and the background's minimum height
25302      * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
25303      * <p>
25304      * When being used in {@link #onMeasure(int, int)}, the caller should still
25305      * ensure the returned height is within the requirements of the parent.
25306      *
25307      * @return The suggested minimum height of the view.
25308      */
getSuggestedMinimumHeight()25309     protected int getSuggestedMinimumHeight() {
25310         return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
25311 
25312     }
25313 
25314     /**
25315      * Returns the suggested minimum width that the view should use. This
25316      * returns the maximum of the view's minimum width
25317      * and the background's minimum width
25318      *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
25319      * <p>
25320      * When being used in {@link #onMeasure(int, int)}, the caller should still
25321      * ensure the returned width is within the requirements of the parent.
25322      *
25323      * @return The suggested minimum width of the view.
25324      */
getSuggestedMinimumWidth()25325     protected int getSuggestedMinimumWidth() {
25326         return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
25327     }
25328 
25329     /**
25330      * Returns the minimum height of the view.
25331      *
25332      * @return the minimum height the view will try to be, in pixels
25333      *
25334      * @see #setMinimumHeight(int)
25335      *
25336      * @attr ref android.R.styleable#View_minHeight
25337      */
25338     @InspectableProperty(name = "minHeight")
getMinimumHeight()25339     public int getMinimumHeight() {
25340         return mMinHeight;
25341     }
25342 
25343     /**
25344      * Sets the minimum height of the view. It is not guaranteed the view will
25345      * be able to achieve this minimum height (for example, if its parent layout
25346      * constrains it with less available height).
25347      *
25348      * @param minHeight The minimum height the view will try to be, in pixels
25349      *
25350      * @see #getMinimumHeight()
25351      *
25352      * @attr ref android.R.styleable#View_minHeight
25353      */
25354     @RemotableViewMethod
setMinimumHeight(int minHeight)25355     public void setMinimumHeight(int minHeight) {
25356         mMinHeight = minHeight;
25357         requestLayout();
25358     }
25359 
25360     /**
25361      * Returns the minimum width of the view.
25362      *
25363      * @return the minimum width the view will try to be, in pixels
25364      *
25365      * @see #setMinimumWidth(int)
25366      *
25367      * @attr ref android.R.styleable#View_minWidth
25368      */
25369     @InspectableProperty(name = "minWidth")
getMinimumWidth()25370     public int getMinimumWidth() {
25371         return mMinWidth;
25372     }
25373 
25374     /**
25375      * Sets the minimum width of the view. It is not guaranteed the view will
25376      * be able to achieve this minimum width (for example, if its parent layout
25377      * constrains it with less available width).
25378      *
25379      * @param minWidth The minimum width the view will try to be, in pixels
25380      *
25381      * @see #getMinimumWidth()
25382      *
25383      * @attr ref android.R.styleable#View_minWidth
25384      */
setMinimumWidth(int minWidth)25385     public void setMinimumWidth(int minWidth) {
25386         mMinWidth = minWidth;
25387         requestLayout();
25388 
25389     }
25390 
25391     /**
25392      * Get the animation currently associated with this view.
25393      *
25394      * @return The animation that is currently playing or
25395      *         scheduled to play for this view.
25396      */
getAnimation()25397     public Animation getAnimation() {
25398         return mCurrentAnimation;
25399     }
25400 
25401     /**
25402      * Start the specified animation now.
25403      *
25404      * @param animation the animation to start now
25405      */
startAnimation(Animation animation)25406     public void startAnimation(Animation animation) {
25407         animation.setStartTime(Animation.START_ON_FIRST_FRAME);
25408         setAnimation(animation);
25409         invalidateParentCaches();
25410         invalidate(true);
25411     }
25412 
25413     /**
25414      * Cancels any animations for this view.
25415      */
clearAnimation()25416     public void clearAnimation() {
25417         if (mCurrentAnimation != null) {
25418             mCurrentAnimation.detach();
25419         }
25420         mCurrentAnimation = null;
25421         invalidateParentIfNeeded();
25422     }
25423 
25424     /**
25425      * Sets the next animation to play for this view.
25426      * If you want the animation to play immediately, use
25427      * {@link #startAnimation(android.view.animation.Animation)} instead.
25428      * This method provides allows fine-grained
25429      * control over the start time and invalidation, but you
25430      * must make sure that 1) the animation has a start time set, and
25431      * 2) the view's parent (which controls animations on its children)
25432      * will be invalidated when the animation is supposed to
25433      * start.
25434      *
25435      * @param animation The next animation, or null.
25436      */
setAnimation(Animation animation)25437     public void setAnimation(Animation animation) {
25438         mCurrentAnimation = animation;
25439 
25440         if (animation != null) {
25441             // If the screen is off assume the animation start time is now instead of
25442             // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
25443             // would cause the animation to start when the screen turns back on
25444             if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
25445                     && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
25446                 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
25447             }
25448             animation.reset();
25449         }
25450     }
25451 
25452     /**
25453      * Invoked by a parent ViewGroup to notify the start of the animation
25454      * currently associated with this view. If you override this method,
25455      * always call super.onAnimationStart();
25456      *
25457      * @see #setAnimation(android.view.animation.Animation)
25458      * @see #getAnimation()
25459      */
25460     @CallSuper
onAnimationStart()25461     protected void onAnimationStart() {
25462         mPrivateFlags |= PFLAG_ANIMATION_STARTED;
25463     }
25464 
25465     /**
25466      * Invoked by a parent ViewGroup to notify the end of the animation
25467      * currently associated with this view. If you override this method,
25468      * always call super.onAnimationEnd();
25469      *
25470      * @see #setAnimation(android.view.animation.Animation)
25471      * @see #getAnimation()
25472      */
25473     @CallSuper
onAnimationEnd()25474     protected void onAnimationEnd() {
25475         mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
25476     }
25477 
25478     /**
25479      * Invoked if there is a Transform that involves alpha. Subclass that can
25480      * draw themselves with the specified alpha should return true, and then
25481      * respect that alpha when their onDraw() is called. If this returns false
25482      * then the view may be redirected to draw into an offscreen buffer to
25483      * fulfill the request, which will look fine, but may be slower than if the
25484      * subclass handles it internally. The default implementation returns false.
25485      *
25486      * @param alpha The alpha (0..255) to apply to the view's drawing
25487      * @return true if the view can draw with the specified alpha.
25488      */
onSetAlpha(int alpha)25489     protected boolean onSetAlpha(int alpha) {
25490         return false;
25491     }
25492 
25493     /**
25494      * This is used by the RootView to perform an optimization when
25495      * the view hierarchy contains one or several SurfaceView.
25496      * SurfaceView is always considered transparent, but its children are not,
25497      * therefore all View objects remove themselves from the global transparent
25498      * region (passed as a parameter to this function).
25499      *
25500      * @param region The transparent region for this ViewAncestor (window).
25501      *
25502      * @return Returns true if the effective visibility of the view at this
25503      * point is opaque, regardless of the transparent region; returns false
25504      * if it is possible for underlying windows to be seen behind the view.
25505      *
25506      * {@hide}
25507      */
25508     @UnsupportedAppUsage
gatherTransparentRegion(Region region)25509     public boolean gatherTransparentRegion(Region region) {
25510         final AttachInfo attachInfo = mAttachInfo;
25511         if (region != null && attachInfo != null) {
25512             final int pflags = mPrivateFlags;
25513             if ((pflags & PFLAG_SKIP_DRAW) == 0) {
25514                 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
25515                 // remove it from the transparent region.
25516                 final int[] location = attachInfo.mTransparentLocation;
25517                 getLocationInWindow(location);
25518                 // When a view has Z value, then it will be better to leave some area below the view
25519                 // for drawing shadow. The shadow outset is proportional to the Z value. Note that
25520                 // the bottom part needs more offset than the left, top and right parts due to the
25521                 // spot light effects.
25522                 int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
25523                 region.op(location[0] - shadowOffset, location[1] - shadowOffset,
25524                         location[0] + mRight - mLeft + shadowOffset,
25525                         location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
25526             } else {
25527                 if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
25528                     // The SKIP_DRAW flag IS set and the background drawable exists, we remove
25529                     // the background drawable's non-transparent parts from this transparent region.
25530                     applyDrawableToTransparentRegion(mBackground, region);
25531                 }
25532                 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
25533                         && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
25534                     // Similarly, we remove the foreground drawable's non-transparent parts.
25535                     applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
25536                 }
25537                 if (mDefaultFocusHighlight != null
25538                         && mDefaultFocusHighlight.getOpacity() != PixelFormat.TRANSPARENT) {
25539                     // Similarly, we remove the default focus highlight's non-transparent parts.
25540                     applyDrawableToTransparentRegion(mDefaultFocusHighlight, region);
25541                 }
25542             }
25543         }
25544         return true;
25545     }
25546 
25547     /**
25548      * Play a sound effect for this view.
25549      *
25550      * <p>The framework will play sound effects for some built in actions, such as
25551      * clicking, but you may wish to play these effects in your widget,
25552      * for instance, for internal navigation.
25553      *
25554      * <p>The sound effect will only be played if sound effects are enabled by the user, and
25555      * {@link #isSoundEffectsEnabled()} is true.
25556      *
25557      * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
25558      */
playSoundEffect(int soundConstant)25559     public void playSoundEffect(int soundConstant) {
25560         if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
25561             return;
25562         }
25563         mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
25564     }
25565 
25566     /**
25567      * BZZZTT!!1!
25568      *
25569      * <p>Provide haptic feedback to the user for this view.
25570      *
25571      * <p>The framework will provide haptic feedback for some built in actions,
25572      * such as long presses, but you may wish to provide feedback for your
25573      * own widget.
25574      *
25575      * <p>The feedback will only be performed if
25576      * {@link #isHapticFeedbackEnabled()} is true.
25577      *
25578      * @param feedbackConstant One of the constants defined in
25579      * {@link HapticFeedbackConstants}
25580      */
performHapticFeedback(int feedbackConstant)25581     public boolean performHapticFeedback(int feedbackConstant) {
25582         return performHapticFeedback(feedbackConstant, 0);
25583     }
25584 
25585     /**
25586      * BZZZTT!!1!
25587      *
25588      * <p>Like {@link #performHapticFeedback(int)}, with additional options.
25589      *
25590      * @param feedbackConstant One of the constants defined in
25591      * {@link HapticFeedbackConstants}
25592      * @param flags Additional flags as per {@link HapticFeedbackConstants}.
25593      */
performHapticFeedback(int feedbackConstant, int flags)25594     public boolean performHapticFeedback(int feedbackConstant, int flags) {
25595         if (mAttachInfo == null) {
25596             return false;
25597         }
25598         //noinspection SimplifiableIfStatement
25599         if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
25600                 && !isHapticFeedbackEnabled()) {
25601             return false;
25602         }
25603         return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
25604                 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
25605     }
25606 
25607     /**
25608      * Request that the visibility of the status bar or other screen/window
25609      * decorations be changed.
25610      *
25611      * <p>This method is used to put the over device UI into temporary modes
25612      * where the user's attention is focused more on the application content,
25613      * by dimming or hiding surrounding system affordances.  This is typically
25614      * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
25615      * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
25616      * to be placed behind the action bar (and with these flags other system
25617      * affordances) so that smooth transitions between hiding and showing them
25618      * can be done.
25619      *
25620      * <p>Two representative examples of the use of system UI visibility is
25621      * implementing a content browsing application (like a magazine reader)
25622      * and a video playing application.
25623      *
25624      * <p>The first code shows a typical implementation of a View in a content
25625      * browsing application.  In this implementation, the application goes
25626      * into a content-oriented mode by hiding the status bar and action bar,
25627      * and putting the navigation elements into lights out mode.  The user can
25628      * then interact with content while in this mode.  Such an application should
25629      * provide an easy way for the user to toggle out of the mode (such as to
25630      * check information in the status bar or access notifications).  In the
25631      * implementation here, this is done simply by tapping on the content.
25632      *
25633      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
25634      *      content}
25635      *
25636      * <p>This second code sample shows a typical implementation of a View
25637      * in a video playing application.  In this situation, while the video is
25638      * playing the application would like to go into a complete full-screen mode,
25639      * to use as much of the display as possible for the video.  When in this state
25640      * the user can not interact with the application; the system intercepts
25641      * touching on the screen to pop the UI out of full screen mode.  See
25642      * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
25643      *
25644      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
25645      *      content}
25646      *
25647      * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
25648      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
25649      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
25650      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
25651      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
25652      */
setSystemUiVisibility(int visibility)25653     public void setSystemUiVisibility(int visibility) {
25654         if (visibility != mSystemUiVisibility) {
25655             mSystemUiVisibility = visibility;
25656             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
25657                 mParent.recomputeViewAttributes(this);
25658             }
25659         }
25660     }
25661 
25662     /**
25663      * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
25664      * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
25665      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
25666      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
25667      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
25668      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
25669      */
getSystemUiVisibility()25670     public int getSystemUiVisibility() {
25671         return mSystemUiVisibility;
25672     }
25673 
25674     /**
25675      * Returns the current system UI visibility that is currently set for
25676      * the entire window.  This is the combination of the
25677      * {@link #setSystemUiVisibility(int)} values supplied by all of the
25678      * views in the window.
25679      */
getWindowSystemUiVisibility()25680     public int getWindowSystemUiVisibility() {
25681         return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
25682     }
25683 
25684     /**
25685      * Override to find out when the window's requested system UI visibility
25686      * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
25687      * This is different from the callbacks received through
25688      * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
25689      * in that this is only telling you about the local request of the window,
25690      * not the actual values applied by the system.
25691      */
onWindowSystemUiVisibilityChanged(int visible)25692     public void onWindowSystemUiVisibilityChanged(int visible) {
25693     }
25694 
25695     /**
25696      * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
25697      * the view hierarchy.
25698      */
dispatchWindowSystemUiVisiblityChanged(int visible)25699     public void dispatchWindowSystemUiVisiblityChanged(int visible) {
25700         onWindowSystemUiVisibilityChanged(visible);
25701     }
25702 
25703     /**
25704      * Set a listener to receive callbacks when the visibility of the system bar changes.
25705      * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
25706      */
setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l)25707     public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
25708         getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
25709         if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
25710             mParent.recomputeViewAttributes(this);
25711         }
25712     }
25713 
25714     /**
25715      * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
25716      * the view hierarchy.
25717      */
dispatchSystemUiVisibilityChanged(int visibility)25718     public void dispatchSystemUiVisibilityChanged(int visibility) {
25719         ListenerInfo li = mListenerInfo;
25720         if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
25721             li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
25722                     visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
25723         }
25724     }
25725 
updateLocalSystemUiVisibility(int localValue, int localChanges)25726     boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
25727         int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
25728         if (val != mSystemUiVisibility) {
25729             setSystemUiVisibility(val);
25730             return true;
25731         }
25732         return false;
25733     }
25734 
25735     /** @hide */
25736     @UnsupportedAppUsage
setDisabledSystemUiVisibility(int flags)25737     public void setDisabledSystemUiVisibility(int flags) {
25738         if (mAttachInfo != null) {
25739             if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
25740                 mAttachInfo.mDisabledSystemUiVisibility = flags;
25741                 if (mParent != null) {
25742                     mParent.recomputeViewAttributes(this);
25743                 }
25744             }
25745         }
25746     }
25747 
25748     /**
25749      * Creates an image that the system displays during the drag and drop
25750      * operation. This is called a &quot;drag shadow&quot;. The default implementation
25751      * for a DragShadowBuilder based on a View returns an image that has exactly the same
25752      * appearance as the given View. The default also positions the center of the drag shadow
25753      * directly under the touch point. If no View is provided (the constructor with no parameters
25754      * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
25755      * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
25756      * default is an invisible drag shadow.
25757      * <p>
25758      * You are not required to use the View you provide to the constructor as the basis of the
25759      * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
25760      * anything you want as the drag shadow.
25761      * </p>
25762      * <p>
25763      *  You pass a DragShadowBuilder object to the system when you start the drag. The system
25764      *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
25765      *  size and position of the drag shadow. It uses this data to construct a
25766      *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
25767      *  so that your application can draw the shadow image in the Canvas.
25768      * </p>
25769      *
25770      * <div class="special reference">
25771      * <h3>Developer Guides</h3>
25772      * <p>For a guide to implementing drag and drop features, read the
25773      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
25774      * </div>
25775      */
25776     public static class DragShadowBuilder {
25777         @UnsupportedAppUsage
25778         private final WeakReference<View> mView;
25779 
25780         /**
25781          * Constructs a shadow image builder based on a View. By default, the resulting drag
25782          * shadow will have the same appearance and dimensions as the View, with the touch point
25783          * over the center of the View.
25784          * @param view A View. Any View in scope can be used.
25785          */
DragShadowBuilder(View view)25786         public DragShadowBuilder(View view) {
25787             mView = new WeakReference<View>(view);
25788         }
25789 
25790         /**
25791          * Construct a shadow builder object with no associated View.  This
25792          * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
25793          * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
25794          * to supply the drag shadow's dimensions and appearance without
25795          * reference to any View object.
25796          */
DragShadowBuilder()25797         public DragShadowBuilder() {
25798             mView = new WeakReference<View>(null);
25799         }
25800 
25801         /**
25802          * Returns the View object that had been passed to the
25803          * {@link #DragShadowBuilder(View)}
25804          * constructor.  If that View parameter was {@code null} or if the
25805          * {@link #DragShadowBuilder()}
25806          * constructor was used to instantiate the builder object, this method will return
25807          * null.
25808          *
25809          * @return The View object associate with this builder object.
25810          */
25811         @SuppressWarnings({"JavadocReference"})
getView()25812         final public View getView() {
25813             return mView.get();
25814         }
25815 
25816         /**
25817          * Provides the metrics for the shadow image. These include the dimensions of
25818          * the shadow image, and the point within that shadow that should
25819          * be centered under the touch location while dragging.
25820          * <p>
25821          * The default implementation sets the dimensions of the shadow to be the
25822          * same as the dimensions of the View itself and centers the shadow under
25823          * the touch point.
25824          * </p>
25825          *
25826          * @param outShadowSize A {@link android.graphics.Point} containing the width and height
25827          * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
25828          * desired width and must set {@link android.graphics.Point#y} to the desired height of the
25829          * image. Since Android P, the width and height must be positive values.
25830          *
25831          * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
25832          * shadow image that should be underneath the touch point during the drag and drop
25833          * operation. Your application must set {@link android.graphics.Point#x} to the
25834          * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
25835          */
onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint)25836         public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
25837             final View view = mView.get();
25838             if (view != null) {
25839                 outShadowSize.set(view.getWidth(), view.getHeight());
25840                 outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
25841             } else {
25842                 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
25843             }
25844         }
25845 
25846         /**
25847          * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
25848          * based on the dimensions it received from the
25849          * {@link #onProvideShadowMetrics(Point, Point)} callback.
25850          *
25851          * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
25852          */
onDrawShadow(Canvas canvas)25853         public void onDrawShadow(Canvas canvas) {
25854             final View view = mView.get();
25855             if (view != null) {
25856                 view.draw(canvas);
25857             } else {
25858                 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
25859             }
25860         }
25861     }
25862 
25863     /**
25864      * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
25865      * startDragAndDrop()} for newer platform versions.
25866      */
25867     @Deprecated
startDrag(ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flags)25868     public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
25869                                    Object myLocalState, int flags) {
25870         return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
25871     }
25872 
25873     /**
25874      * Starts a drag and drop operation. When your application calls this method, it passes a
25875      * {@link android.view.View.DragShadowBuilder} object to the system. The
25876      * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
25877      * to get metrics for the drag shadow, and then calls the object's
25878      * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
25879      * <p>
25880      *  Once the system has the drag shadow, it begins the drag and drop operation by sending
25881      *  drag events to all the View objects in your application that are currently visible. It does
25882      *  this either by calling the View object's drag listener (an implementation of
25883      *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
25884      *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
25885      *  Both are passed a {@link android.view.DragEvent} object that has a
25886      *  {@link android.view.DragEvent#getAction()} value of
25887      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
25888      * </p>
25889      * <p>
25890      * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
25891      * int) startDragAndDrop()} on any attached View object. The View object does not need to be
25892      * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
25893      * to the View the user selected for dragging.
25894      * </p>
25895      * @param data A {@link android.content.ClipData} object pointing to the data to be
25896      * transferred by the drag and drop operation.
25897      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
25898      * drag shadow.
25899      * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
25900      * drop operation. When dispatching drag events to views in the same activity this object
25901      * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other
25902      * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()}
25903      * will return null).
25904      * <p>
25905      * myLocalState is a lightweight mechanism for the sending information from the dragged View
25906      * to the target Views. For example, it can contain flags that differentiate between a
25907      * a copy operation and a move operation.
25908      * </p>
25909      * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
25910      * flags, or any combination of the following:
25911      *     <ul>
25912      *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
25913      *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
25914      *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
25915      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
25916      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
25917      *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
25918      *     </ul>
25919      * @return {@code true} if the method completes successfully, or
25920      * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
25921      * do a drag because of another ongoing operation or some other reasons.
25922      */
startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flags)25923     public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
25924             Object myLocalState, int flags) {
25925         if (ViewDebug.DEBUG_DRAG) {
25926             Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
25927         }
25928         if (mAttachInfo == null) {
25929             Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
25930             return false;
25931         }
25932         if (!mAttachInfo.mViewRootImpl.mSurface.isValid()) {
25933             Log.w(VIEW_LOG_TAG, "startDragAndDrop called with an invalid surface.");
25934             return false;
25935         }
25936 
25937         if (data != null) {
25938             data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0);
25939         }
25940 
25941         Point shadowSize = new Point();
25942         Point shadowTouchPoint = new Point();
25943         shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
25944 
25945         if ((shadowSize.x < 0) || (shadowSize.y < 0)
25946                 || (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
25947             throw new IllegalStateException("Drag shadow dimensions must not be negative");
25948         }
25949 
25950         // Create 1x1 surface when zero surface size is specified because SurfaceControl.Builder
25951         // does not accept zero size surface.
25952         if (shadowSize.x == 0  || shadowSize.y == 0) {
25953             if (!sAcceptZeroSizeDragShadow) {
25954                 throw new IllegalStateException("Drag shadow dimensions must be positive");
25955             }
25956             shadowSize.x = 1;
25957             shadowSize.y = 1;
25958         }
25959 
25960         if (ViewDebug.DEBUG_DRAG) {
25961             Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
25962                     + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
25963         }
25964 
25965         final ViewRootImpl root = mAttachInfo.mViewRootImpl;
25966         final SurfaceSession session = new SurfaceSession();
25967         final SurfaceControl surfaceControl = new SurfaceControl.Builder(session)
25968                 .setName("drag surface")
25969                 .setParent(root.getSurfaceControl())
25970                 .setBufferSize(shadowSize.x, shadowSize.y)
25971                 .setFormat(PixelFormat.TRANSLUCENT)
25972                 .build();
25973         final Surface surface = new Surface();
25974         surface.copyFrom(surfaceControl);
25975         IBinder token = null;
25976         try {
25977             final Canvas canvas = surface.lockCanvas(null);
25978             try {
25979                 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
25980                 shadowBuilder.onDrawShadow(canvas);
25981             } finally {
25982                 surface.unlockCanvasAndPost(canvas);
25983             }
25984 
25985             // repurpose 'shadowSize' for the last touch point
25986             root.getLastTouchPoint(shadowSize);
25987 
25988             token = mAttachInfo.mSession.performDrag(
25989                     mAttachInfo.mWindow, flags, surfaceControl, root.getLastTouchSource(),
25990                     shadowSize.x, shadowSize.y, shadowTouchPoint.x, shadowTouchPoint.y, data);
25991             if (ViewDebug.DEBUG_DRAG) {
25992                 Log.d(VIEW_LOG_TAG, "performDrag returned " + token);
25993             }
25994             if (token != null) {
25995                 if (mAttachInfo.mDragSurface != null) {
25996                     mAttachInfo.mDragSurface.release();
25997                 }
25998                 mAttachInfo.mDragSurface = surface;
25999                 mAttachInfo.mDragToken = token;
26000                 // Cache the local state object for delivery with DragEvents
26001                 root.setLocalDragState(myLocalState);
26002             }
26003             return token != null;
26004         } catch (Exception e) {
26005             Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
26006             return false;
26007         } finally {
26008             if (token == null) {
26009                 surface.destroy();
26010             }
26011             session.kill();
26012         }
26013     }
26014 
26015     /**
26016      * Cancels an ongoing drag and drop operation.
26017      * <p>
26018      * A {@link android.view.DragEvent} object with
26019      * {@link android.view.DragEvent#getAction()} value of
26020      * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
26021      * {@link android.view.DragEvent#getResult()} value of {@code false}
26022      * will be sent to every
26023      * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
26024      * even if they are not currently visible.
26025      * </p>
26026      * <p>
26027      * This method can be called on any View in the same window as the View on which
26028      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
26029      * was called.
26030      * </p>
26031      */
cancelDragAndDrop()26032     public final void cancelDragAndDrop() {
26033         if (ViewDebug.DEBUG_DRAG) {
26034             Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
26035         }
26036         if (mAttachInfo == null) {
26037             Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
26038             return;
26039         }
26040         if (mAttachInfo.mDragToken != null) {
26041             try {
26042                 mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken, false);
26043             } catch (Exception e) {
26044                 Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
26045             }
26046             mAttachInfo.mDragToken = null;
26047         } else {
26048             Log.e(VIEW_LOG_TAG, "No active drag to cancel");
26049         }
26050     }
26051 
26052     /**
26053      * Updates the drag shadow for the ongoing drag and drop operation.
26054      *
26055      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
26056      * new drag shadow.
26057      */
updateDragShadow(DragShadowBuilder shadowBuilder)26058     public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
26059         if (ViewDebug.DEBUG_DRAG) {
26060             Log.d(VIEW_LOG_TAG, "updateDragShadow");
26061         }
26062         if (mAttachInfo == null) {
26063             Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
26064             return;
26065         }
26066         if (mAttachInfo.mDragToken != null) {
26067             try {
26068                 Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
26069                 try {
26070                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
26071                     shadowBuilder.onDrawShadow(canvas);
26072                 } finally {
26073                     mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
26074                 }
26075             } catch (Exception e) {
26076                 Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
26077             }
26078         } else {
26079             Log.e(VIEW_LOG_TAG, "No active drag");
26080         }
26081     }
26082 
26083     /**
26084      * Starts a move from {startX, startY}, the amount of the movement will be the offset
26085      * between {startX, startY} and the new cursor positon.
26086      * @param startX horizontal coordinate where the move started.
26087      * @param startY vertical coordinate where the move started.
26088      * @return whether moving was started successfully.
26089      * @hide
26090      */
startMovingTask(float startX, float startY)26091     public final boolean startMovingTask(float startX, float startY) {
26092         if (ViewDebug.DEBUG_POSITIONING) {
26093             Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
26094         }
26095         try {
26096             return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
26097         } catch (RemoteException e) {
26098             Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
26099         }
26100         return false;
26101     }
26102 
26103     /**
26104      * Finish a window move task.
26105      * @hide
26106      */
finishMovingTask()26107     public void finishMovingTask() {
26108         if (ViewDebug.DEBUG_POSITIONING) {
26109             Log.d(VIEW_LOG_TAG, "finishMovingTask");
26110         }
26111         try {
26112             mAttachInfo.mSession.finishMovingTask(mAttachInfo.mWindow);
26113         } catch (RemoteException e) {
26114             Log.e(VIEW_LOG_TAG, "Unable to finish moving", e);
26115         }
26116     }
26117 
26118     /**
26119      * Handles drag events sent by the system following a call to
26120      * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
26121      * startDragAndDrop()}.
26122      *<p>
26123      * When the system calls this method, it passes a
26124      * {@link android.view.DragEvent} object. A call to
26125      * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
26126      * in DragEvent. The method uses these to determine what is happening in the drag and drop
26127      * operation.
26128      * @param event The {@link android.view.DragEvent} sent by the system.
26129      * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
26130      * in DragEvent, indicating the type of drag event represented by this object.
26131      * @return {@code true} if the method was successful, otherwise {@code false}.
26132      * <p>
26133      *  The method should return {@code true} in response to an action type of
26134      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
26135      *  operation.
26136      * </p>
26137      * <p>
26138      *  The method should also return {@code true} in response to an action type of
26139      *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
26140      *  {@code false} if it didn't.
26141      * </p>
26142      * <p>
26143      *  For all other events, the return value is ignored.
26144      * </p>
26145      */
onDragEvent(DragEvent event)26146     public boolean onDragEvent(DragEvent event) {
26147         return false;
26148     }
26149 
26150     // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps.
dispatchDragEnterExitInPreN(DragEvent event)26151     boolean dispatchDragEnterExitInPreN(DragEvent event) {
26152         return callDragEventHandler(event);
26153     }
26154 
26155     /**
26156      * Detects if this View is enabled and has a drag event listener.
26157      * If both are true, then it calls the drag event listener with the
26158      * {@link android.view.DragEvent} it received. If the drag event listener returns
26159      * {@code true}, then dispatchDragEvent() returns {@code true}.
26160      * <p>
26161      * For all other cases, the method calls the
26162      * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
26163      * method and returns its result.
26164      * </p>
26165      * <p>
26166      * This ensures that a drag event is always consumed, even if the View does not have a drag
26167      * event listener. However, if the View has a listener and the listener returns true, then
26168      * onDragEvent() is not called.
26169      * </p>
26170      */
dispatchDragEvent(DragEvent event)26171     public boolean dispatchDragEvent(DragEvent event) {
26172         event.mEventHandlerWasCalled = true;
26173         if (event.mAction == DragEvent.ACTION_DRAG_LOCATION ||
26174             event.mAction == DragEvent.ACTION_DROP) {
26175             // About to deliver an event with coordinates to this view. Notify that now this view
26176             // has drag focus. This will send exit/enter events as needed.
26177             getViewRootImpl().setDragFocus(this, event);
26178         }
26179         return callDragEventHandler(event);
26180     }
26181 
callDragEventHandler(DragEvent event)26182     final boolean callDragEventHandler(DragEvent event) {
26183         final boolean result;
26184 
26185         ListenerInfo li = mListenerInfo;
26186         //noinspection SimplifiableIfStatement
26187         if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
26188                 && li.mOnDragListener.onDrag(this, event)) {
26189             result = true;
26190         } else {
26191             result = onDragEvent(event);
26192         }
26193 
26194         switch (event.mAction) {
26195             case DragEvent.ACTION_DRAG_ENTERED: {
26196                 mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
26197                 refreshDrawableState();
26198             } break;
26199             case DragEvent.ACTION_DRAG_EXITED: {
26200                 mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
26201                 refreshDrawableState();
26202             } break;
26203             case DragEvent.ACTION_DRAG_ENDED: {
26204                 mPrivateFlags2 &= ~View.DRAG_MASK;
26205                 refreshDrawableState();
26206             } break;
26207         }
26208 
26209         return result;
26210     }
26211 
canAcceptDrag()26212     boolean canAcceptDrag() {
26213         return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
26214     }
26215 
26216     /**
26217      * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
26218      * it is ever exposed at all.
26219      * @hide
26220      */
26221     @UnsupportedAppUsage
onCloseSystemDialogs(String reason)26222     public void onCloseSystemDialogs(String reason) {
26223     }
26224 
26225     /**
26226      * Given a Drawable whose bounds have been set to draw into this view,
26227      * update a Region being computed for
26228      * {@link #gatherTransparentRegion(android.graphics.Region)} so
26229      * that any non-transparent parts of the Drawable are removed from the
26230      * given transparent region.
26231      *
26232      * @param dr The Drawable whose transparency is to be applied to the region.
26233      * @param region A Region holding the current transparency information,
26234      * where any parts of the region that are set are considered to be
26235      * transparent.  On return, this region will be modified to have the
26236      * transparency information reduced by the corresponding parts of the
26237      * Drawable that are not transparent.
26238      * {@hide}
26239      */
26240     @UnsupportedAppUsage
applyDrawableToTransparentRegion(Drawable dr, Region region)26241     public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
26242         if (DBG) {
26243             Log.i("View", "Getting transparent region for: " + this);
26244         }
26245         final Region r = dr.getTransparentRegion();
26246         final Rect db = dr.getBounds();
26247         final AttachInfo attachInfo = mAttachInfo;
26248         if (r != null && attachInfo != null) {
26249             final int w = getRight()-getLeft();
26250             final int h = getBottom()-getTop();
26251             if (db.left > 0) {
26252                 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
26253                 r.op(0, 0, db.left, h, Region.Op.UNION);
26254             }
26255             if (db.right < w) {
26256                 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
26257                 r.op(db.right, 0, w, h, Region.Op.UNION);
26258             }
26259             if (db.top > 0) {
26260                 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
26261                 r.op(0, 0, w, db.top, Region.Op.UNION);
26262             }
26263             if (db.bottom < h) {
26264                 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
26265                 r.op(0, db.bottom, w, h, Region.Op.UNION);
26266             }
26267             final int[] location = attachInfo.mTransparentLocation;
26268             getLocationInWindow(location);
26269             r.translate(location[0], location[1]);
26270             region.op(r, Region.Op.INTERSECT);
26271         } else {
26272             region.op(db, Region.Op.DIFFERENCE);
26273         }
26274     }
26275 
checkForLongClick(long delay, float x, float y, int classification)26276     private void checkForLongClick(long delay, float x, float y, int classification) {
26277         if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
26278             mHasPerformedLongPress = false;
26279 
26280             if (mPendingCheckForLongPress == null) {
26281                 mPendingCheckForLongPress = new CheckForLongPress();
26282             }
26283             mPendingCheckForLongPress.setAnchor(x, y);
26284             mPendingCheckForLongPress.rememberWindowAttachCount();
26285             mPendingCheckForLongPress.rememberPressedState();
26286             mPendingCheckForLongPress.setClassification(classification);
26287             postDelayed(mPendingCheckForLongPress, delay);
26288         }
26289     }
26290 
26291     /**
26292      * Inflate a view from an XML resource.  This convenience method wraps the {@link
26293      * LayoutInflater} class, which provides a full range of options for view inflation.
26294      *
26295      * @param context The Context object for your activity or application.
26296      * @param resource The resource ID to inflate
26297      * @param root A view group that will be the parent.  Used to properly inflate the
26298      * layout_* parameters.
26299      * @see LayoutInflater
26300      */
inflate(Context context, @LayoutRes int resource, ViewGroup root)26301     public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
26302         LayoutInflater factory = LayoutInflater.from(context);
26303         return factory.inflate(resource, root);
26304     }
26305 
26306     /**
26307      * Scroll the view with standard behavior for scrolling beyond the normal
26308      * content boundaries. Views that call this method should override
26309      * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
26310      * results of an over-scroll operation.
26311      *
26312      * Views can use this method to handle any touch or fling-based scrolling.
26313      *
26314      * @param deltaX Change in X in pixels
26315      * @param deltaY Change in Y in pixels
26316      * @param scrollX Current X scroll value in pixels before applying deltaX
26317      * @param scrollY Current Y scroll value in pixels before applying deltaY
26318      * @param scrollRangeX Maximum content scroll range along the X axis
26319      * @param scrollRangeY Maximum content scroll range along the Y axis
26320      * @param maxOverScrollX Number of pixels to overscroll by in either direction
26321      *          along the X axis.
26322      * @param maxOverScrollY Number of pixels to overscroll by in either direction
26323      *          along the Y axis.
26324      * @param isTouchEvent true if this scroll operation is the result of a touch event.
26325      * @return true if scrolling was clamped to an over-scroll boundary along either
26326      *          axis, false otherwise.
26327      */
26328     @SuppressWarnings({"UnusedParameters"})
overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent)26329     protected boolean overScrollBy(int deltaX, int deltaY,
26330             int scrollX, int scrollY,
26331             int scrollRangeX, int scrollRangeY,
26332             int maxOverScrollX, int maxOverScrollY,
26333             boolean isTouchEvent) {
26334         final int overScrollMode = mOverScrollMode;
26335         final boolean canScrollHorizontal =
26336                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
26337         final boolean canScrollVertical =
26338                 computeVerticalScrollRange() > computeVerticalScrollExtent();
26339         final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
26340                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
26341         final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
26342                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
26343 
26344         int newScrollX = scrollX + deltaX;
26345         if (!overScrollHorizontal) {
26346             maxOverScrollX = 0;
26347         }
26348 
26349         int newScrollY = scrollY + deltaY;
26350         if (!overScrollVertical) {
26351             maxOverScrollY = 0;
26352         }
26353 
26354         // Clamp values if at the limits and record
26355         final int left = -maxOverScrollX;
26356         final int right = maxOverScrollX + scrollRangeX;
26357         final int top = -maxOverScrollY;
26358         final int bottom = maxOverScrollY + scrollRangeY;
26359 
26360         boolean clampedX = false;
26361         if (newScrollX > right) {
26362             newScrollX = right;
26363             clampedX = true;
26364         } else if (newScrollX < left) {
26365             newScrollX = left;
26366             clampedX = true;
26367         }
26368 
26369         boolean clampedY = false;
26370         if (newScrollY > bottom) {
26371             newScrollY = bottom;
26372             clampedY = true;
26373         } else if (newScrollY < top) {
26374             newScrollY = top;
26375             clampedY = true;
26376         }
26377 
26378         onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
26379 
26380         return clampedX || clampedY;
26381     }
26382 
26383     /**
26384      * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
26385      * respond to the results of an over-scroll operation.
26386      *
26387      * @param scrollX New X scroll value in pixels
26388      * @param scrollY New Y scroll value in pixels
26389      * @param clampedX True if scrollX was clamped to an over-scroll boundary
26390      * @param clampedY True if scrollY was clamped to an over-scroll boundary
26391      */
onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY)26392     protected void onOverScrolled(int scrollX, int scrollY,
26393             boolean clampedX, boolean clampedY) {
26394         // Intentionally empty.
26395     }
26396 
26397     /**
26398      * Returns the over-scroll mode for this view. The result will be
26399      * one of {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
26400      * (allow over-scrolling only if the view content is larger than the container),
26401      * or {@link #OVER_SCROLL_NEVER}.
26402      *
26403      * @return This view's over-scroll mode.
26404      */
26405     @InspectableProperty(enumMapping = {
26406             @EnumEntry(value = OVER_SCROLL_ALWAYS, name = "always"),
26407             @EnumEntry(value = OVER_SCROLL_IF_CONTENT_SCROLLS, name = "ifContentScrolls"),
26408             @EnumEntry(value = OVER_SCROLL_NEVER, name = "never")
26409     })
getOverScrollMode()26410     public int getOverScrollMode() {
26411         return mOverScrollMode;
26412     }
26413 
26414     /**
26415      * Set the over-scroll mode for this view. Valid over-scroll modes are
26416      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
26417      * (allow over-scrolling only if the view content is larger than the container),
26418      * or {@link #OVER_SCROLL_NEVER}.
26419      *
26420      * Setting the over-scroll mode of a view will have an effect only if the
26421      * view is capable of scrolling.
26422      *
26423      * @param overScrollMode The new over-scroll mode for this view.
26424      */
setOverScrollMode(int overScrollMode)26425     public void setOverScrollMode(int overScrollMode) {
26426         if (overScrollMode != OVER_SCROLL_ALWAYS &&
26427                 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
26428                 overScrollMode != OVER_SCROLL_NEVER) {
26429             throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
26430         }
26431         mOverScrollMode = overScrollMode;
26432     }
26433 
26434     /**
26435      * Enable or disable nested scrolling for this view.
26436      *
26437      * <p>If this property is set to true the view will be permitted to initiate nested
26438      * scrolling operations with a compatible parent view in the current hierarchy. If this
26439      * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
26440      * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
26441      * the nested scroll.</p>
26442      *
26443      * @param enabled true to enable nested scrolling, false to disable
26444      *
26445      * @see #isNestedScrollingEnabled()
26446      */
setNestedScrollingEnabled(boolean enabled)26447     public void setNestedScrollingEnabled(boolean enabled) {
26448         if (enabled) {
26449             mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
26450         } else {
26451             stopNestedScroll();
26452             mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
26453         }
26454     }
26455 
26456     /**
26457      * Returns true if nested scrolling is enabled for this view.
26458      *
26459      * <p>If nested scrolling is enabled and this View class implementation supports it,
26460      * this view will act as a nested scrolling child view when applicable, forwarding data
26461      * about the scroll operation in progress to a compatible and cooperating nested scrolling
26462      * parent.</p>
26463      *
26464      * @return true if nested scrolling is enabled
26465      *
26466      * @see #setNestedScrollingEnabled(boolean)
26467      */
26468     @InspectableProperty
isNestedScrollingEnabled()26469     public boolean isNestedScrollingEnabled() {
26470         return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
26471                 PFLAG3_NESTED_SCROLLING_ENABLED;
26472     }
26473 
26474     /**
26475      * Begin a nestable scroll operation along the given axes.
26476      *
26477      * <p>A view starting a nested scroll promises to abide by the following contract:</p>
26478      *
26479      * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
26480      * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
26481      * In the case of touch scrolling the nested scroll will be terminated automatically in
26482      * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
26483      * In the event of programmatic scrolling the caller must explicitly call
26484      * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
26485      *
26486      * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
26487      * If it returns false the caller may ignore the rest of this contract until the next scroll.
26488      * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
26489      *
26490      * <p>At each incremental step of the scroll the caller should invoke
26491      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
26492      * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
26493      * parent at least partially consumed the scroll and the caller should adjust the amount it
26494      * scrolls by.</p>
26495      *
26496      * <p>After applying the remainder of the scroll delta the caller should invoke
26497      * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
26498      * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
26499      * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
26500      * </p>
26501      *
26502      * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
26503      *             {@link #SCROLL_AXIS_VERTICAL}.
26504      * @return true if a cooperative parent was found and nested scrolling has been enabled for
26505      *         the current gesture.
26506      *
26507      * @see #stopNestedScroll()
26508      * @see #dispatchNestedPreScroll(int, int, int[], int[])
26509      * @see #dispatchNestedScroll(int, int, int, int, int[])
26510      */
startNestedScroll(int axes)26511     public boolean startNestedScroll(int axes) {
26512         if (hasNestedScrollingParent()) {
26513             // Already in progress
26514             return true;
26515         }
26516         if (isNestedScrollingEnabled()) {
26517             ViewParent p = getParent();
26518             View child = this;
26519             while (p != null) {
26520                 try {
26521                     if (p.onStartNestedScroll(child, this, axes)) {
26522                         mNestedScrollingParent = p;
26523                         p.onNestedScrollAccepted(child, this, axes);
26524                         return true;
26525                     }
26526                 } catch (AbstractMethodError e) {
26527                     Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
26528                             "method onStartNestedScroll", e);
26529                     // Allow the search upward to continue
26530                 }
26531                 if (p instanceof View) {
26532                     child = (View) p;
26533                 }
26534                 p = p.getParent();
26535             }
26536         }
26537         return false;
26538     }
26539 
26540     /**
26541      * Stop a nested scroll in progress.
26542      *
26543      * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
26544      *
26545      * @see #startNestedScroll(int)
26546      */
stopNestedScroll()26547     public void stopNestedScroll() {
26548         if (mNestedScrollingParent != null) {
26549             mNestedScrollingParent.onStopNestedScroll(this);
26550             mNestedScrollingParent = null;
26551         }
26552     }
26553 
26554     /**
26555      * Returns true if this view has a nested scrolling parent.
26556      *
26557      * <p>The presence of a nested scrolling parent indicates that this view has initiated
26558      * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
26559      *
26560      * @return whether this view has a nested scrolling parent
26561      */
hasNestedScrollingParent()26562     public boolean hasNestedScrollingParent() {
26563         return mNestedScrollingParent != null;
26564     }
26565 
26566     /**
26567      * Dispatch one step of a nested scroll in progress.
26568      *
26569      * <p>Implementations of views that support nested scrolling should call this to report
26570      * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
26571      * is not currently in progress or nested scrolling is not
26572      * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
26573      *
26574      * <p>Compatible View implementations should also call
26575      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
26576      * consuming a component of the scroll event themselves.</p>
26577      *
26578      * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
26579      * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
26580      * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
26581      * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
26582      * @param offsetInWindow Optional. If not null, on return this will contain the offset
26583      *                       in local view coordinates of this view from before this operation
26584      *                       to after it completes. View implementations may use this to adjust
26585      *                       expected input coordinate tracking.
26586      * @return true if the event was dispatched, false if it could not be dispatched.
26587      * @see #dispatchNestedPreScroll(int, int, int[], int[])
26588      */
dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow)26589     public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
26590             int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
26591         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
26592             if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
26593                 int startX = 0;
26594                 int startY = 0;
26595                 if (offsetInWindow != null) {
26596                     getLocationInWindow(offsetInWindow);
26597                     startX = offsetInWindow[0];
26598                     startY = offsetInWindow[1];
26599                 }
26600 
26601                 mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
26602                         dxUnconsumed, dyUnconsumed);
26603 
26604                 if (offsetInWindow != null) {
26605                     getLocationInWindow(offsetInWindow);
26606                     offsetInWindow[0] -= startX;
26607                     offsetInWindow[1] -= startY;
26608                 }
26609                 return true;
26610             } else if (offsetInWindow != null) {
26611                 // No motion, no dispatch. Keep offsetInWindow up to date.
26612                 offsetInWindow[0] = 0;
26613                 offsetInWindow[1] = 0;
26614             }
26615         }
26616         return false;
26617     }
26618 
26619     /**
26620      * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
26621      *
26622      * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
26623      * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
26624      * scrolling operation to consume some or all of the scroll operation before the child view
26625      * consumes it.</p>
26626      *
26627      * @param dx Horizontal scroll distance in pixels
26628      * @param dy Vertical scroll distance in pixels
26629      * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
26630      *                 and consumed[1] the consumed dy.
26631      * @param offsetInWindow Optional. If not null, on return this will contain the offset
26632      *                       in local view coordinates of this view from before this operation
26633      *                       to after it completes. View implementations may use this to adjust
26634      *                       expected input coordinate tracking.
26635      * @return true if the parent consumed some or all of the scroll delta
26636      * @see #dispatchNestedScroll(int, int, int, int, int[])
26637      */
dispatchNestedPreScroll(int dx, int dy, @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow)26638     public boolean dispatchNestedPreScroll(int dx, int dy,
26639             @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
26640         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
26641             if (dx != 0 || dy != 0) {
26642                 int startX = 0;
26643                 int startY = 0;
26644                 if (offsetInWindow != null) {
26645                     getLocationInWindow(offsetInWindow);
26646                     startX = offsetInWindow[0];
26647                     startY = offsetInWindow[1];
26648                 }
26649 
26650                 if (consumed == null) {
26651                     if (mTempNestedScrollConsumed == null) {
26652                         mTempNestedScrollConsumed = new int[2];
26653                     }
26654                     consumed = mTempNestedScrollConsumed;
26655                 }
26656                 consumed[0] = 0;
26657                 consumed[1] = 0;
26658                 mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
26659 
26660                 if (offsetInWindow != null) {
26661                     getLocationInWindow(offsetInWindow);
26662                     offsetInWindow[0] -= startX;
26663                     offsetInWindow[1] -= startY;
26664                 }
26665                 return consumed[0] != 0 || consumed[1] != 0;
26666             } else if (offsetInWindow != null) {
26667                 offsetInWindow[0] = 0;
26668                 offsetInWindow[1] = 0;
26669             }
26670         }
26671         return false;
26672     }
26673 
26674     /**
26675      * Dispatch a fling to a nested scrolling parent.
26676      *
26677      * <p>This method should be used to indicate that a nested scrolling child has detected
26678      * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
26679      * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
26680      * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
26681      * along a scrollable axis.</p>
26682      *
26683      * <p>If a nested scrolling child view would normally fling but it is at the edge of
26684      * its own content, it can use this method to delegate the fling to its nested scrolling
26685      * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
26686      *
26687      * @param velocityX Horizontal fling velocity in pixels per second
26688      * @param velocityY Vertical fling velocity in pixels per second
26689      * @param consumed true if the child consumed the fling, false otherwise
26690      * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
26691      */
dispatchNestedFling(float velocityX, float velocityY, boolean consumed)26692     public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
26693         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
26694             return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
26695         }
26696         return false;
26697     }
26698 
26699     /**
26700      * Dispatch a fling to a nested scrolling parent before it is processed by this view.
26701      *
26702      * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
26703      * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
26704      * offsets an opportunity for the parent view in a nested fling to fully consume the fling
26705      * before the child view consumes it. If this method returns <code>true</code>, a nested
26706      * parent view consumed the fling and this view should not scroll as a result.</p>
26707      *
26708      * <p>For a better user experience, only one view in a nested scrolling chain should consume
26709      * the fling at a time. If a parent view consumed the fling this method will return false.
26710      * Custom view implementations should account for this in two ways:</p>
26711      *
26712      * <ul>
26713      *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
26714      *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
26715      *     position regardless.</li>
26716      *     <li>If a nested parent does consume the fling, this view should not scroll at all,
26717      *     even to settle back to a valid idle position.</li>
26718      * </ul>
26719      *
26720      * <p>Views should also not offer fling velocities to nested parent views along an axis
26721      * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
26722      * should not offer a horizontal fling velocity to its parents since scrolling along that
26723      * axis is not permitted and carrying velocity along that motion does not make sense.</p>
26724      *
26725      * @param velocityX Horizontal fling velocity in pixels per second
26726      * @param velocityY Vertical fling velocity in pixels per second
26727      * @return true if a nested scrolling parent consumed the fling
26728      */
dispatchNestedPreFling(float velocityX, float velocityY)26729     public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
26730         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
26731             return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
26732         }
26733         return false;
26734     }
26735 
26736     /**
26737      * Gets a scale factor that determines the distance the view should scroll
26738      * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
26739      * @return The vertical scroll scale factor.
26740      * @hide
26741      */
26742     @UnsupportedAppUsage
getVerticalScrollFactor()26743     protected float getVerticalScrollFactor() {
26744         if (mVerticalScrollFactor == 0) {
26745             TypedValue outValue = new TypedValue();
26746             if (!mContext.getTheme().resolveAttribute(
26747                     com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
26748                 throw new IllegalStateException(
26749                         "Expected theme to define listPreferredItemHeight.");
26750             }
26751             mVerticalScrollFactor = outValue.getDimension(
26752                     mContext.getResources().getDisplayMetrics());
26753         }
26754         return mVerticalScrollFactor;
26755     }
26756 
26757     /**
26758      * Gets a scale factor that determines the distance the view should scroll
26759      * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
26760      * @return The horizontal scroll scale factor.
26761      * @hide
26762      */
26763     @UnsupportedAppUsage
getHorizontalScrollFactor()26764     protected float getHorizontalScrollFactor() {
26765         // TODO: Should use something else.
26766         return getVerticalScrollFactor();
26767     }
26768 
26769     /**
26770      * Return the value specifying the text direction or policy that was set with
26771      * {@link #setTextDirection(int)}.
26772      *
26773      * @return the defined text direction. It can be one of:
26774      *
26775      * {@link #TEXT_DIRECTION_INHERIT},
26776      * {@link #TEXT_DIRECTION_FIRST_STRONG},
26777      * {@link #TEXT_DIRECTION_ANY_RTL},
26778      * {@link #TEXT_DIRECTION_LTR},
26779      * {@link #TEXT_DIRECTION_RTL},
26780      * {@link #TEXT_DIRECTION_LOCALE},
26781      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
26782      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
26783      *
26784      * @attr ref android.R.styleable#View_textDirection
26785      *
26786      * @hide
26787      */
26788     @ViewDebug.ExportedProperty(category = "text", mapping = {
26789             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
26790             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
26791             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
26792             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
26793             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
26794             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
26795             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
26796             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
26797     })
26798     @InspectableProperty(hasAttributeId = false, enumMapping = {
26799             @EnumEntry(value = TEXT_DIRECTION_INHERIT, name = "inherit"),
26800             @EnumEntry(value = TEXT_DIRECTION_LOCALE, name = "locale"),
26801             @EnumEntry(value = TEXT_DIRECTION_ANY_RTL, name = "anyRtl"),
26802             @EnumEntry(value = TEXT_DIRECTION_LTR, name = "ltr"),
26803             @EnumEntry(value = TEXT_DIRECTION_RTL, name = "rtl"),
26804             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG, name = "firstStrong"),
26805             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_LTR, name = "firstStrongLtr"),
26806             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_RTL, name = "firstStrongRtl"),
26807     })
26808     @UnsupportedAppUsage
getRawTextDirection()26809     public int getRawTextDirection() {
26810         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
26811     }
26812 
26813     /**
26814      * Set the text direction.
26815      *
26816      * @param textDirection the direction to set. Should be one of:
26817      *
26818      * {@link #TEXT_DIRECTION_INHERIT},
26819      * {@link #TEXT_DIRECTION_FIRST_STRONG},
26820      * {@link #TEXT_DIRECTION_ANY_RTL},
26821      * {@link #TEXT_DIRECTION_LTR},
26822      * {@link #TEXT_DIRECTION_RTL},
26823      * {@link #TEXT_DIRECTION_LOCALE}
26824      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
26825      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
26826      *
26827      * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
26828      * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
26829      * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
26830      *
26831      * @attr ref android.R.styleable#View_textDirection
26832      */
setTextDirection(int textDirection)26833     public void setTextDirection(int textDirection) {
26834         if (getRawTextDirection() != textDirection) {
26835             // Reset the current text direction and the resolved one
26836             mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
26837             resetResolvedTextDirection();
26838             // Set the new text direction
26839             mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
26840             // Do resolution
26841             resolveTextDirection();
26842             // Notify change
26843             onRtlPropertiesChanged(getLayoutDirection());
26844             // Refresh
26845             requestLayout();
26846             invalidate(true);
26847         }
26848     }
26849 
26850     /**
26851      * Return the resolved text direction.
26852      *
26853      * @return the resolved text direction. Returns one of:
26854      *
26855      * {@link #TEXT_DIRECTION_FIRST_STRONG},
26856      * {@link #TEXT_DIRECTION_ANY_RTL},
26857      * {@link #TEXT_DIRECTION_LTR},
26858      * {@link #TEXT_DIRECTION_RTL},
26859      * {@link #TEXT_DIRECTION_LOCALE},
26860      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
26861      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
26862      *
26863      * @attr ref android.R.styleable#View_textDirection
26864      */
26865     @ViewDebug.ExportedProperty(category = "text", mapping = {
26866             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
26867             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
26868             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
26869             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
26870             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
26871             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
26872             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
26873             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
26874     })
26875     @InspectableProperty(hasAttributeId = false, enumMapping = {
26876             @EnumEntry(value = TEXT_DIRECTION_LOCALE, name = "locale"),
26877             @EnumEntry(value = TEXT_DIRECTION_ANY_RTL, name = "anyRtl"),
26878             @EnumEntry(value = TEXT_DIRECTION_LTR, name = "ltr"),
26879             @EnumEntry(value = TEXT_DIRECTION_RTL, name = "rtl"),
26880             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG, name = "firstStrong"),
26881             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_LTR, name = "firstStrongLtr"),
26882             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_RTL, name = "firstStrongRtl"),
26883     })
getTextDirection()26884     public int getTextDirection() {
26885         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
26886     }
26887 
26888     /**
26889      * Resolve the text direction.
26890      *
26891      * @return true if resolution has been done, false otherwise.
26892      *
26893      * @hide
26894      */
resolveTextDirection()26895     public boolean resolveTextDirection() {
26896         // Reset any previous text direction resolution
26897         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
26898 
26899         if (hasRtlSupport()) {
26900             // Set resolved text direction flag depending on text direction flag
26901             final int textDirection = getRawTextDirection();
26902             switch(textDirection) {
26903                 case TEXT_DIRECTION_INHERIT:
26904                     if (!canResolveTextDirection()) {
26905                         // We cannot do the resolution if there is no parent, so use the default one
26906                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
26907                         // Resolution will need to happen again later
26908                         return false;
26909                     }
26910 
26911                     // Parent has not yet resolved, so we still return the default
26912                     try {
26913                         if (!mParent.isTextDirectionResolved()) {
26914                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
26915                             // Resolution will need to happen again later
26916                             return false;
26917                         }
26918                     } catch (AbstractMethodError e) {
26919                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
26920                                 " does not fully implement ViewParent", e);
26921                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
26922                                 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
26923                         return true;
26924                     }
26925 
26926                     // Set current resolved direction to the same value as the parent's one
26927                     int parentResolvedDirection;
26928                     try {
26929                         parentResolvedDirection = mParent.getTextDirection();
26930                     } catch (AbstractMethodError e) {
26931                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
26932                                 " does not fully implement ViewParent", e);
26933                         parentResolvedDirection = TEXT_DIRECTION_LTR;
26934                     }
26935                     switch (parentResolvedDirection) {
26936                         case TEXT_DIRECTION_FIRST_STRONG:
26937                         case TEXT_DIRECTION_ANY_RTL:
26938                         case TEXT_DIRECTION_LTR:
26939                         case TEXT_DIRECTION_RTL:
26940                         case TEXT_DIRECTION_LOCALE:
26941                         case TEXT_DIRECTION_FIRST_STRONG_LTR:
26942                         case TEXT_DIRECTION_FIRST_STRONG_RTL:
26943                             mPrivateFlags2 |=
26944                                     (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
26945                             break;
26946                         default:
26947                             // Default resolved direction is "first strong" heuristic
26948                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
26949                     }
26950                     break;
26951                 case TEXT_DIRECTION_FIRST_STRONG:
26952                 case TEXT_DIRECTION_ANY_RTL:
26953                 case TEXT_DIRECTION_LTR:
26954                 case TEXT_DIRECTION_RTL:
26955                 case TEXT_DIRECTION_LOCALE:
26956                 case TEXT_DIRECTION_FIRST_STRONG_LTR:
26957                 case TEXT_DIRECTION_FIRST_STRONG_RTL:
26958                     // Resolved direction is the same as text direction
26959                     mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
26960                     break;
26961                 default:
26962                     // Default resolved direction is "first strong" heuristic
26963                     mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
26964             }
26965         } else {
26966             // Default resolved direction is "first strong" heuristic
26967             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
26968         }
26969 
26970         // Set to resolved
26971         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
26972         return true;
26973     }
26974 
26975     /**
26976      * Check if text direction resolution can be done.
26977      *
26978      * @return true if text direction resolution can be done otherwise return false.
26979      */
canResolveTextDirection()26980     public boolean canResolveTextDirection() {
26981         switch (getRawTextDirection()) {
26982             case TEXT_DIRECTION_INHERIT:
26983                 if (mParent != null) {
26984                     try {
26985                         return mParent.canResolveTextDirection();
26986                     } catch (AbstractMethodError e) {
26987                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
26988                                 " does not fully implement ViewParent", e);
26989                     }
26990                 }
26991                 return false;
26992 
26993             default:
26994                 return true;
26995         }
26996     }
26997 
26998     /**
26999      * Reset resolved text direction. Text direction will be resolved during a call to
27000      * {@link #onMeasure(int, int)}.
27001      *
27002      * @hide
27003      */
27004     @TestApi
resetResolvedTextDirection()27005     public void resetResolvedTextDirection() {
27006         // Reset any previous text direction resolution
27007         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
27008         // Set to default value
27009         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
27010     }
27011 
27012     /**
27013      * @return true if text direction is inherited.
27014      *
27015      * @hide
27016      */
isTextDirectionInherited()27017     public boolean isTextDirectionInherited() {
27018         return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
27019     }
27020 
27021     /**
27022      * @return true if text direction is resolved.
27023      */
isTextDirectionResolved()27024     public boolean isTextDirectionResolved() {
27025         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
27026     }
27027 
27028     /**
27029      * Return the value specifying the text alignment or policy that was set with
27030      * {@link #setTextAlignment(int)}.
27031      *
27032      * @return the defined text alignment. It can be one of:
27033      *
27034      * {@link #TEXT_ALIGNMENT_INHERIT},
27035      * {@link #TEXT_ALIGNMENT_GRAVITY},
27036      * {@link #TEXT_ALIGNMENT_CENTER},
27037      * {@link #TEXT_ALIGNMENT_TEXT_START},
27038      * {@link #TEXT_ALIGNMENT_TEXT_END},
27039      * {@link #TEXT_ALIGNMENT_VIEW_START},
27040      * {@link #TEXT_ALIGNMENT_VIEW_END}
27041      *
27042      * @attr ref android.R.styleable#View_textAlignment
27043      *
27044      * @hide
27045      */
27046     @ViewDebug.ExportedProperty(category = "text", mapping = {
27047             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
27048             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
27049             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
27050             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
27051             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
27052             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
27053             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
27054     })
27055     @InspectableProperty(hasAttributeId = false, enumMapping = {
27056             @EnumEntry(value = TEXT_ALIGNMENT_INHERIT, name = "inherit"),
27057             @EnumEntry(value = TEXT_ALIGNMENT_GRAVITY, name = "gravity"),
27058             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_START, name = "textStart"),
27059             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_END, name = "textEnd"),
27060             @EnumEntry(value = TEXT_ALIGNMENT_CENTER, name = "center"),
27061             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_START, name = "viewStart"),
27062             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_END, name = "viewEnd")
27063     })
27064     @TextAlignment
27065     @UnsupportedAppUsage
getRawTextAlignment()27066     public int getRawTextAlignment() {
27067         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
27068     }
27069 
27070     /**
27071      * Set the text alignment.
27072      *
27073      * @param textAlignment The text alignment to set. Should be one of
27074      *
27075      * {@link #TEXT_ALIGNMENT_INHERIT},
27076      * {@link #TEXT_ALIGNMENT_GRAVITY},
27077      * {@link #TEXT_ALIGNMENT_CENTER},
27078      * {@link #TEXT_ALIGNMENT_TEXT_START},
27079      * {@link #TEXT_ALIGNMENT_TEXT_END},
27080      * {@link #TEXT_ALIGNMENT_VIEW_START},
27081      * {@link #TEXT_ALIGNMENT_VIEW_END}
27082      *
27083      * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
27084      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
27085      * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
27086      *
27087      * @attr ref android.R.styleable#View_textAlignment
27088      */
setTextAlignment(@extAlignment int textAlignment)27089     public void setTextAlignment(@TextAlignment int textAlignment) {
27090         if (textAlignment != getRawTextAlignment()) {
27091             // Reset the current and resolved text alignment
27092             mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
27093             resetResolvedTextAlignment();
27094             // Set the new text alignment
27095             mPrivateFlags2 |=
27096                     ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
27097             // Do resolution
27098             resolveTextAlignment();
27099             // Notify change
27100             onRtlPropertiesChanged(getLayoutDirection());
27101             // Refresh
27102             requestLayout();
27103             invalidate(true);
27104         }
27105     }
27106 
27107     /**
27108      * Return the resolved text alignment.
27109      *
27110      * @return the resolved text alignment. Returns one of:
27111      *
27112      * {@link #TEXT_ALIGNMENT_GRAVITY},
27113      * {@link #TEXT_ALIGNMENT_CENTER},
27114      * {@link #TEXT_ALIGNMENT_TEXT_START},
27115      * {@link #TEXT_ALIGNMENT_TEXT_END},
27116      * {@link #TEXT_ALIGNMENT_VIEW_START},
27117      * {@link #TEXT_ALIGNMENT_VIEW_END}
27118      *
27119      * @attr ref android.R.styleable#View_textAlignment
27120      */
27121     @ViewDebug.ExportedProperty(category = "text", mapping = {
27122             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
27123             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
27124             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
27125             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
27126             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
27127             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
27128             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
27129     })
27130     @InspectableProperty(enumMapping = {
27131             @EnumEntry(value = TEXT_ALIGNMENT_GRAVITY, name = "gravity"),
27132             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_START, name = "textStart"),
27133             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_END, name = "textEnd"),
27134             @EnumEntry(value = TEXT_ALIGNMENT_CENTER, name = "center"),
27135             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_START, name = "viewStart"),
27136             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_END, name = "viewEnd")
27137     })
27138     @TextAlignment
getTextAlignment()27139     public int getTextAlignment() {
27140         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
27141                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
27142     }
27143 
27144     /**
27145      * Resolve the text alignment.
27146      *
27147      * @return true if resolution has been done, false otherwise.
27148      *
27149      * @hide
27150      */
resolveTextAlignment()27151     public boolean resolveTextAlignment() {
27152         // Reset any previous text alignment resolution
27153         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
27154 
27155         if (hasRtlSupport()) {
27156             // Set resolved text alignment flag depending on text alignment flag
27157             final int textAlignment = getRawTextAlignment();
27158             switch (textAlignment) {
27159                 case TEXT_ALIGNMENT_INHERIT:
27160                     // Check if we can resolve the text alignment
27161                     if (!canResolveTextAlignment()) {
27162                         // We cannot do the resolution if there is no parent so use the default
27163                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
27164                         // Resolution will need to happen again later
27165                         return false;
27166                     }
27167 
27168                     // Parent has not yet resolved, so we still return the default
27169                     try {
27170                         if (!mParent.isTextAlignmentResolved()) {
27171                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
27172                             // Resolution will need to happen again later
27173                             return false;
27174                         }
27175                     } catch (AbstractMethodError e) {
27176                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
27177                                 " does not fully implement ViewParent", e);
27178                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
27179                                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
27180                         return true;
27181                     }
27182 
27183                     int parentResolvedTextAlignment;
27184                     try {
27185                         parentResolvedTextAlignment = mParent.getTextAlignment();
27186                     } catch (AbstractMethodError e) {
27187                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
27188                                 " does not fully implement ViewParent", e);
27189                         parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
27190                     }
27191                     switch (parentResolvedTextAlignment) {
27192                         case TEXT_ALIGNMENT_GRAVITY:
27193                         case TEXT_ALIGNMENT_TEXT_START:
27194                         case TEXT_ALIGNMENT_TEXT_END:
27195                         case TEXT_ALIGNMENT_CENTER:
27196                         case TEXT_ALIGNMENT_VIEW_START:
27197                         case TEXT_ALIGNMENT_VIEW_END:
27198                             // Resolved text alignment is the same as the parent resolved
27199                             // text alignment
27200                             mPrivateFlags2 |=
27201                                     (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
27202                             break;
27203                         default:
27204                             // Use default resolved text alignment
27205                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
27206                     }
27207                     break;
27208                 case TEXT_ALIGNMENT_GRAVITY:
27209                 case TEXT_ALIGNMENT_TEXT_START:
27210                 case TEXT_ALIGNMENT_TEXT_END:
27211                 case TEXT_ALIGNMENT_CENTER:
27212                 case TEXT_ALIGNMENT_VIEW_START:
27213                 case TEXT_ALIGNMENT_VIEW_END:
27214                     // Resolved text alignment is the same as text alignment
27215                     mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
27216                     break;
27217                 default:
27218                     // Use default resolved text alignment
27219                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
27220             }
27221         } else {
27222             // Use default resolved text alignment
27223             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
27224         }
27225 
27226         // Set the resolved
27227         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
27228         return true;
27229     }
27230 
27231     /**
27232      * Check if text alignment resolution can be done.
27233      *
27234      * @return true if text alignment resolution can be done otherwise return false.
27235      */
canResolveTextAlignment()27236     public boolean canResolveTextAlignment() {
27237         switch (getRawTextAlignment()) {
27238             case TEXT_DIRECTION_INHERIT:
27239                 if (mParent != null) {
27240                     try {
27241                         return mParent.canResolveTextAlignment();
27242                     } catch (AbstractMethodError e) {
27243                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
27244                                 " does not fully implement ViewParent", e);
27245                     }
27246                 }
27247                 return false;
27248 
27249             default:
27250                 return true;
27251         }
27252     }
27253 
27254     /**
27255      * Reset resolved text alignment. Text alignment will be resolved during a call to
27256      * {@link #onMeasure(int, int)}.
27257      *
27258      * @hide
27259      */
27260     @TestApi
resetResolvedTextAlignment()27261     public void resetResolvedTextAlignment() {
27262         // Reset any previous text alignment resolution
27263         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
27264         // Set to default
27265         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
27266     }
27267 
27268     /**
27269      * @return true if text alignment is inherited.
27270      *
27271      * @hide
27272      */
isTextAlignmentInherited()27273     public boolean isTextAlignmentInherited() {
27274         return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
27275     }
27276 
27277     /**
27278      * @return true if text alignment is resolved.
27279      */
isTextAlignmentResolved()27280     public boolean isTextAlignmentResolved() {
27281         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
27282     }
27283 
27284     /**
27285      * Generate a value suitable for use in {@link #setId(int)}.
27286      * This value will not collide with ID values generated at build time by aapt for R.id.
27287      *
27288      * @return a generated ID value
27289      */
generateViewId()27290     public static int generateViewId() {
27291         for (;;) {
27292             final int result = sNextGeneratedId.get();
27293             // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
27294             int newValue = result + 1;
27295             if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
27296             if (sNextGeneratedId.compareAndSet(result, newValue)) {
27297                 return result;
27298             }
27299         }
27300     }
27301 
isViewIdGenerated(int id)27302     private static boolean isViewIdGenerated(int id) {
27303         return (id & 0xFF000000) == 0 && (id & 0x00FFFFFF) != 0;
27304     }
27305 
27306     /**
27307      * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
27308      * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
27309      *                           a normal View or a ViewGroup with
27310      *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
27311      * @hide
27312      */
captureTransitioningViews(List<View> transitioningViews)27313     public void captureTransitioningViews(List<View> transitioningViews) {
27314         if (getVisibility() == View.VISIBLE) {
27315             transitioningViews.add(this);
27316         }
27317     }
27318 
27319     /**
27320      * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
27321      * @param namedElements Will contain all Views in the hierarchy having a transitionName.
27322      * @hide
27323      */
findNamedViews(Map<String, View> namedElements)27324     public void findNamedViews(Map<String, View> namedElements) {
27325         if (getVisibility() == VISIBLE || mGhostView != null) {
27326             String transitionName = getTransitionName();
27327             if (transitionName != null) {
27328                 namedElements.put(transitionName, this);
27329             }
27330         }
27331     }
27332 
27333     /**
27334      * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
27335      * The default implementation does not care the location or event types, but some subclasses
27336      * may use it (such as WebViews).
27337      * @param event The MotionEvent from a mouse
27338      * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
27339      *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
27340      * @see PointerIcon
27341      */
onResolvePointerIcon(MotionEvent event, int pointerIndex)27342     public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
27343         final float x = event.getX(pointerIndex);
27344         final float y = event.getY(pointerIndex);
27345         if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
27346             return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
27347         }
27348         return mPointerIcon;
27349     }
27350 
27351     /**
27352      * Set the pointer icon for the current view.
27353      * Passing {@code null} will restore the pointer icon to its default value.
27354      * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
27355      */
setPointerIcon(PointerIcon pointerIcon)27356     public void setPointerIcon(PointerIcon pointerIcon) {
27357         mPointerIcon = pointerIcon;
27358         if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
27359             return;
27360         }
27361         try {
27362             mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
27363         } catch (RemoteException e) {
27364         }
27365     }
27366 
27367     /**
27368      * Gets the pointer icon for the current view.
27369      */
27370     @InspectableProperty
getPointerIcon()27371     public PointerIcon getPointerIcon() {
27372         return mPointerIcon;
27373     }
27374 
27375     /**
27376      * Checks pointer capture status.
27377      *
27378      * @return true if the view has pointer capture.
27379      * @see #requestPointerCapture()
27380      * @see #hasPointerCapture()
27381      */
hasPointerCapture()27382     public boolean hasPointerCapture() {
27383         final ViewRootImpl viewRootImpl = getViewRootImpl();
27384         if (viewRootImpl == null) {
27385             return false;
27386         }
27387         return viewRootImpl.hasPointerCapture();
27388     }
27389 
27390     /**
27391      * Requests pointer capture mode.
27392      * <p>
27393      * When the window has pointer capture, the mouse pointer icon will disappear and will not
27394      * change its position. Further mouse will be dispatched with the source
27395      * {@link InputDevice#SOURCE_MOUSE_RELATIVE}, and relative position changes will be available
27396      * through {@link MotionEvent#getX} and {@link MotionEvent#getY}. Non-mouse events
27397      * (touchscreens, or stylus) will not be affected.
27398      * <p>
27399      * If the window already has pointer capture, this call does nothing.
27400      * <p>
27401      * The capture may be released through {@link #releasePointerCapture()}, or will be lost
27402      * automatically when the window loses focus.
27403      *
27404      * @see #releasePointerCapture()
27405      * @see #hasPointerCapture()
27406      */
requestPointerCapture()27407     public void requestPointerCapture() {
27408         final ViewRootImpl viewRootImpl = getViewRootImpl();
27409         if (viewRootImpl != null) {
27410             viewRootImpl.requestPointerCapture(true);
27411         }
27412     }
27413 
27414 
27415     /**
27416      * Releases the pointer capture.
27417      * <p>
27418      * If the window does not have pointer capture, this call will do nothing.
27419      * @see #requestPointerCapture()
27420      * @see #hasPointerCapture()
27421      */
releasePointerCapture()27422     public void releasePointerCapture() {
27423         final ViewRootImpl viewRootImpl = getViewRootImpl();
27424         if (viewRootImpl != null) {
27425             viewRootImpl.requestPointerCapture(false);
27426         }
27427     }
27428 
27429     /**
27430      * Called when the window has just acquired or lost pointer capture.
27431      *
27432      * @param hasCapture True if the view now has pointerCapture, false otherwise.
27433      */
27434     @CallSuper
onPointerCaptureChange(boolean hasCapture)27435     public void onPointerCaptureChange(boolean hasCapture) {
27436     }
27437 
27438     /**
27439      * @see #onPointerCaptureChange
27440      */
dispatchPointerCaptureChanged(boolean hasCapture)27441     public void dispatchPointerCaptureChanged(boolean hasCapture) {
27442         onPointerCaptureChange(hasCapture);
27443     }
27444 
27445     /**
27446      * Implement this method to handle captured pointer events
27447      *
27448      * @param event The captured pointer event.
27449      * @return True if the event was handled, false otherwise.
27450      * @see #requestPointerCapture()
27451      */
onCapturedPointerEvent(MotionEvent event)27452     public boolean onCapturedPointerEvent(MotionEvent event) {
27453         return false;
27454     }
27455 
27456     /**
27457      * Interface definition for a callback to be invoked when a captured pointer event
27458      * is being dispatched this view. The callback will be invoked before the event is
27459      * given to the view.
27460      */
27461     public interface OnCapturedPointerListener {
27462         /**
27463          * Called when a captured pointer event is dispatched to a view.
27464          * @param view The view this event has been dispatched to.
27465          * @param event The captured event.
27466          * @return True if the listener has consumed the event, false otherwise.
27467          */
onCapturedPointer(View view, MotionEvent event)27468         boolean onCapturedPointer(View view, MotionEvent event);
27469     }
27470 
27471     /**
27472      * Set a listener to receive callbacks when the pointer capture state of a view changes.
27473      * @param l  The {@link OnCapturedPointerListener} to receive callbacks.
27474      */
setOnCapturedPointerListener(OnCapturedPointerListener l)27475     public void setOnCapturedPointerListener(OnCapturedPointerListener l) {
27476         getListenerInfo().mOnCapturedPointerListener = l;
27477     }
27478 
27479     // Properties
27480     //
27481     /**
27482      * A Property wrapper around the <code>alpha</code> functionality handled by the
27483      * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
27484      */
27485     public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
27486         @Override
27487         public void setValue(View object, float value) {
27488             object.setAlpha(value);
27489         }
27490 
27491         @Override
27492         public Float get(View object) {
27493             return object.getAlpha();
27494         }
27495     };
27496 
27497     /**
27498      * A Property wrapper around the <code>translationX</code> functionality handled by the
27499      * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
27500      */
27501     public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
27502         @Override
27503         public void setValue(View object, float value) {
27504             object.setTranslationX(value);
27505         }
27506 
27507                 @Override
27508         public Float get(View object) {
27509             return object.getTranslationX();
27510         }
27511     };
27512 
27513     /**
27514      * A Property wrapper around the <code>translationY</code> functionality handled by the
27515      * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
27516      */
27517     public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
27518         @Override
27519         public void setValue(View object, float value) {
27520             object.setTranslationY(value);
27521         }
27522 
27523         @Override
27524         public Float get(View object) {
27525             return object.getTranslationY();
27526         }
27527     };
27528 
27529     /**
27530      * A Property wrapper around the <code>translationZ</code> functionality handled by the
27531      * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
27532      */
27533     public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
27534         @Override
27535         public void setValue(View object, float value) {
27536             object.setTranslationZ(value);
27537         }
27538 
27539         @Override
27540         public Float get(View object) {
27541             return object.getTranslationZ();
27542         }
27543     };
27544 
27545     /**
27546      * A Property wrapper around the <code>x</code> functionality handled by the
27547      * {@link View#setX(float)} and {@link View#getX()} methods.
27548      */
27549     public static final Property<View, Float> X = new FloatProperty<View>("x") {
27550         @Override
27551         public void setValue(View object, float value) {
27552             object.setX(value);
27553         }
27554 
27555         @Override
27556         public Float get(View object) {
27557             return object.getX();
27558         }
27559     };
27560 
27561     /**
27562      * A Property wrapper around the <code>y</code> functionality handled by the
27563      * {@link View#setY(float)} and {@link View#getY()} methods.
27564      */
27565     public static final Property<View, Float> Y = new FloatProperty<View>("y") {
27566         @Override
27567         public void setValue(View object, float value) {
27568             object.setY(value);
27569         }
27570 
27571         @Override
27572         public Float get(View object) {
27573             return object.getY();
27574         }
27575     };
27576 
27577     /**
27578      * A Property wrapper around the <code>z</code> functionality handled by the
27579      * {@link View#setZ(float)} and {@link View#getZ()} methods.
27580      */
27581     public static final Property<View, Float> Z = new FloatProperty<View>("z") {
27582         @Override
27583         public void setValue(View object, float value) {
27584             object.setZ(value);
27585         }
27586 
27587         @Override
27588         public Float get(View object) {
27589             return object.getZ();
27590         }
27591     };
27592 
27593     /**
27594      * A Property wrapper around the <code>rotation</code> functionality handled by the
27595      * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
27596      */
27597     public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
27598         @Override
27599         public void setValue(View object, float value) {
27600             object.setRotation(value);
27601         }
27602 
27603         @Override
27604         public Float get(View object) {
27605             return object.getRotation();
27606         }
27607     };
27608 
27609     /**
27610      * A Property wrapper around the <code>rotationX</code> functionality handled by the
27611      * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
27612      */
27613     public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
27614         @Override
27615         public void setValue(View object, float value) {
27616             object.setRotationX(value);
27617         }
27618 
27619         @Override
27620         public Float get(View object) {
27621             return object.getRotationX();
27622         }
27623     };
27624 
27625     /**
27626      * A Property wrapper around the <code>rotationY</code> functionality handled by the
27627      * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
27628      */
27629     public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
27630         @Override
27631         public void setValue(View object, float value) {
27632             object.setRotationY(value);
27633         }
27634 
27635         @Override
27636         public Float get(View object) {
27637             return object.getRotationY();
27638         }
27639     };
27640 
27641     /**
27642      * A Property wrapper around the <code>scaleX</code> functionality handled by the
27643      * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
27644      */
27645     public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
27646         @Override
27647         public void setValue(View object, float value) {
27648             object.setScaleX(value);
27649         }
27650 
27651         @Override
27652         public Float get(View object) {
27653             return object.getScaleX();
27654         }
27655     };
27656 
27657     /**
27658      * A Property wrapper around the <code>scaleY</code> functionality handled by the
27659      * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
27660      */
27661     public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
27662         @Override
27663         public void setValue(View object, float value) {
27664             object.setScaleY(value);
27665         }
27666 
27667         @Override
27668         public Float get(View object) {
27669             return object.getScaleY();
27670         }
27671     };
27672 
27673     /**
27674      * A MeasureSpec encapsulates the layout requirements passed from parent to child.
27675      * Each MeasureSpec represents a requirement for either the width or the height.
27676      * A MeasureSpec is comprised of a size and a mode. There are three possible
27677      * modes:
27678      * <dl>
27679      * <dt>UNSPECIFIED</dt>
27680      * <dd>
27681      * The parent has not imposed any constraint on the child. It can be whatever size
27682      * it wants.
27683      * </dd>
27684      *
27685      * <dt>EXACTLY</dt>
27686      * <dd>
27687      * The parent has determined an exact size for the child. The child is going to be
27688      * given those bounds regardless of how big it wants to be.
27689      * </dd>
27690      *
27691      * <dt>AT_MOST</dt>
27692      * <dd>
27693      * The child can be as large as it wants up to the specified size.
27694      * </dd>
27695      * </dl>
27696      *
27697      * MeasureSpecs are implemented as ints to reduce object allocation. This class
27698      * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
27699      */
27700     public static class MeasureSpec {
27701         private static final int MODE_SHIFT = 30;
27702         private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
27703 
27704         /** @hide */
27705         @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
27706         @Retention(RetentionPolicy.SOURCE)
27707         public @interface MeasureSpecMode {}
27708 
27709         /**
27710          * Measure specification mode: The parent has not imposed any constraint
27711          * on the child. It can be whatever size it wants.
27712          */
27713         public static final int UNSPECIFIED = 0 << MODE_SHIFT;
27714 
27715         /**
27716          * Measure specification mode: The parent has determined an exact size
27717          * for the child. The child is going to be given those bounds regardless
27718          * of how big it wants to be.
27719          */
27720         public static final int EXACTLY     = 1 << MODE_SHIFT;
27721 
27722         /**
27723          * Measure specification mode: The child can be as large as it wants up
27724          * to the specified size.
27725          */
27726         public static final int AT_MOST     = 2 << MODE_SHIFT;
27727 
27728         /**
27729          * Creates a measure specification based on the supplied size and mode.
27730          *
27731          * The mode must always be one of the following:
27732          * <ul>
27733          *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
27734          *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
27735          *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
27736          * </ul>
27737          *
27738          * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
27739          * implementation was such that the order of arguments did not matter
27740          * and overflow in either value could impact the resulting MeasureSpec.
27741          * {@link android.widget.RelativeLayout} was affected by this bug.
27742          * Apps targeting API levels greater than 17 will get the fixed, more strict
27743          * behavior.</p>
27744          *
27745          * @param size the size of the measure specification
27746          * @param mode the mode of the measure specification
27747          * @return the measure specification based on size and mode
27748          */
makeMeasureSpec(@ntRangefrom = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size, @MeasureSpecMode int mode)27749         public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
27750                                           @MeasureSpecMode int mode) {
27751             if (sUseBrokenMakeMeasureSpec) {
27752                 return size + mode;
27753             } else {
27754                 return (size & ~MODE_MASK) | (mode & MODE_MASK);
27755             }
27756         }
27757 
27758         /**
27759          * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
27760          * will automatically get a size of 0. Older apps expect this.
27761          *
27762          * @hide internal use only for compatibility with system widgets and older apps
27763          */
27764         @UnsupportedAppUsage
makeSafeMeasureSpec(int size, int mode)27765         public static int makeSafeMeasureSpec(int size, int mode) {
27766             if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
27767                 return 0;
27768             }
27769             return makeMeasureSpec(size, mode);
27770         }
27771 
27772         /**
27773          * Extracts the mode from the supplied measure specification.
27774          *
27775          * @param measureSpec the measure specification to extract the mode from
27776          * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
27777          *         {@link android.view.View.MeasureSpec#AT_MOST} or
27778          *         {@link android.view.View.MeasureSpec#EXACTLY}
27779          */
27780         @MeasureSpecMode
getMode(int measureSpec)27781         public static int getMode(int measureSpec) {
27782             //noinspection ResourceType
27783             return (measureSpec & MODE_MASK);
27784         }
27785 
27786         /**
27787          * Extracts the size from the supplied measure specification.
27788          *
27789          * @param measureSpec the measure specification to extract the size from
27790          * @return the size in pixels defined in the supplied measure specification
27791          */
getSize(int measureSpec)27792         public static int getSize(int measureSpec) {
27793             return (measureSpec & ~MODE_MASK);
27794         }
27795 
adjust(int measureSpec, int delta)27796         static int adjust(int measureSpec, int delta) {
27797             final int mode = getMode(measureSpec);
27798             int size = getSize(measureSpec);
27799             if (mode == UNSPECIFIED) {
27800                 // No need to adjust size for UNSPECIFIED mode.
27801                 return makeMeasureSpec(size, UNSPECIFIED);
27802             }
27803             size += delta;
27804             if (size < 0) {
27805                 Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
27806                         ") spec: " + toString(measureSpec) + " delta: " + delta);
27807                 size = 0;
27808             }
27809             return makeMeasureSpec(size, mode);
27810         }
27811 
27812         /**
27813          * Returns a String representation of the specified measure
27814          * specification.
27815          *
27816          * @param measureSpec the measure specification to convert to a String
27817          * @return a String with the following format: "MeasureSpec: MODE SIZE"
27818          */
toString(int measureSpec)27819         public static String toString(int measureSpec) {
27820             int mode = getMode(measureSpec);
27821             int size = getSize(measureSpec);
27822 
27823             StringBuilder sb = new StringBuilder("MeasureSpec: ");
27824 
27825             if (mode == UNSPECIFIED)
27826                 sb.append("UNSPECIFIED ");
27827             else if (mode == EXACTLY)
27828                 sb.append("EXACTLY ");
27829             else if (mode == AT_MOST)
27830                 sb.append("AT_MOST ");
27831             else
27832                 sb.append(mode).append(" ");
27833 
27834             sb.append(size);
27835             return sb.toString();
27836         }
27837     }
27838 
27839     private final class CheckForLongPress implements Runnable {
27840         private int mOriginalWindowAttachCount;
27841         private float mX;
27842         private float mY;
27843         private boolean mOriginalPressedState;
27844         /**
27845          * The classification of the long click being checked: one of the
27846          * StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__* constants.
27847          */
27848         private int mClassification;
27849 
27850         @UnsupportedAppUsage
CheckForLongPress()27851         private CheckForLongPress() {
27852         }
27853 
27854         @Override
run()27855         public void run() {
27856             if ((mOriginalPressedState == isPressed()) && (mParent != null)
27857                     && mOriginalWindowAttachCount == mWindowAttachCount) {
27858                 recordGestureClassification(mClassification);
27859                 if (performLongClick(mX, mY)) {
27860                     mHasPerformedLongPress = true;
27861                 }
27862             }
27863         }
27864 
setAnchor(float x, float y)27865         public void setAnchor(float x, float y) {
27866             mX = x;
27867             mY = y;
27868         }
27869 
rememberWindowAttachCount()27870         public void rememberWindowAttachCount() {
27871             mOriginalWindowAttachCount = mWindowAttachCount;
27872         }
27873 
rememberPressedState()27874         public void rememberPressedState() {
27875             mOriginalPressedState = isPressed();
27876         }
27877 
setClassification(int classification)27878         public void setClassification(int classification) {
27879             mClassification = classification;
27880         }
27881     }
27882 
27883     private final class CheckForTap implements Runnable {
27884         public float x;
27885         public float y;
27886 
27887         @Override
run()27888         public void run() {
27889             mPrivateFlags &= ~PFLAG_PREPRESSED;
27890             setPressed(true, x, y);
27891             final long delay =
27892                     ViewConfiguration.getLongPressTimeout() - ViewConfiguration.getTapTimeout();
27893             checkForLongClick(delay, x, y, TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
27894         }
27895     }
27896 
27897     private final class PerformClick implements Runnable {
27898         @Override
run()27899         public void run() {
27900             recordGestureClassification(TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP);
27901             performClickInternal();
27902         }
27903     }
27904 
27905     /** Records a classification for the current event stream. */
recordGestureClassification(int classification)27906     private void recordGestureClassification(int classification) {
27907         if (classification == TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION) {
27908             return;
27909         }
27910         // To avoid negatively impacting View performance, the latency and displacement metrics
27911         // are omitted.
27912         StatsLog.write(StatsLog.TOUCH_GESTURE_CLASSIFIED, getClass().getName(), classification);
27913     }
27914 
27915     /**
27916      * This method returns a ViewPropertyAnimator object, which can be used to animate
27917      * specific properties on this View.
27918      *
27919      * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
27920      */
animate()27921     public ViewPropertyAnimator animate() {
27922         if (mAnimator == null) {
27923             mAnimator = new ViewPropertyAnimator(this);
27924         }
27925         return mAnimator;
27926     }
27927 
27928     /**
27929      * Sets the name of the View to be used to identify Views in Transitions.
27930      * Names should be unique in the View hierarchy.
27931      *
27932      * @param transitionName The name of the View to uniquely identify it for Transitions.
27933      */
setTransitionName(String transitionName)27934     public final void setTransitionName(String transitionName) {
27935         mTransitionName = transitionName;
27936     }
27937 
27938     /**
27939      * Returns the name of the View to be used to identify Views in Transitions.
27940      * Names should be unique in the View hierarchy.
27941      *
27942      * <p>This returns null if the View has not been given a name.</p>
27943      *
27944      * @return The name used of the View to be used to identify Views in Transitions or null
27945      * if no name has been given.
27946      */
27947     @ViewDebug.ExportedProperty
27948     @InspectableProperty
getTransitionName()27949     public String getTransitionName() {
27950         return mTransitionName;
27951     }
27952 
27953     /**
27954      * @hide
27955      */
requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId)27956     public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
27957         // Do nothing.
27958     }
27959 
27960     /**
27961      * Interface definition for a callback to be invoked when a hardware key event is
27962      * dispatched to this view. The callback will be invoked before the key event is
27963      * given to the view. This is only useful for hardware keyboards; a software input
27964      * method has no obligation to trigger this listener.
27965      */
27966     public interface OnKeyListener {
27967         /**
27968          * Called when a hardware key is dispatched to a view. This allows listeners to
27969          * get a chance to respond before the target view.
27970          * <p>Key presses in software keyboards will generally NOT trigger this method,
27971          * although some may elect to do so in some situations. Do not assume a
27972          * software input method has to be key-based; even if it is, it may use key presses
27973          * in a different way than you expect, so there is no way to reliably catch soft
27974          * input key presses.
27975          *
27976          * @param v The view the key has been dispatched to.
27977          * @param keyCode The code for the physical key that was pressed
27978          * @param event The KeyEvent object containing full information about
27979          *        the event.
27980          * @return True if the listener has consumed the event, false otherwise.
27981          */
onKey(View v, int keyCode, KeyEvent event)27982         boolean onKey(View v, int keyCode, KeyEvent event);
27983     }
27984 
27985     /**
27986      * Interface definition for a callback to be invoked when a hardware key event hasn't
27987      * been handled by the view hierarchy.
27988      */
27989     public interface OnUnhandledKeyEventListener {
27990         /**
27991          * Called when a hardware key is dispatched to a view after being unhandled during normal
27992          * {@link KeyEvent} dispatch.
27993          *
27994          * @param v The view the key has been dispatched to.
27995          * @param event The KeyEvent object containing information about the event.
27996          * @return {@code true} if the listener has consumed the event, {@code false} otherwise.
27997          */
onUnhandledKeyEvent(View v, KeyEvent event)27998         boolean onUnhandledKeyEvent(View v, KeyEvent event);
27999     }
28000 
28001     /**
28002      * Interface definition for a callback to be invoked when a touch event is
28003      * dispatched to this view. The callback will be invoked before the touch
28004      * event is given to the view.
28005      */
28006     public interface OnTouchListener {
28007         /**
28008          * Called when a touch event is dispatched to a view. This allows listeners to
28009          * get a chance to respond before the target view.
28010          *
28011          * @param v The view the touch event has been dispatched to.
28012          * @param event The MotionEvent object containing full information about
28013          *        the event.
28014          * @return True if the listener has consumed the event, false otherwise.
28015          */
onTouch(View v, MotionEvent event)28016         boolean onTouch(View v, MotionEvent event);
28017     }
28018 
28019     /**
28020      * Interface definition for a callback to be invoked when a hover event is
28021      * dispatched to this view. The callback will be invoked before the hover
28022      * event is given to the view.
28023      */
28024     public interface OnHoverListener {
28025         /**
28026          * Called when a hover event is dispatched to a view. This allows listeners to
28027          * get a chance to respond before the target view.
28028          *
28029          * @param v The view the hover event has been dispatched to.
28030          * @param event The MotionEvent object containing full information about
28031          *        the event.
28032          * @return True if the listener has consumed the event, false otherwise.
28033          */
onHover(View v, MotionEvent event)28034         boolean onHover(View v, MotionEvent event);
28035     }
28036 
28037     /**
28038      * Interface definition for a callback to be invoked when a generic motion event is
28039      * dispatched to this view. The callback will be invoked before the generic motion
28040      * event is given to the view.
28041      */
28042     public interface OnGenericMotionListener {
28043         /**
28044          * Called when a generic motion event is dispatched to a view. This allows listeners to
28045          * get a chance to respond before the target view.
28046          *
28047          * @param v The view the generic motion event has been dispatched to.
28048          * @param event The MotionEvent object containing full information about
28049          *        the event.
28050          * @return True if the listener has consumed the event, false otherwise.
28051          */
onGenericMotion(View v, MotionEvent event)28052         boolean onGenericMotion(View v, MotionEvent event);
28053     }
28054 
28055     /**
28056      * Interface definition for a callback to be invoked when a view has been clicked and held.
28057      */
28058     public interface OnLongClickListener {
28059         /**
28060          * Called when a view has been clicked and held.
28061          *
28062          * @param v The view that was clicked and held.
28063          *
28064          * @return true if the callback consumed the long click, false otherwise.
28065          */
onLongClick(View v)28066         boolean onLongClick(View v);
28067     }
28068 
28069     /**
28070      * Interface definition for a callback to be invoked when a drag is being dispatched
28071      * to this view.  The callback will be invoked before the hosting view's own
28072      * onDrag(event) method.  If the listener wants to fall back to the hosting view's
28073      * onDrag(event) behavior, it should return 'false' from this callback.
28074      *
28075      * <div class="special reference">
28076      * <h3>Developer Guides</h3>
28077      * <p>For a guide to implementing drag and drop features, read the
28078      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
28079      * </div>
28080      */
28081     public interface OnDragListener {
28082         /**
28083          * Called when a drag event is dispatched to a view. This allows listeners
28084          * to get a chance to override base View behavior.
28085          *
28086          * @param v The View that received the drag event.
28087          * @param event The {@link android.view.DragEvent} object for the drag event.
28088          * @return {@code true} if the drag event was handled successfully, or {@code false}
28089          * if the drag event was not handled. Note that {@code false} will trigger the View
28090          * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
28091          */
onDrag(View v, DragEvent event)28092         boolean onDrag(View v, DragEvent event);
28093     }
28094 
28095     /**
28096      * Interface definition for a callback to be invoked when the focus state of
28097      * a view changed.
28098      */
28099     public interface OnFocusChangeListener {
28100         /**
28101          * Called when the focus state of a view has changed.
28102          *
28103          * @param v The view whose state has changed.
28104          * @param hasFocus The new focus state of v.
28105          */
onFocusChange(View v, boolean hasFocus)28106         void onFocusChange(View v, boolean hasFocus);
28107     }
28108 
28109     /**
28110      * Interface definition for a callback to be invoked when a view is clicked.
28111      */
28112     public interface OnClickListener {
28113         /**
28114          * Called when a view has been clicked.
28115          *
28116          * @param v The view that was clicked.
28117          */
onClick(View v)28118         void onClick(View v);
28119     }
28120 
28121     /**
28122      * Interface definition for a callback to be invoked when a view is context clicked.
28123      */
28124     public interface OnContextClickListener {
28125         /**
28126          * Called when a view is context clicked.
28127          *
28128          * @param v The view that has been context clicked.
28129          * @return true if the callback consumed the context click, false otherwise.
28130          */
onContextClick(View v)28131         boolean onContextClick(View v);
28132     }
28133 
28134     /**
28135      * Interface definition for a callback to be invoked when the context menu
28136      * for this view is being built.
28137      */
28138     public interface OnCreateContextMenuListener {
28139         /**
28140          * Called when the context menu for this view is being built. It is not
28141          * safe to hold onto the menu after this method returns.
28142          *
28143          * @param menu The context menu that is being built
28144          * @param v The view for which the context menu is being built
28145          * @param menuInfo Extra information about the item for which the
28146          *            context menu should be shown. This information will vary
28147          *            depending on the class of v.
28148          */
onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)28149         void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
28150     }
28151 
28152     /**
28153      * Interface definition for a callback to be invoked when the status bar changes
28154      * visibility.  This reports <strong>global</strong> changes to the system UI
28155      * state, not what the application is requesting.
28156      *
28157      * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
28158      */
28159     public interface OnSystemUiVisibilityChangeListener {
28160         /**
28161          * Called when the status bar changes visibility because of a call to
28162          * {@link View#setSystemUiVisibility(int)}.
28163          *
28164          * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
28165          * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
28166          * This tells you the <strong>global</strong> state of these UI visibility
28167          * flags, not what your app is currently applying.
28168          */
onSystemUiVisibilityChange(int visibility)28169         public void onSystemUiVisibilityChange(int visibility);
28170     }
28171 
28172     /**
28173      * Interface definition for a callback to be invoked when this view is attached
28174      * or detached from its window.
28175      */
28176     public interface OnAttachStateChangeListener {
28177         /**
28178          * Called when the view is attached to a window.
28179          * @param v The view that was attached
28180          */
onViewAttachedToWindow(View v)28181         public void onViewAttachedToWindow(View v);
28182         /**
28183          * Called when the view is detached from a window.
28184          * @param v The view that was detached
28185          */
onViewDetachedFromWindow(View v)28186         public void onViewDetachedFromWindow(View v);
28187     }
28188 
28189     /**
28190      * Listener for applying window insets on a view in a custom way.
28191      *
28192      * <p>Apps may choose to implement this interface if they want to apply custom policy
28193      * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
28194      * is set, its
28195      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
28196      * method will be called instead of the View's own
28197      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
28198      * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
28199      * the View's normal behavior as part of its own.</p>
28200      */
28201     public interface OnApplyWindowInsetsListener {
28202         /**
28203          * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
28204          * on a View, this listener method will be called instead of the view's own
28205          * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
28206          *
28207          * @param v The view applying window insets
28208          * @param insets The insets to apply
28209          * @return The insets supplied, minus any insets that were consumed
28210          */
onApplyWindowInsets(View v, WindowInsets insets)28211         public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
28212     }
28213 
28214     private final class UnsetPressedState implements Runnable {
28215         @Override
run()28216         public void run() {
28217             setPressed(false);
28218         }
28219     }
28220 
28221     /**
28222      * When a view becomes invisible checks if autofill considers the view invisible too. This
28223      * happens after the regular removal operation to make sure the operation is finished by the
28224      * time this is called.
28225      */
28226     private static class VisibilityChangeForAutofillHandler extends Handler {
28227         private final AutofillManager mAfm;
28228         private final View mView;
28229 
VisibilityChangeForAutofillHandler(@onNull AutofillManager afm, @NonNull View view)28230         private VisibilityChangeForAutofillHandler(@NonNull AutofillManager afm,
28231                 @NonNull View view) {
28232             mAfm = afm;
28233             mView = view;
28234         }
28235 
28236         @Override
handleMessage(Message msg)28237         public void handleMessage(Message msg) {
28238             mAfm.notifyViewVisibilityChanged(mView, mView.isShown());
28239         }
28240     }
28241 
28242     /**
28243      * Base class for derived classes that want to save and restore their own
28244      * state in {@link android.view.View#onSaveInstanceState()}.
28245      */
28246     public static class BaseSavedState extends AbsSavedState {
28247         static final int START_ACTIVITY_REQUESTED_WHO_SAVED = 0b1;
28248         static final int IS_AUTOFILLED = 0b10;
28249         static final int AUTOFILL_ID = 0b100;
28250 
28251         // Flags that describe what data in this state is valid
28252         int mSavedData;
28253         String mStartActivityRequestWhoSaved;
28254         boolean mIsAutofilled;
28255         int mAutofillViewId;
28256 
28257         /**
28258          * Constructor used when reading from a parcel. Reads the state of the superclass.
28259          *
28260          * @param source parcel to read from
28261          */
BaseSavedState(Parcel source)28262         public BaseSavedState(Parcel source) {
28263             this(source, null);
28264         }
28265 
28266         /**
28267          * Constructor used when reading from a parcel using a given class loader.
28268          * Reads the state of the superclass.
28269          *
28270          * @param source parcel to read from
28271          * @param loader ClassLoader to use for reading
28272          */
BaseSavedState(Parcel source, ClassLoader loader)28273         public BaseSavedState(Parcel source, ClassLoader loader) {
28274             super(source, loader);
28275             mSavedData = source.readInt();
28276             mStartActivityRequestWhoSaved = source.readString();
28277             mIsAutofilled = source.readBoolean();
28278             mAutofillViewId = source.readInt();
28279         }
28280 
28281         /**
28282          * Constructor called by derived classes when creating their SavedState objects
28283          *
28284          * @param superState The state of the superclass of this view
28285          */
BaseSavedState(Parcelable superState)28286         public BaseSavedState(Parcelable superState) {
28287             super(superState);
28288         }
28289 
28290         @Override
writeToParcel(Parcel out, int flags)28291         public void writeToParcel(Parcel out, int flags) {
28292             super.writeToParcel(out, flags);
28293 
28294             out.writeInt(mSavedData);
28295             out.writeString(mStartActivityRequestWhoSaved);
28296             out.writeBoolean(mIsAutofilled);
28297             out.writeInt(mAutofillViewId);
28298         }
28299 
28300         public static final @android.annotation.NonNull Parcelable.Creator<BaseSavedState> CREATOR
28301                 = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
28302             @Override
28303             public BaseSavedState createFromParcel(Parcel in) {
28304                 return new BaseSavedState(in);
28305             }
28306 
28307             @Override
28308             public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
28309                 return new BaseSavedState(in, loader);
28310             }
28311 
28312             @Override
28313             public BaseSavedState[] newArray(int size) {
28314                 return new BaseSavedState[size];
28315             }
28316         };
28317     }
28318 
28319     /**
28320      * A set of information given to a view when it is attached to its parent
28321      * window.
28322      */
28323     final static class AttachInfo {
28324         interface Callbacks {
playSoundEffect(int effectId)28325             void playSoundEffect(int effectId);
performHapticFeedback(int effectId, boolean always)28326             boolean performHapticFeedback(int effectId, boolean always);
28327         }
28328 
28329         /**
28330          * InvalidateInfo is used to post invalidate(int, int, int, int) messages
28331          * to a Handler. This class contains the target (View) to invalidate and
28332          * the coordinates of the dirty rectangle.
28333          *
28334          * For performance purposes, this class also implements a pool of up to
28335          * POOL_LIMIT objects that get reused. This reduces memory allocations
28336          * whenever possible.
28337          */
28338         static class InvalidateInfo {
28339 
28340             @UnsupportedAppUsage
InvalidateInfo()28341             InvalidateInfo() {
28342             }
28343 
28344             private static final int POOL_LIMIT = 10;
28345 
28346             private static final SynchronizedPool<InvalidateInfo> sPool =
28347                     new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
28348 
28349             @UnsupportedAppUsage
28350             View target;
28351 
28352             @UnsupportedAppUsage
28353             int left;
28354             @UnsupportedAppUsage
28355             int top;
28356             @UnsupportedAppUsage
28357             int right;
28358             @UnsupportedAppUsage
28359             int bottom;
28360 
obtain()28361             public static InvalidateInfo obtain() {
28362                 InvalidateInfo instance = sPool.acquire();
28363                 return (instance != null) ? instance : new InvalidateInfo();
28364             }
28365 
recycle()28366             public void recycle() {
28367                 target = null;
28368                 sPool.release(this);
28369             }
28370         }
28371 
28372         @UnsupportedAppUsage
28373         final IWindowSession mSession;
28374 
28375         @UnsupportedAppUsage
28376         final IWindow mWindow;
28377 
28378         final IBinder mWindowToken;
28379 
28380         Display mDisplay;
28381 
28382         final Callbacks mRootCallbacks;
28383 
28384         IWindowId mIWindowId;
28385         WindowId mWindowId;
28386 
28387         /**
28388          * The top view of the hierarchy.
28389          */
28390         View mRootView;
28391 
28392         IBinder mPanelParentWindowToken;
28393 
28394         boolean mHardwareAccelerated;
28395         boolean mHardwareAccelerationRequested;
28396         ThreadedRenderer mThreadedRenderer;
28397         List<RenderNode> mPendingAnimatingRenderNodes;
28398 
28399         /**
28400          * The state of the display to which the window is attached, as reported
28401          * by {@link Display#getState()}.  Note that the display state constants
28402          * declared by {@link Display} do not exactly line up with the screen state
28403          * constants declared by {@link View} (there are more display states than
28404          * screen states).
28405          */
28406         @UnsupportedAppUsage
28407         int mDisplayState = Display.STATE_UNKNOWN;
28408 
28409         /**
28410          * Scale factor used by the compatibility mode
28411          */
28412         @UnsupportedAppUsage
28413         float mApplicationScale;
28414 
28415         /**
28416          * Indicates whether the application is in compatibility mode
28417          */
28418         @UnsupportedAppUsage
28419         boolean mScalingRequired;
28420 
28421         /**
28422          * Left position of this view's window
28423          */
28424         int mWindowLeft;
28425 
28426         /**
28427          * Top position of this view's window
28428          */
28429         int mWindowTop;
28430 
28431         /**
28432          * Indicates whether views need to use 32-bit drawing caches
28433          */
28434         boolean mUse32BitDrawingCache;
28435 
28436         /**
28437          * For windows that are full-screen but using insets to layout inside
28438          * of the screen areas, these are the current insets to appear inside
28439          * the overscan area of the display.
28440          */
28441         final Rect mOverscanInsets = new Rect();
28442 
28443         /**
28444          * For windows that are full-screen but using insets to layout inside
28445          * of the screen decorations, these are the current insets for the
28446          * content of the window.
28447          */
28448         @UnsupportedAppUsage
28449         final Rect mContentInsets = new Rect();
28450 
28451         /**
28452          * For windows that are full-screen but using insets to layout inside
28453          * of the screen decorations, these are the current insets for the
28454          * actual visible parts of the window.
28455          */
28456         @UnsupportedAppUsage
28457         final Rect mVisibleInsets = new Rect();
28458 
28459         /**
28460          * For windows that are full-screen but using insets to layout inside
28461          * of the screen decorations, these are the current insets for the
28462          * stable system windows.
28463          */
28464         @UnsupportedAppUsage
28465         final Rect mStableInsets = new Rect();
28466 
28467         final DisplayCutout.ParcelableWrapper mDisplayCutout =
28468                 new DisplayCutout.ParcelableWrapper(DisplayCutout.NO_CUTOUT);
28469 
28470         /**
28471          * For windows that include areas that are not covered by real surface these are the outsets
28472          * for real surface.
28473          */
28474         final Rect mOutsets = new Rect();
28475 
28476         /**
28477          * In multi-window we force show the system bars. Because we don't want that the surface
28478          * size changes in this mode, we instead have a flag whether the system bars sizes should
28479          * always be consumed, so the app is treated like there are no virtual system bars at all.
28480          */
28481         boolean mAlwaysConsumeSystemBars;
28482 
28483         /**
28484          * The internal insets given by this window.  This value is
28485          * supplied by the client (through
28486          * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
28487          * be given to the window manager when changed to be used in laying
28488          * out windows behind it.
28489          */
28490         @UnsupportedAppUsage
28491         final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
28492                 = new ViewTreeObserver.InternalInsetsInfo();
28493 
28494         /**
28495          * Set to true when mGivenInternalInsets is non-empty.
28496          */
28497         boolean mHasNonEmptyGivenInternalInsets;
28498 
28499         /**
28500          * All views in the window's hierarchy that serve as scroll containers,
28501          * used to determine if the window can be resized or must be panned
28502          * to adjust for a soft input area.
28503          */
28504         @UnsupportedAppUsage
28505         final ArrayList<View> mScrollContainers = new ArrayList<View>();
28506 
28507         @UnsupportedAppUsage
28508         final KeyEvent.DispatcherState mKeyDispatchState
28509                 = new KeyEvent.DispatcherState();
28510 
28511         /**
28512          * Indicates whether the view's window currently has the focus.
28513          */
28514         @UnsupportedAppUsage
28515         boolean mHasWindowFocus;
28516 
28517         /**
28518          * The current visibility of the window.
28519          */
28520         int mWindowVisibility;
28521 
28522         /**
28523          * Indicates the time at which drawing started to occur.
28524          */
28525         @UnsupportedAppUsage
28526         long mDrawingTime;
28527 
28528         /**
28529          * Indicates whether the view's window is currently in touch mode.
28530          */
28531         @UnsupportedAppUsage
28532         boolean mInTouchMode;
28533 
28534         /**
28535          * Indicates whether the view has requested unbuffered input dispatching for the current
28536          * event stream.
28537          */
28538         boolean mUnbufferedDispatchRequested;
28539 
28540         /**
28541          * Indicates that ViewAncestor should trigger a global layout change
28542          * the next time it performs a traversal
28543          */
28544         @UnsupportedAppUsage
28545         boolean mRecomputeGlobalAttributes;
28546 
28547         /**
28548          * Always report new attributes at next traversal.
28549          */
28550         boolean mForceReportNewAttributes;
28551 
28552         /**
28553          * Set during a traveral if any views want to keep the screen on.
28554          */
28555         @UnsupportedAppUsage
28556         boolean mKeepScreenOn;
28557 
28558         /**
28559          * Set during a traveral if the light center needs to be updated.
28560          */
28561         boolean mNeedsUpdateLightCenter;
28562 
28563         /**
28564          * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
28565          */
28566         int mSystemUiVisibility;
28567 
28568         /**
28569          * Hack to force certain system UI visibility flags to be cleared.
28570          */
28571         int mDisabledSystemUiVisibility;
28572 
28573         /**
28574          * Last global system UI visibility reported by the window manager.
28575          */
28576         int mGlobalSystemUiVisibility = -1;
28577 
28578         /**
28579          * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
28580          * attached.
28581          */
28582         boolean mHasSystemUiListeners;
28583 
28584         /**
28585          * Set if the window has requested to extend into the overscan region
28586          * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
28587          */
28588         boolean mOverscanRequested;
28589 
28590         /**
28591          * Set if the visibility of any views has changed.
28592          */
28593         @UnsupportedAppUsage
28594         boolean mViewVisibilityChanged;
28595 
28596         /**
28597          * Set to true if a view has been scrolled.
28598          */
28599         @UnsupportedAppUsage
28600         boolean mViewScrollChanged;
28601 
28602         /**
28603          * Set to true if a pointer event is currently being handled.
28604          */
28605         boolean mHandlingPointerEvent;
28606 
28607         /**
28608          * The offset of this view's window when it's on an embedded display that is re-parented
28609          * to another window.
28610          */
28611         final Point mLocationInParentDisplay = new Point();
28612 
28613         /**
28614          * Global to the view hierarchy used as a temporary for dealing with
28615          * x/y points in the transparent region computations.
28616          */
28617         final int[] mTransparentLocation = new int[2];
28618 
28619         /**
28620          * Global to the view hierarchy used as a temporary for dealing with
28621          * x/y points in the ViewGroup.invalidateChild implementation.
28622          */
28623         final int[] mInvalidateChildLocation = new int[2];
28624 
28625         /**
28626          * Global to the view hierarchy used as a temporary for dealing with
28627          * computing absolute on-screen location.
28628          */
28629         final int[] mTmpLocation = new int[2];
28630 
28631         /**
28632          * Global to the view hierarchy used as a temporary for dealing with
28633          * x/y location when view is transformed.
28634          */
28635         final float[] mTmpTransformLocation = new float[2];
28636 
28637         /**
28638          * The view tree observer used to dispatch global events like
28639          * layout, pre-draw, touch mode change, etc.
28640          */
28641         @UnsupportedAppUsage
28642         final ViewTreeObserver mTreeObserver;
28643 
28644         /**
28645          * A Canvas used by the view hierarchy to perform bitmap caching.
28646          */
28647         Canvas mCanvas;
28648 
28649         /**
28650          * The view root impl.
28651          */
28652         final ViewRootImpl mViewRootImpl;
28653 
28654         /**
28655          * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
28656          * handler can be used to pump events in the UI events queue.
28657          */
28658         @UnsupportedAppUsage
28659         final Handler mHandler;
28660 
28661         /**
28662          * Temporary for use in computing invalidate rectangles while
28663          * calling up the hierarchy.
28664          */
28665         final Rect mTmpInvalRect = new Rect();
28666 
28667         /**
28668          * Temporary for use in computing hit areas with transformed views
28669          */
28670         final RectF mTmpTransformRect = new RectF();
28671 
28672         /**
28673          * Temporary for use in computing hit areas with transformed views
28674          */
28675         final RectF mTmpTransformRect1 = new RectF();
28676 
28677         /**
28678          * Temporary list of rectanges.
28679          */
28680         final List<RectF> mTmpRectList = new ArrayList<>();
28681 
28682         /**
28683          * Temporary for use in transforming invalidation rect
28684          */
28685         final Matrix mTmpMatrix = new Matrix();
28686 
28687         /**
28688          * Temporary for use in transforming invalidation rect
28689          */
28690         final Transformation mTmpTransformation = new Transformation();
28691 
28692         /**
28693          * Temporary for use in querying outlines from OutlineProviders
28694          */
28695         final Outline mTmpOutline = new Outline();
28696 
28697         /**
28698          * Temporary list for use in collecting focusable descendents of a view.
28699          */
28700         final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
28701 
28702         /**
28703          * The id of the window for accessibility purposes.
28704          */
28705         int mAccessibilityWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
28706 
28707         /**
28708          * Flags related to accessibility processing.
28709          *
28710          * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
28711          * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
28712          */
28713         int mAccessibilityFetchFlags;
28714 
28715         /**
28716          * The drawable for highlighting accessibility focus.
28717          */
28718         Drawable mAccessibilityFocusDrawable;
28719 
28720         /**
28721          * The drawable for highlighting autofilled views.
28722          *
28723          * @see #isAutofilled()
28724          */
28725         Drawable mAutofilledDrawable;
28726 
28727         /**
28728          * Show where the margins, bounds and layout bounds are for each view.
28729          */
28730         boolean mDebugLayout = DisplayProperties.debug_layout().orElse(false);
28731 
28732         /**
28733          * Point used to compute visible regions.
28734          */
28735         final Point mPoint = new Point();
28736 
28737         /**
28738          * Used to track which View originated a requestLayout() call, used when
28739          * requestLayout() is called during layout.
28740          */
28741         View mViewRequestingLayout;
28742 
28743         /**
28744          * Used to track the identity of the current drag operation.
28745          */
28746         IBinder mDragToken;
28747 
28748         /**
28749          * The drag shadow surface for the current drag operation.
28750          */
28751         public Surface mDragSurface;
28752 
28753 
28754         /**
28755          * The view that currently has a tooltip displayed.
28756          */
28757         View mTooltipHost;
28758 
28759         /**
28760          * The initial structure has been reported so the view is ready to report updates.
28761          */
28762         boolean mReadyForContentCaptureUpdates;
28763 
28764         /**
28765          * Map(keyed by session) of content capture events that need to be notified after the view
28766          * hierarchy is traversed: value is either the view itself for appearead events, or its
28767          * autofill id for disappeared.
28768          */
28769         SparseArray<ArrayList<Object>> mContentCaptureEvents;
28770 
28771         /**
28772          * Cached reference to the {@link ContentCaptureManager}.
28773          */
28774         ContentCaptureManager mContentCaptureManager;
28775 
28776         /**
28777          * Creates a new set of attachment information with the specified
28778          * events handler and thread.
28779          *
28780          * @param handler the events handler the view must use
28781          */
AttachInfo(IWindowSession session, IWindow window, Display display, ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer, Context context)28782         AttachInfo(IWindowSession session, IWindow window, Display display,
28783                 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer,
28784                 Context context) {
28785             mSession = session;
28786             mWindow = window;
28787             mWindowToken = window.asBinder();
28788             mDisplay = display;
28789             mViewRootImpl = viewRootImpl;
28790             mHandler = handler;
28791             mRootCallbacks = effectPlayer;
28792             mTreeObserver = new ViewTreeObserver(context);
28793         }
28794 
delayNotifyContentCaptureEvent(@onNull ContentCaptureSession session, @NonNull View view, boolean appeared)28795         private void delayNotifyContentCaptureEvent(@NonNull ContentCaptureSession session,
28796                 @NonNull View view, boolean appeared) {
28797             if (mContentCaptureEvents == null) {
28798                 // Most of the time there will be just one session, so intial capacity is 1
28799                 mContentCaptureEvents = new SparseArray<>(1);
28800             }
28801             int sessionId = session.getId();
28802             // TODO: life would be much easier if we provided a MultiMap implementation somwhere...
28803             ArrayList<Object> events = mContentCaptureEvents.get(sessionId);
28804             if (events == null) {
28805                 events = new ArrayList<>();
28806                 mContentCaptureEvents.put(sessionId, events);
28807             }
28808             events.add(appeared ? view : view.getAutofillId());
28809         }
28810 
28811         @Nullable
getContentCaptureManager(@onNull Context context)28812         ContentCaptureManager getContentCaptureManager(@NonNull Context context) {
28813             if (mContentCaptureManager != null) {
28814                 return mContentCaptureManager;
28815             }
28816             mContentCaptureManager = context.getSystemService(ContentCaptureManager.class);
28817             return mContentCaptureManager;
28818         }
28819     }
28820 
28821     /**
28822      * <p>ScrollabilityCache holds various fields used by a View when scrolling
28823      * is supported. This avoids keeping too many unused fields in most
28824      * instances of View.</p>
28825      */
28826     private static class ScrollabilityCache implements Runnable {
28827 
28828         /**
28829          * Scrollbars are not visible
28830          */
28831         public static final int OFF = 0;
28832 
28833         /**
28834          * Scrollbars are visible
28835          */
28836         public static final int ON = 1;
28837 
28838         /**
28839          * Scrollbars are fading away
28840          */
28841         public static final int FADING = 2;
28842 
28843         public boolean fadeScrollBars;
28844 
28845         public int fadingEdgeLength;
28846         public int scrollBarDefaultDelayBeforeFade;
28847         public int scrollBarFadeDuration;
28848 
28849         public int scrollBarSize;
28850         public int scrollBarMinTouchTarget;
28851         @UnsupportedAppUsage
28852         public ScrollBarDrawable scrollBar;
28853         public float[] interpolatorValues;
28854         @UnsupportedAppUsage
28855         public View host;
28856 
28857         public final Paint paint;
28858         public final Matrix matrix;
28859         public Shader shader;
28860 
28861         public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
28862 
28863         private static final float[] OPAQUE = { 255 };
28864         private static final float[] TRANSPARENT = { 0.0f };
28865 
28866         /**
28867          * When fading should start. This time moves into the future every time
28868          * a new scroll happens. Measured based on SystemClock.uptimeMillis()
28869          */
28870         public long fadeStartTime;
28871 
28872 
28873         /**
28874          * The current state of the scrollbars: ON, OFF, or FADING
28875          */
28876         @UnsupportedAppUsage
28877         public int state = OFF;
28878 
28879         private int mLastColor;
28880 
28881         public final Rect mScrollBarBounds = new Rect();
28882         public final Rect mScrollBarTouchBounds = new Rect();
28883 
28884         public static final int NOT_DRAGGING = 0;
28885         public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
28886         public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
28887         public int mScrollBarDraggingState = NOT_DRAGGING;
28888 
28889         public float mScrollBarDraggingPos = 0;
28890 
ScrollabilityCache(ViewConfiguration configuration, View host)28891         public ScrollabilityCache(ViewConfiguration configuration, View host) {
28892             fadingEdgeLength = configuration.getScaledFadingEdgeLength();
28893             scrollBarSize = configuration.getScaledScrollBarSize();
28894             scrollBarMinTouchTarget = configuration.getScaledMinScrollbarTouchTarget();
28895             scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
28896             scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
28897 
28898             paint = new Paint();
28899             matrix = new Matrix();
28900             // use use a height of 1, and then wack the matrix each time we
28901             // actually use it.
28902             shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
28903             paint.setShader(shader);
28904             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
28905 
28906             this.host = host;
28907         }
28908 
setFadeColor(int color)28909         public void setFadeColor(int color) {
28910             if (color != mLastColor) {
28911                 mLastColor = color;
28912 
28913                 if (color != 0) {
28914                     shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
28915                             color & 0x00FFFFFF, Shader.TileMode.CLAMP);
28916                     paint.setShader(shader);
28917                     // Restore the default transfer mode (src_over)
28918                     paint.setXfermode(null);
28919                 } else {
28920                     shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
28921                     paint.setShader(shader);
28922                     paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
28923                 }
28924             }
28925         }
28926 
run()28927         public void run() {
28928             long now = AnimationUtils.currentAnimationTimeMillis();
28929             if (now >= fadeStartTime) {
28930 
28931                 // the animation fades the scrollbars out by changing
28932                 // the opacity (alpha) from fully opaque to fully
28933                 // transparent
28934                 int nextFrame = (int) now;
28935                 int framesCount = 0;
28936 
28937                 Interpolator interpolator = scrollBarInterpolator;
28938 
28939                 // Start opaque
28940                 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
28941 
28942                 // End transparent
28943                 nextFrame += scrollBarFadeDuration;
28944                 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
28945 
28946                 state = FADING;
28947 
28948                 // Kick off the fade animation
28949                 host.invalidate(true);
28950             }
28951         }
28952     }
28953 
28954     /**
28955      * Resuable callback for sending
28956      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
28957      */
28958     private class SendViewScrolledAccessibilityEvent implements Runnable {
28959         public volatile boolean mIsPending;
28960         public int mDeltaX;
28961         public int mDeltaY;
28962 
post(int dx, int dy)28963         public void post(int dx, int dy) {
28964             mDeltaX += dx;
28965             mDeltaY += dy;
28966             if (!mIsPending) {
28967                 mIsPending = true;
28968                 postDelayed(this, ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
28969             }
28970         }
28971 
28972         @Override
run()28973         public void run() {
28974             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
28975                 AccessibilityEvent event = AccessibilityEvent.obtain(
28976                         AccessibilityEvent.TYPE_VIEW_SCROLLED);
28977                 event.setScrollDeltaX(mDeltaX);
28978                 event.setScrollDeltaY(mDeltaY);
28979                 sendAccessibilityEventUnchecked(event);
28980             }
28981             reset();
28982         }
28983 
reset()28984         private void reset() {
28985             mIsPending = false;
28986             mDeltaX = 0;
28987             mDeltaY = 0;
28988         }
28989     }
28990 
28991     /**
28992      * Remove the pending callback for sending a
28993      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
28994      */
28995     @UnsupportedAppUsage
cancel(@ullable SendViewScrolledAccessibilityEvent callback)28996     private void cancel(@Nullable SendViewScrolledAccessibilityEvent callback) {
28997         if (callback == null || !callback.mIsPending) return;
28998         removeCallbacks(callback);
28999         callback.reset();
29000     }
29001 
29002     /**
29003      * <p>
29004      * This class represents a delegate that can be registered in a {@link View}
29005      * to enhance accessibility support via composition rather via inheritance.
29006      * It is specifically targeted to widget developers that extend basic View
29007      * classes i.e. classes in package android.view, that would like their
29008      * applications to be backwards compatible.
29009      * </p>
29010      * <div class="special reference">
29011      * <h3>Developer Guides</h3>
29012      * <p>For more information about making applications accessible, read the
29013      * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
29014      * developer guide.</p>
29015      * </div>
29016      * <p>
29017      * A scenario in which a developer would like to use an accessibility delegate
29018      * is overriding a method introduced in a later API version than the minimal API
29019      * version supported by the application. For example, the method
29020      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
29021      * in API version 4 when the accessibility APIs were first introduced. If a
29022      * developer would like their application to run on API version 4 devices (assuming
29023      * all other APIs used by the application are version 4 or lower) and take advantage
29024      * of this method, instead of overriding the method which would break the application's
29025      * backwards compatibility, they can override the corresponding method in this
29026      * delegate and register the delegate in the target View if the API version of
29027      * the system is high enough, i.e. the API version is the same as or higher than the API
29028      * version that introduced
29029      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
29030      * </p>
29031      * <p>
29032      * Here is an example implementation:
29033      * </p>
29034      * <code><pre><p>
29035      * if (Build.VERSION.SDK_INT >= 14) {
29036      *     // If the API version is equal of higher than the version in
29037      *     // which onInitializeAccessibilityNodeInfo was introduced we
29038      *     // register a delegate with a customized implementation.
29039      *     View view = findViewById(R.id.view_id);
29040      *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
29041      *         public void onInitializeAccessibilityNodeInfo(View host,
29042      *                 AccessibilityNodeInfo info) {
29043      *             // Let the default implementation populate the info.
29044      *             super.onInitializeAccessibilityNodeInfo(host, info);
29045      *             // Set some other information.
29046      *             info.setEnabled(host.isEnabled());
29047      *         }
29048      *     });
29049      * }
29050      * </code></pre></p>
29051      * <p>
29052      * This delegate contains methods that correspond to the accessibility methods
29053      * in View. If a delegate has been specified the implementation in View hands
29054      * off handling to the corresponding method in this delegate. The default
29055      * implementation the delegate methods behaves exactly as the corresponding
29056      * method in View for the case of no accessibility delegate been set. Hence,
29057      * to customize the behavior of a View method, clients can override only the
29058      * corresponding delegate method without altering the behavior of the rest
29059      * accessibility related methods of the host view.
29060      * </p>
29061      * <p>
29062      * <strong>Note:</strong> On platform versions prior to
29063      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
29064      * views in the {@code android.widget.*} package are called <i>before</i>
29065      * host methods. This prevents certain properties such as class name from
29066      * being modified by overriding
29067      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
29068      * as any changes will be overwritten by the host class.
29069      * <p>
29070      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
29071      * methods are called <i>after</i> host methods, which all properties to be
29072      * modified without being overwritten by the host class.
29073      */
29074     public static class AccessibilityDelegate {
29075 
29076         /**
29077          * Sends an accessibility event of the given type. If accessibility is not
29078          * enabled this method has no effect.
29079          * <p>
29080          * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
29081          *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
29082          * been set.
29083          * </p>
29084          *
29085          * @param host The View hosting the delegate.
29086          * @param eventType The type of the event to send.
29087          *
29088          * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
29089          */
sendAccessibilityEvent(View host, int eventType)29090         public void sendAccessibilityEvent(View host, int eventType) {
29091             host.sendAccessibilityEventInternal(eventType);
29092         }
29093 
29094         /**
29095          * Performs the specified accessibility action on the view. For
29096          * possible accessibility actions look at {@link AccessibilityNodeInfo}.
29097          * <p>
29098          * The default implementation behaves as
29099          * {@link View#performAccessibilityAction(int, Bundle)
29100          *  View#performAccessibilityAction(int, Bundle)} for the case of
29101          *  no accessibility delegate been set.
29102          * </p>
29103          *
29104          * @param action The action to perform.
29105          * @return Whether the action was performed.
29106          *
29107          * @see View#performAccessibilityAction(int, Bundle)
29108          *      View#performAccessibilityAction(int, Bundle)
29109          */
performAccessibilityAction(View host, int action, Bundle args)29110         public boolean performAccessibilityAction(View host, int action, Bundle args) {
29111             return host.performAccessibilityActionInternal(action, args);
29112         }
29113 
29114         /**
29115          * Sends an accessibility event. This method behaves exactly as
29116          * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
29117          * empty {@link AccessibilityEvent} and does not perform a check whether
29118          * accessibility is enabled.
29119          * <p>
29120          * The default implementation behaves as
29121          * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
29122          *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
29123          * the case of no accessibility delegate been set.
29124          * </p>
29125          *
29126          * @param host The View hosting the delegate.
29127          * @param event The event to send.
29128          *
29129          * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
29130          *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
29131          */
sendAccessibilityEventUnchecked(View host, AccessibilityEvent event)29132         public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
29133             host.sendAccessibilityEventUncheckedInternal(event);
29134         }
29135 
29136         /**
29137          * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
29138          * to its children for adding their text content to the event.
29139          * <p>
29140          * The default implementation behaves as
29141          * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
29142          *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
29143          * the case of no accessibility delegate been set.
29144          * </p>
29145          *
29146          * @param host The View hosting the delegate.
29147          * @param event The event.
29148          * @return True if the event population was completed.
29149          *
29150          * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
29151          *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
29152          */
dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event)29153         public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
29154             return host.dispatchPopulateAccessibilityEventInternal(event);
29155         }
29156 
29157         /**
29158          * Gives a chance to the host View to populate the accessibility event with its
29159          * text content.
29160          * <p>
29161          * The default implementation behaves as
29162          * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
29163          *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
29164          * the case of no accessibility delegate been set.
29165          * </p>
29166          *
29167          * @param host The View hosting the delegate.
29168          * @param event The accessibility event which to populate.
29169          *
29170          * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
29171          *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
29172          */
onPopulateAccessibilityEvent(View host, AccessibilityEvent event)29173         public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
29174             host.onPopulateAccessibilityEventInternal(event);
29175         }
29176 
29177         /**
29178          * Initializes an {@link AccessibilityEvent} with information about the
29179          * the host View which is the event source.
29180          * <p>
29181          * The default implementation behaves as
29182          * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
29183          *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
29184          * the case of no accessibility delegate been set.
29185          * </p>
29186          *
29187          * @param host The View hosting the delegate.
29188          * @param event The event to initialize.
29189          *
29190          * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
29191          *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
29192          */
onInitializeAccessibilityEvent(View host, AccessibilityEvent event)29193         public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
29194             host.onInitializeAccessibilityEventInternal(event);
29195         }
29196 
29197         /**
29198          * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
29199          * <p>
29200          * The default implementation behaves as
29201          * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
29202          *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
29203          * the case of no accessibility delegate been set.
29204          * </p>
29205          *
29206          * @param host The View hosting the delegate.
29207          * @param info The instance to initialize.
29208          *
29209          * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
29210          *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
29211          */
onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info)29212         public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
29213             host.onInitializeAccessibilityNodeInfoInternal(info);
29214         }
29215 
29216         /**
29217          * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
29218          * additional data.
29219          * <p>
29220          * This method only needs to be implemented if the View offers to provide additional data.
29221          * </p>
29222          * <p>
29223          * The default implementation behaves as
29224          * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, String, Bundle)
29225          * for the case where no accessibility delegate is set.
29226          * </p>
29227          *
29228          * @param host The View hosting the delegate. Never {@code null}.
29229          * @param info The info to which to add the extra data. Never {@code null}.
29230          * @param extraDataKey A key specifying the type of extra data to add to the info. The
29231          *                     extra data should be added to the {@link Bundle} returned by
29232          *                     the info's {@link AccessibilityNodeInfo#getExtras} method.  Never
29233          *                     {@code null}.
29234          * @param arguments A {@link Bundle} holding any arguments relevant for this request.
29235          *                  May be {@code null} if the if the service provided no arguments.
29236          *
29237          * @see AccessibilityNodeInfo#setAvailableExtraData(List)
29238          */
addExtraDataToAccessibilityNodeInfo(@onNull View host, @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey, @Nullable Bundle arguments)29239         public void addExtraDataToAccessibilityNodeInfo(@NonNull View host,
29240                 @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
29241                 @Nullable Bundle arguments) {
29242             host.addExtraDataToAccessibilityNodeInfo(info, extraDataKey, arguments);
29243         }
29244 
29245         /**
29246          * Called when a child of the host View has requested sending an
29247          * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
29248          * to augment the event.
29249          * <p>
29250          * The default implementation behaves as
29251          * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
29252          *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
29253          * the case of no accessibility delegate been set.
29254          * </p>
29255          *
29256          * @param host The View hosting the delegate.
29257          * @param child The child which requests sending the event.
29258          * @param event The event to be sent.
29259          * @return True if the event should be sent
29260          *
29261          * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
29262          *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
29263          */
onRequestSendAccessibilityEvent(ViewGroup host, View child, AccessibilityEvent event)29264         public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
29265                 AccessibilityEvent event) {
29266             return host.onRequestSendAccessibilityEventInternal(child, event);
29267         }
29268 
29269         /**
29270          * Gets the provider for managing a virtual view hierarchy rooted at this View
29271          * and reported to {@link android.accessibilityservice.AccessibilityService}s
29272          * that explore the window content.
29273          * <p>
29274          * The default implementation behaves as
29275          * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
29276          * the case of no accessibility delegate been set.
29277          * </p>
29278          *
29279          * @return The provider.
29280          *
29281          * @see AccessibilityNodeProvider
29282          */
getAccessibilityNodeProvider(View host)29283         public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
29284             return null;
29285         }
29286 
29287         /**
29288          * Returns an {@link AccessibilityNodeInfo} representing the host view from the
29289          * point of view of an {@link android.accessibilityservice.AccessibilityService}.
29290          * This method is responsible for obtaining an accessibility node info from a
29291          * pool of reusable instances and calling
29292          * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
29293          * view to initialize the former.
29294          * <p>
29295          * <strong>Note:</strong> The client is responsible for recycling the obtained
29296          * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
29297          * creation.
29298          * </p>
29299          * <p>
29300          * The default implementation behaves as
29301          * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
29302          * the case of no accessibility delegate been set.
29303          * </p>
29304          * @return A populated {@link AccessibilityNodeInfo}.
29305          *
29306          * @see AccessibilityNodeInfo
29307          *
29308          * @hide
29309          */
29310         @UnsupportedAppUsage
createAccessibilityNodeInfo(View host)29311         public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
29312             return host.createAccessibilityNodeInfoInternal();
29313         }
29314     }
29315 
29316     private static class MatchIdPredicate implements Predicate<View> {
29317         public int mId;
29318 
29319         @Override
test(View view)29320         public boolean test(View view) {
29321             return (view.mID == mId);
29322         }
29323     }
29324 
29325     private static class MatchLabelForPredicate implements Predicate<View> {
29326         private int mLabeledId;
29327 
29328         @Override
test(View view)29329         public boolean test(View view) {
29330             return (view.mLabelForId == mLabeledId);
29331         }
29332     }
29333 
29334     /**
29335      * Dump all private flags in readable format, useful for documentation and
29336      * consistency checking.
29337      */
dumpFlags()29338     private static void dumpFlags() {
29339         final HashMap<String, String> found = Maps.newHashMap();
29340         try {
29341             for (Field field : View.class.getDeclaredFields()) {
29342                 final int modifiers = field.getModifiers();
29343                 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
29344                     if (field.getType().equals(int.class)) {
29345                         final int value = field.getInt(null);
29346                         dumpFlag(found, field.getName(), value);
29347                     } else if (field.getType().equals(int[].class)) {
29348                         final int[] values = (int[]) field.get(null);
29349                         for (int i = 0; i < values.length; i++) {
29350                             dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
29351                         }
29352                     }
29353                 }
29354             }
29355         } catch (IllegalAccessException e) {
29356             throw new RuntimeException(e);
29357         }
29358 
29359         final ArrayList<String> keys = Lists.newArrayList();
29360         keys.addAll(found.keySet());
29361         Collections.sort(keys);
29362         for (String key : keys) {
29363             Log.d(VIEW_LOG_TAG, found.get(key));
29364         }
29365     }
29366 
dumpFlag(HashMap<String, String> found, String name, int value)29367     private static void dumpFlag(HashMap<String, String> found, String name, int value) {
29368         // Sort flags by prefix, then by bits, always keeping unique keys
29369         final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
29370         final int prefix = name.indexOf('_');
29371         final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
29372         final String output = bits + " " + name;
29373         found.put(key, output);
29374     }
29375 
29376     /** {@hide} */
encode(@onNull ViewHierarchyEncoder stream)29377     public void encode(@NonNull ViewHierarchyEncoder stream) {
29378         stream.beginObject(this);
29379         encodeProperties(stream);
29380         stream.endObject();
29381     }
29382 
29383     /** {@hide} */
29384     @CallSuper
encodeProperties(@onNull ViewHierarchyEncoder stream)29385     protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
29386         Object resolveId = ViewDebug.resolveId(getContext(), mID);
29387         if (resolveId instanceof String) {
29388             stream.addProperty("id", (String) resolveId);
29389         } else {
29390             stream.addProperty("id", mID);
29391         }
29392 
29393         stream.addProperty("misc:transformation.alpha",
29394                 mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
29395         stream.addProperty("misc:transitionName", getTransitionName());
29396 
29397         // layout
29398         stream.addProperty("layout:left", mLeft);
29399         stream.addProperty("layout:right", mRight);
29400         stream.addProperty("layout:top", mTop);
29401         stream.addProperty("layout:bottom", mBottom);
29402         stream.addProperty("layout:width", getWidth());
29403         stream.addProperty("layout:height", getHeight());
29404         stream.addProperty("layout:layoutDirection", getLayoutDirection());
29405         stream.addProperty("layout:layoutRtl", isLayoutRtl());
29406         stream.addProperty("layout:hasTransientState", hasTransientState());
29407         stream.addProperty("layout:baseline", getBaseline());
29408 
29409         // layout params
29410         ViewGroup.LayoutParams layoutParams = getLayoutParams();
29411         if (layoutParams != null) {
29412             stream.addPropertyKey("layoutParams");
29413             layoutParams.encode(stream);
29414         }
29415 
29416         // scrolling
29417         stream.addProperty("scrolling:scrollX", mScrollX);
29418         stream.addProperty("scrolling:scrollY", mScrollY);
29419 
29420         // padding
29421         stream.addProperty("padding:paddingLeft", mPaddingLeft);
29422         stream.addProperty("padding:paddingRight", mPaddingRight);
29423         stream.addProperty("padding:paddingTop", mPaddingTop);
29424         stream.addProperty("padding:paddingBottom", mPaddingBottom);
29425         stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
29426         stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
29427         stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
29428         stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
29429         stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
29430 
29431         // measurement
29432         stream.addProperty("measurement:minHeight", mMinHeight);
29433         stream.addProperty("measurement:minWidth", mMinWidth);
29434         stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
29435         stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
29436 
29437         // drawing
29438         stream.addProperty("drawing:elevation", getElevation());
29439         stream.addProperty("drawing:translationX", getTranslationX());
29440         stream.addProperty("drawing:translationY", getTranslationY());
29441         stream.addProperty("drawing:translationZ", getTranslationZ());
29442         stream.addProperty("drawing:rotation", getRotation());
29443         stream.addProperty("drawing:rotationX", getRotationX());
29444         stream.addProperty("drawing:rotationY", getRotationY());
29445         stream.addProperty("drawing:scaleX", getScaleX());
29446         stream.addProperty("drawing:scaleY", getScaleY());
29447         stream.addProperty("drawing:pivotX", getPivotX());
29448         stream.addProperty("drawing:pivotY", getPivotY());
29449         stream.addProperty("drawing:clipBounds",
29450                 mClipBounds == null ? null : mClipBounds.toString());
29451         stream.addProperty("drawing:opaque", isOpaque());
29452         stream.addProperty("drawing:alpha", getAlpha());
29453         stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
29454         stream.addProperty("drawing:shadow", hasShadow());
29455         stream.addProperty("drawing:solidColor", getSolidColor());
29456         stream.addProperty("drawing:layerType", mLayerType);
29457         stream.addProperty("drawing:willNotDraw", willNotDraw());
29458         stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
29459         stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
29460         stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
29461         stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
29462         stream.addProperty("drawing:outlineAmbientShadowColor", getOutlineAmbientShadowColor());
29463         stream.addProperty("drawing:outlineSpotShadowColor", getOutlineSpotShadowColor());
29464 
29465         // focus
29466         stream.addProperty("focus:hasFocus", hasFocus());
29467         stream.addProperty("focus:isFocused", isFocused());
29468         stream.addProperty("focus:focusable", getFocusable());
29469         stream.addProperty("focus:isFocusable", isFocusable());
29470         stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
29471 
29472         stream.addProperty("misc:clickable", isClickable());
29473         stream.addProperty("misc:pressed", isPressed());
29474         stream.addProperty("misc:selected", isSelected());
29475         stream.addProperty("misc:touchMode", isInTouchMode());
29476         stream.addProperty("misc:hovered", isHovered());
29477         stream.addProperty("misc:activated", isActivated());
29478 
29479         stream.addProperty("misc:visibility", getVisibility());
29480         stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
29481         stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
29482 
29483         stream.addProperty("misc:enabled", isEnabled());
29484         stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
29485         stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
29486 
29487         // theme attributes
29488         Resources.Theme theme = getContext().getTheme();
29489         if (theme != null) {
29490             stream.addPropertyKey("theme");
29491             theme.encode(stream);
29492         }
29493 
29494         // view attribute information
29495         int n = mAttributes != null ? mAttributes.length : 0;
29496         stream.addProperty("meta:__attrCount__", n/2);
29497         for (int i = 0; i < n; i += 2) {
29498             stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
29499         }
29500 
29501         stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
29502 
29503         // text
29504         stream.addProperty("text:textDirection", getTextDirection());
29505         stream.addProperty("text:textAlignment", getTextAlignment());
29506 
29507         // accessibility
29508         CharSequence contentDescription = getContentDescription();
29509         stream.addProperty("accessibility:contentDescription",
29510                 contentDescription == null ? "" : contentDescription.toString());
29511         stream.addProperty("accessibility:labelFor", getLabelFor());
29512         stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
29513     }
29514 
29515     /**
29516      * Determine if this view is rendered on a round wearable device and is the main view
29517      * on the screen.
29518      */
shouldDrawRoundScrollbar()29519     boolean shouldDrawRoundScrollbar() {
29520         if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
29521             return false;
29522         }
29523 
29524         final View rootView = getRootView();
29525         final WindowInsets insets = getRootWindowInsets();
29526 
29527         int height = getHeight();
29528         int width = getWidth();
29529         int displayHeight = rootView.getHeight();
29530         int displayWidth = rootView.getWidth();
29531 
29532         if (height != displayHeight || width != displayWidth) {
29533             return false;
29534         }
29535 
29536         getLocationInWindow(mAttachInfo.mTmpLocation);
29537         return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
29538                 && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
29539     }
29540 
29541     /**
29542      * Sets the tooltip text which will be displayed in a small popup next to the view.
29543      * <p>
29544      * The tooltip will be displayed:
29545      * <ul>
29546      * <li>On long click, unless it is handled otherwise (by OnLongClickListener or a context
29547      * menu). </li>
29548      * <li>On hover, after a brief delay since the pointer has stopped moving </li>
29549      * </ul>
29550      * <p>
29551      * <strong>Note:</strong> Do not override this method, as it will have no
29552      * effect on the text displayed in the tooltip.
29553      *
29554      * @param tooltipText the tooltip text, or null if no tooltip is required
29555      * @see #getTooltipText()
29556      * @attr ref android.R.styleable#View_tooltipText
29557      */
setTooltipText(@ullable CharSequence tooltipText)29558     public void setTooltipText(@Nullable CharSequence tooltipText) {
29559         if (TextUtils.isEmpty(tooltipText)) {
29560             setFlags(0, TOOLTIP);
29561             hideTooltip();
29562             mTooltipInfo = null;
29563         } else {
29564             setFlags(TOOLTIP, TOOLTIP);
29565             if (mTooltipInfo == null) {
29566                 mTooltipInfo = new TooltipInfo();
29567                 mTooltipInfo.mShowTooltipRunnable = this::showHoverTooltip;
29568                 mTooltipInfo.mHideTooltipRunnable = this::hideTooltip;
29569                 mTooltipInfo.mHoverSlop = ViewConfiguration.get(mContext).getScaledHoverSlop();
29570                 mTooltipInfo.clearAnchorPos();
29571             }
29572             mTooltipInfo.mTooltipText = tooltipText;
29573         }
29574     }
29575 
29576     /**
29577      * @hide Binary compatibility stub. To be removed when we finalize O APIs.
29578      */
29579     @UnsupportedAppUsage
setTooltip(@ullable CharSequence tooltipText)29580     public void setTooltip(@Nullable CharSequence tooltipText) {
29581         setTooltipText(tooltipText);
29582     }
29583 
29584     /**
29585      * Returns the view's tooltip text.
29586      *
29587      * <strong>Note:</strong> Do not override this method, as it will have no
29588      * effect on the text displayed in the tooltip. You must call
29589      * {@link #setTooltipText(CharSequence)} to modify the tooltip text.
29590      *
29591      * @return the tooltip text
29592      * @see #setTooltipText(CharSequence)
29593      * @attr ref android.R.styleable#View_tooltipText
29594      */
29595     @InspectableProperty
29596     @Nullable
getTooltipText()29597     public CharSequence getTooltipText() {
29598         return mTooltipInfo != null ? mTooltipInfo.mTooltipText : null;
29599     }
29600 
29601     /**
29602      * @hide Binary compatibility stub. To be removed when we finalize O APIs.
29603      */
29604     @Nullable
getTooltip()29605     public CharSequence getTooltip() {
29606         return getTooltipText();
29607     }
29608 
showTooltip(int x, int y, boolean fromLongClick)29609     private boolean showTooltip(int x, int y, boolean fromLongClick) {
29610         if (mAttachInfo == null || mTooltipInfo == null) {
29611             return false;
29612         }
29613         if (fromLongClick && (mViewFlags & ENABLED_MASK) != ENABLED) {
29614             return false;
29615         }
29616         if (TextUtils.isEmpty(mTooltipInfo.mTooltipText)) {
29617             return false;
29618         }
29619         hideTooltip();
29620         mTooltipInfo.mTooltipFromLongClick = fromLongClick;
29621         mTooltipInfo.mTooltipPopup = new TooltipPopup(getContext());
29622         final boolean fromTouch = (mPrivateFlags3 & PFLAG3_FINGER_DOWN) == PFLAG3_FINGER_DOWN;
29623         mTooltipInfo.mTooltipPopup.show(this, x, y, fromTouch, mTooltipInfo.mTooltipText);
29624         mAttachInfo.mTooltipHost = this;
29625         // The available accessibility actions have changed
29626         notifyViewAccessibilityStateChangedIfNeeded(CONTENT_CHANGE_TYPE_UNDEFINED);
29627         return true;
29628     }
29629 
29630     @UnsupportedAppUsage
hideTooltip()29631     void hideTooltip() {
29632         if (mTooltipInfo == null) {
29633             return;
29634         }
29635         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
29636         if (mTooltipInfo.mTooltipPopup == null) {
29637             return;
29638         }
29639         mTooltipInfo.mTooltipPopup.hide();
29640         mTooltipInfo.mTooltipPopup = null;
29641         mTooltipInfo.mTooltipFromLongClick = false;
29642         mTooltipInfo.clearAnchorPos();
29643         if (mAttachInfo != null) {
29644             mAttachInfo.mTooltipHost = null;
29645         }
29646         // The available accessibility actions have changed
29647         notifyViewAccessibilityStateChangedIfNeeded(CONTENT_CHANGE_TYPE_UNDEFINED);
29648     }
29649 
showLongClickTooltip(int x, int y)29650     private boolean showLongClickTooltip(int x, int y) {
29651         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
29652         removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
29653         return showTooltip(x, y, true);
29654     }
29655 
showHoverTooltip()29656     private boolean showHoverTooltip() {
29657         return showTooltip(mTooltipInfo.mAnchorX, mTooltipInfo.mAnchorY, false);
29658     }
29659 
dispatchTooltipHoverEvent(MotionEvent event)29660     boolean dispatchTooltipHoverEvent(MotionEvent event) {
29661         if (mTooltipInfo == null) {
29662             return false;
29663         }
29664         switch(event.getAction()) {
29665             case MotionEvent.ACTION_HOVER_MOVE:
29666                 if ((mViewFlags & TOOLTIP) != TOOLTIP) {
29667                     break;
29668                 }
29669                 if (!mTooltipInfo.mTooltipFromLongClick && mTooltipInfo.updateAnchorPos(event)) {
29670                     if (mTooltipInfo.mTooltipPopup == null) {
29671                         // Schedule showing the tooltip after a timeout.
29672                         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
29673                         postDelayed(mTooltipInfo.mShowTooltipRunnable,
29674                                 ViewConfiguration.getHoverTooltipShowTimeout());
29675                     }
29676 
29677                     // Hide hover-triggered tooltip after a period of inactivity.
29678                     // Match the timeout used by NativeInputManager to hide the mouse pointer
29679                     // (depends on SYSTEM_UI_FLAG_LOW_PROFILE being set).
29680                     final int timeout;
29681                     if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LOW_PROFILE)
29682                             == SYSTEM_UI_FLAG_LOW_PROFILE) {
29683                         timeout = ViewConfiguration.getHoverTooltipHideShortTimeout();
29684                     } else {
29685                         timeout = ViewConfiguration.getHoverTooltipHideTimeout();
29686                     }
29687                     removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
29688                     postDelayed(mTooltipInfo.mHideTooltipRunnable, timeout);
29689                 }
29690                 return true;
29691 
29692             case MotionEvent.ACTION_HOVER_EXIT:
29693                 mTooltipInfo.clearAnchorPos();
29694                 if (!mTooltipInfo.mTooltipFromLongClick) {
29695                     hideTooltip();
29696                 }
29697                 break;
29698         }
29699         return false;
29700     }
29701 
handleTooltipKey(KeyEvent event)29702     void handleTooltipKey(KeyEvent event) {
29703         switch (event.getAction()) {
29704             case KeyEvent.ACTION_DOWN:
29705                 if (event.getRepeatCount() == 0) {
29706                     hideTooltip();
29707                 }
29708                 break;
29709 
29710             case KeyEvent.ACTION_UP:
29711                 handleTooltipUp();
29712                 break;
29713         }
29714     }
29715 
handleTooltipUp()29716     private void handleTooltipUp() {
29717         if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
29718             return;
29719         }
29720         removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
29721         postDelayed(mTooltipInfo.mHideTooltipRunnable,
29722                 ViewConfiguration.getLongPressTooltipHideTimeout());
29723     }
29724 
getFocusableAttribute(TypedArray attributes)29725     private int getFocusableAttribute(TypedArray attributes) {
29726         TypedValue val = new TypedValue();
29727         if (attributes.getValue(com.android.internal.R.styleable.View_focusable, val)) {
29728             if (val.type == TypedValue.TYPE_INT_BOOLEAN) {
29729                 return (val.data == 0 ? NOT_FOCUSABLE : FOCUSABLE);
29730             } else {
29731                 return val.data;
29732             }
29733         } else {
29734             return FOCUSABLE_AUTO;
29735         }
29736     }
29737 
29738     /**
29739      * @return The content view of the tooltip popup currently being shown, or null if the tooltip
29740      * is not showing.
29741      * @hide
29742      */
29743     @TestApi
getTooltipView()29744     public View getTooltipView() {
29745         if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
29746             return null;
29747         }
29748         return mTooltipInfo.mTooltipPopup.getContentView();
29749     }
29750 
29751     /**
29752      * @return {@code true} if the default focus highlight is enabled, {@code false} otherwies.
29753      * @hide
29754      */
29755     @TestApi
isDefaultFocusHighlightEnabled()29756     public static boolean isDefaultFocusHighlightEnabled() {
29757         return sUseDefaultFocusHighlight;
29758     }
29759 
29760     /**
29761      * Dispatch a previously unhandled {@link KeyEvent} to this view. Unlike normal key dispatch,
29762      * this dispatches to ALL child views until it is consumed. The dispatch order is z-order
29763      * (visually on-top views first).
29764      *
29765      * @param evt the previously unhandled {@link KeyEvent}.
29766      * @return the {@link View} which consumed the event or {@code null} if not consumed.
29767      */
dispatchUnhandledKeyEvent(KeyEvent evt)29768     View dispatchUnhandledKeyEvent(KeyEvent evt) {
29769         if (onUnhandledKeyEvent(evt)) {
29770             return this;
29771         }
29772         return null;
29773     }
29774 
29775     /**
29776      * Allows this view to handle {@link KeyEvent}s which weren't handled by normal dispatch. This
29777      * occurs after the normal view hierarchy dispatch, but before the window callback. By default,
29778      * this will dispatch into all the listeners registered via
29779      * {@link #addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener)} in last-in-first-out
29780      * order (most recently added will receive events first).
29781      *
29782      * @param event An unhandled event.
29783      * @return {@code true} if the event was handled, {@code false} otherwise.
29784      * @see #addOnUnhandledKeyEventListener
29785      */
onUnhandledKeyEvent(@onNull KeyEvent event)29786     boolean onUnhandledKeyEvent(@NonNull KeyEvent event) {
29787         if (mListenerInfo != null && mListenerInfo.mUnhandledKeyListeners != null) {
29788             for (int i = mListenerInfo.mUnhandledKeyListeners.size() - 1; i >= 0; --i) {
29789                 if (mListenerInfo.mUnhandledKeyListeners.get(i).onUnhandledKeyEvent(this, event)) {
29790                     return true;
29791                 }
29792             }
29793         }
29794         return false;
29795     }
29796 
hasUnhandledKeyListener()29797     boolean hasUnhandledKeyListener() {
29798         return (mListenerInfo != null && mListenerInfo.mUnhandledKeyListeners != null
29799                 && !mListenerInfo.mUnhandledKeyListeners.isEmpty());
29800     }
29801 
29802     /**
29803      * Adds a listener which will receive unhandled {@link KeyEvent}s. This must be called on the
29804      * UI thread.
29805      *
29806      * @param listener a receiver of unhandled {@link KeyEvent}s.
29807      * @see #removeOnUnhandledKeyEventListener
29808      */
addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener)29809     public void addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener) {
29810         ArrayList<OnUnhandledKeyEventListener> listeners = getListenerInfo().mUnhandledKeyListeners;
29811         if (listeners == null) {
29812             listeners = new ArrayList<>();
29813             getListenerInfo().mUnhandledKeyListeners = listeners;
29814         }
29815         listeners.add(listener);
29816         if (listeners.size() == 1 && mParent instanceof ViewGroup) {
29817             ((ViewGroup) mParent).incrementChildUnhandledKeyListeners();
29818         }
29819     }
29820 
29821     /**
29822      * Removes a listener which will receive unhandled {@link KeyEvent}s. This must be called on the
29823      * UI thread.
29824      *
29825      * @param listener a receiver of unhandled {@link KeyEvent}s.
29826      * @see #addOnUnhandledKeyEventListener
29827      */
removeOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener)29828     public void removeOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener) {
29829         if (mListenerInfo != null) {
29830             if (mListenerInfo.mUnhandledKeyListeners != null
29831                     && !mListenerInfo.mUnhandledKeyListeners.isEmpty()) {
29832                 mListenerInfo.mUnhandledKeyListeners.remove(listener);
29833                 if (mListenerInfo.mUnhandledKeyListeners.isEmpty()) {
29834                     mListenerInfo.mUnhandledKeyListeners = null;
29835                     if (mParent instanceof ViewGroup) {
29836                         ((ViewGroup) mParent).decrementChildUnhandledKeyListeners();
29837                     }
29838                 }
29839             }
29840         }
29841     }
29842 }
29843