• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.view;
18 
19 import static android.content.res.Resources.ID_NULL;
20 import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
21 import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED;
22 
23 import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS;
24 import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS;
25 import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP;
26 import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION;
27 
28 import static java.lang.Math.max;
29 
30 import android.animation.AnimatorInflater;
31 import android.animation.StateListAnimator;
32 import android.annotation.AttrRes;
33 import android.annotation.CallSuper;
34 import android.annotation.ColorInt;
35 import android.annotation.DrawableRes;
36 import android.annotation.FloatRange;
37 import android.annotation.IdRes;
38 import android.annotation.IntDef;
39 import android.annotation.IntRange;
40 import android.annotation.LayoutRes;
41 import android.annotation.NonNull;
42 import android.annotation.Nullable;
43 import android.annotation.Size;
44 import android.annotation.StyleRes;
45 import android.annotation.TestApi;
46 import android.annotation.UiThread;
47 import android.compat.annotation.UnsupportedAppUsage;
48 import android.content.AutofillOptions;
49 import android.content.ClipData;
50 import android.content.Context;
51 import android.content.ContextWrapper;
52 import android.content.Intent;
53 import android.content.res.ColorStateList;
54 import android.content.res.Configuration;
55 import android.content.res.Resources;
56 import android.content.res.TypedArray;
57 import android.graphics.Bitmap;
58 import android.graphics.BlendMode;
59 import android.graphics.Canvas;
60 import android.graphics.Color;
61 import android.graphics.Insets;
62 import android.graphics.Interpolator;
63 import android.graphics.LinearGradient;
64 import android.graphics.Matrix;
65 import android.graphics.Outline;
66 import android.graphics.Paint;
67 import android.graphics.PixelFormat;
68 import android.graphics.Point;
69 import android.graphics.PorterDuff;
70 import android.graphics.PorterDuffXfermode;
71 import android.graphics.RecordingCanvas;
72 import android.graphics.Rect;
73 import android.graphics.RectF;
74 import android.graphics.Region;
75 import android.graphics.RenderNode;
76 import android.graphics.Shader;
77 import android.graphics.drawable.ColorDrawable;
78 import android.graphics.drawable.Drawable;
79 import android.graphics.drawable.GradientDrawable;
80 import android.hardware.display.DisplayManagerGlobal;
81 import android.net.Uri;
82 import android.os.Build;
83 import android.os.Build.VERSION_CODES;
84 import android.os.Bundle;
85 import android.os.Handler;
86 import android.os.IBinder;
87 import android.os.Message;
88 import android.os.Parcel;
89 import android.os.Parcelable;
90 import android.os.RemoteException;
91 import android.os.SystemClock;
92 import android.os.Trace;
93 import android.sysprop.DisplayProperties;
94 import android.text.InputType;
95 import android.text.TextUtils;
96 import android.util.AttributeSet;
97 import android.util.FloatProperty;
98 import android.util.LayoutDirection;
99 import android.util.Log;
100 import android.util.LongSparseLongArray;
101 import android.util.Pair;
102 import android.util.Pools.SynchronizedPool;
103 import android.util.Property;
104 import android.util.SparseArray;
105 import android.util.SparseIntArray;
106 import android.util.StateSet;
107 import android.util.SuperNotCalledException;
108 import android.util.TypedValue;
109 import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
110 import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
111 import android.view.AccessibilityIterators.TextSegmentIterator;
112 import android.view.AccessibilityIterators.WordTextSegmentIterator;
113 import android.view.ContextMenu.ContextMenuInfo;
114 import android.view.InputDevice.InputSourceClass;
115 import android.view.Window.OnContentApplyWindowInsetsListener;
116 import android.view.WindowInsets.Type;
117 import android.view.WindowInsetsAnimation.Bounds;
118 import android.view.WindowManager.LayoutParams;
119 import android.view.accessibility.AccessibilityEvent;
120 import android.view.accessibility.AccessibilityEventSource;
121 import android.view.accessibility.AccessibilityManager;
122 import android.view.accessibility.AccessibilityNodeIdManager;
123 import android.view.accessibility.AccessibilityNodeInfo;
124 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
125 import android.view.accessibility.AccessibilityNodeProvider;
126 import android.view.accessibility.AccessibilityWindowInfo;
127 import android.view.animation.Animation;
128 import android.view.animation.AnimationUtils;
129 import android.view.animation.Transformation;
130 import android.view.autofill.AutofillId;
131 import android.view.autofill.AutofillManager;
132 import android.view.autofill.AutofillValue;
133 import android.view.contentcapture.ContentCaptureContext;
134 import android.view.contentcapture.ContentCaptureManager;
135 import android.view.contentcapture.ContentCaptureSession;
136 import android.view.inputmethod.EditorInfo;
137 import android.view.inputmethod.InputConnection;
138 import android.view.inspector.InspectableProperty;
139 import android.view.inspector.InspectableProperty.EnumEntry;
140 import android.view.inspector.InspectableProperty.FlagEntry;
141 import android.widget.Checkable;
142 import android.widget.FrameLayout;
143 import android.widget.ScrollBarDrawable;
144 
145 import com.android.internal.R;
146 import com.android.internal.util.FrameworkStatsLog;
147 import com.android.internal.view.ScrollCaptureInternal;
148 import com.android.internal.view.TooltipPopup;
149 import com.android.internal.view.menu.MenuBuilder;
150 import com.android.internal.widget.ScrollBarUtils;
151 
152 import com.google.android.collect.Lists;
153 import com.google.android.collect.Maps;
154 
155 import java.lang.annotation.Retention;
156 import java.lang.annotation.RetentionPolicy;
157 import java.lang.ref.WeakReference;
158 import java.lang.reflect.Field;
159 import java.lang.reflect.InvocationTargetException;
160 import java.lang.reflect.Method;
161 import java.lang.reflect.Modifier;
162 import java.util.ArrayList;
163 import java.util.Arrays;
164 import java.util.Calendar;
165 import java.util.Collection;
166 import java.util.Collections;
167 import java.util.HashMap;
168 import java.util.List;
169 import java.util.Locale;
170 import java.util.Map;
171 import java.util.Queue;
172 import java.util.concurrent.CopyOnWriteArrayList;
173 import java.util.concurrent.atomic.AtomicInteger;
174 import java.util.function.Predicate;
175 
176 /**
177  * <p>
178  * This class represents the basic building block for user interface components. A View
179  * occupies a rectangular area on the screen and is responsible for drawing and
180  * event handling. View is the base class for <em>widgets</em>, which are
181  * used to create interactive UI components (buttons, text fields, etc.). The
182  * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
183  * are invisible containers that hold other Views (or other ViewGroups) and define
184  * their layout properties.
185  * </p>
186  *
187  * <div class="special reference">
188  * <h3>Developer Guides</h3>
189  * <p>For information about using this class to develop your application's user interface,
190  * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
191  * </div>
192  *
193  * <a name="Using"></a>
194  * <h3>Using Views</h3>
195  * <p>
196  * All of the views in a window are arranged in a single tree. You can add views
197  * either from code or by specifying a tree of views in one or more XML layout
198  * files. There are many specialized subclasses of views that act as controls or
199  * are capable of displaying text, images, or other content.
200  * </p>
201  * <p>
202  * Once you have created a tree of views, there are typically a few types of
203  * common operations you may wish to perform:
204  * <ul>
205  * <li><strong>Set properties:</strong> for example setting the text of a
206  * {@link android.widget.TextView}. The available properties and the methods
207  * that set them will vary among the different subclasses of views. Note that
208  * properties that are known at build time can be set in the XML layout
209  * files.</li>
210  * <li><strong>Set focus:</strong> The framework will handle moving focus in
211  * response to user input. To force focus to a specific view, call
212  * {@link #requestFocus}.</li>
213  * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
214  * that will be notified when something interesting happens to the view. For
215  * example, all views will let you set a listener to be notified when the view
216  * gains or loses focus. You can register such a listener using
217  * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
218  * Other view subclasses offer more specialized listeners. For example, a Button
219  * exposes a listener to notify clients when the button is clicked.</li>
220  * <li><strong>Set visibility:</strong> You can hide or show views using
221  * {@link #setVisibility(int)}.</li>
222  * </ul>
223  * </p>
224  * <p><em>
225  * Note: The Android framework is responsible for measuring, laying out and
226  * drawing views. You should not call methods that perform these actions on
227  * views yourself unless you are actually implementing a
228  * {@link android.view.ViewGroup}.
229  * </em></p>
230  *
231  * <a name="Lifecycle"></a>
232  * <h3>Implementing a Custom View</h3>
233  *
234  * <p>
235  * To implement a custom view, you will usually begin by providing overrides for
236  * some of the standard methods that the framework calls on all views. You do
237  * not need to override all of these methods. In fact, you can start by just
238  * overriding {@link #onDraw(android.graphics.Canvas)}.
239  * <table border="2" width="85%" align="center" cellpadding="5">
240  *     <thead>
241  *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
242  *     </thead>
243  *
244  *     <tbody>
245  *     <tr>
246  *         <td rowspan="2">Creation</td>
247  *         <td>Constructors</td>
248  *         <td>There is a form of the constructor that are called when the view
249  *         is created from code and a form that is called when the view is
250  *         inflated from a layout file. The second form should parse and apply
251  *         any attributes defined in the layout file.
252  *         </td>
253  *     </tr>
254  *     <tr>
255  *         <td><code>{@link #onFinishInflate()}</code></td>
256  *         <td>Called after a view and all of its children has been inflated
257  *         from XML.</td>
258  *     </tr>
259  *
260  *     <tr>
261  *         <td rowspan="3">Layout</td>
262  *         <td><code>{@link #onMeasure(int, int)}</code></td>
263  *         <td>Called to determine the size requirements for this view and all
264  *         of its children.
265  *         </td>
266  *     </tr>
267  *     <tr>
268  *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
269  *         <td>Called when this view should assign a size and position to all
270  *         of its children.
271  *         </td>
272  *     </tr>
273  *     <tr>
274  *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
275  *         <td>Called when the size of this view has changed.
276  *         </td>
277  *     </tr>
278  *
279  *     <tr>
280  *         <td>Drawing</td>
281  *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
282  *         <td>Called when the view should render its content.
283  *         </td>
284  *     </tr>
285  *
286  *     <tr>
287  *         <td rowspan="4">Event processing</td>
288  *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
289  *         <td>Called when a new hardware key event occurs.
290  *         </td>
291  *     </tr>
292  *     <tr>
293  *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
294  *         <td>Called when a hardware key up event occurs.
295  *         </td>
296  *     </tr>
297  *     <tr>
298  *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
299  *         <td>Called when a trackball motion event occurs.
300  *         </td>
301  *     </tr>
302  *     <tr>
303  *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
304  *         <td>Called when a touch screen motion event occurs.
305  *         </td>
306  *     </tr>
307  *
308  *     <tr>
309  *         <td rowspan="2">Focus</td>
310  *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
311  *         <td>Called when the view gains or loses focus.
312  *         </td>
313  *     </tr>
314  *
315  *     <tr>
316  *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
317  *         <td>Called when the window containing the view gains or loses focus.
318  *         </td>
319  *     </tr>
320  *
321  *     <tr>
322  *         <td rowspan="3">Attaching</td>
323  *         <td><code>{@link #onAttachedToWindow()}</code></td>
324  *         <td>Called when the view is attached to a window.
325  *         </td>
326  *     </tr>
327  *
328  *     <tr>
329  *         <td><code>{@link #onDetachedFromWindow}</code></td>
330  *         <td>Called when the view is detached from its window.
331  *         </td>
332  *     </tr>
333  *
334  *     <tr>
335  *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
336  *         <td>Called when the visibility of the window containing the view
337  *         has changed.
338  *         </td>
339  *     </tr>
340  *     </tbody>
341  *
342  * </table>
343  * </p>
344  *
345  * <a name="IDs"></a>
346  * <h3>IDs</h3>
347  * Views may have an integer id associated with them. These ids are typically
348  * assigned in the layout XML files, and are used to find specific views within
349  * the view tree. A common pattern is to:
350  * <ul>
351  * <li>Define a Button in the layout file and assign it a unique ID.
352  * <pre>
353  * &lt;Button
354  *     android:id="@+id/my_button"
355  *     android:layout_width="wrap_content"
356  *     android:layout_height="wrap_content"
357  *     android:text="@string/my_button_text"/&gt;
358  * </pre></li>
359  * <li>From the onCreate method of an Activity, find the Button
360  * <pre class="prettyprint">
361  *      Button myButton = findViewById(R.id.my_button);
362  * </pre></li>
363  * </ul>
364  * <p>
365  * View IDs need not be unique throughout the tree, but it is good practice to
366  * ensure that they are at least unique within the part of the tree you are
367  * searching.
368  * </p>
369  *
370  * <a name="Position"></a>
371  * <h3>Position</h3>
372  * <p>
373  * The geometry of a view is that of a rectangle. A view has a location,
374  * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
375  * two dimensions, expressed as a width and a height. The unit for location
376  * and dimensions is the pixel.
377  * </p>
378  *
379  * <p>
380  * It is possible to retrieve the location of a view by invoking the methods
381  * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
382  * coordinate of the rectangle representing the view. The latter returns the
383  * top, or Y, coordinate of the rectangle representing the view. These methods
384  * both return the location of the view relative to its parent. For instance,
385  * when getLeft() returns 20, that means the view is located 20 pixels to the
386  * right of the left edge of its direct parent.
387  * </p>
388  *
389  * <p>
390  * In addition, several convenience methods are offered to avoid unnecessary
391  * computations, namely {@link #getRight()} and {@link #getBottom()}.
392  * These methods return the coordinates of the right and bottom edges of the
393  * rectangle representing the view. For instance, calling {@link #getRight()}
394  * is similar to the following computation: <code>getLeft() + getWidth()</code>
395  * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
396  * </p>
397  *
398  * <a name="SizePaddingMargins"></a>
399  * <h3>Size, padding and margins</h3>
400  * <p>
401  * The size of a view is expressed with a width and a height. A view actually
402  * possess two pairs of width and height values.
403  * </p>
404  *
405  * <p>
406  * The first pair is known as <em>measured width</em> and
407  * <em>measured height</em>. These dimensions define how big a view wants to be
408  * within its parent (see <a href="#Layout">Layout</a> for more details.) The
409  * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
410  * and {@link #getMeasuredHeight()}.
411  * </p>
412  *
413  * <p>
414  * The second pair is simply known as <em>width</em> and <em>height</em>, or
415  * sometimes <em>drawing width</em> and <em>drawing height</em>. These
416  * dimensions define the actual size of the view on screen, at drawing time and
417  * after layout. These values may, but do not have to, be different from the
418  * measured width and height. The width and height can be obtained by calling
419  * {@link #getWidth()} and {@link #getHeight()}.
420  * </p>
421  *
422  * <p>
423  * To measure its dimensions, a view takes into account its padding. The padding
424  * is expressed in pixels for the left, top, right and bottom parts of the view.
425  * Padding can be used to offset the content of the view by a specific amount of
426  * pixels. For instance, a left padding of 2 will push the view's content by
427  * 2 pixels to the right of the left edge. Padding can be set using the
428  * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
429  * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
430  * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
431  * {@link #getPaddingEnd()}.
432  * </p>
433  *
434  * <p>
435  * Even though a view can define a padding, it does not provide any support for
436  * margins. However, view groups provide such a support. Refer to
437  * {@link android.view.ViewGroup} and
438  * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
439  * </p>
440  *
441  * <a name="Layout"></a>
442  * <h3>Layout</h3>
443  * <p>
444  * Layout is a two pass process: a measure pass and a layout pass. The measuring
445  * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
446  * of the view tree. Each view pushes dimension specifications down the tree
447  * during the recursion. At the end of the measure pass, every view has stored
448  * its measurements. The second pass happens in
449  * {@link #layout(int,int,int,int)} and is also top-down. During
450  * this pass each parent is responsible for positioning all of its children
451  * using the sizes computed in the measure pass.
452  * </p>
453  *
454  * <p>
455  * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
456  * {@link #getMeasuredHeight()} values must be set, along with those for all of
457  * that view's descendants. A view's measured width and measured height values
458  * must respect the constraints imposed by the view's parents. This guarantees
459  * that at the end of the measure pass, all parents accept all of their
460  * children's measurements. A parent view may call measure() more than once on
461  * its children. For example, the parent may measure each child once with
462  * unspecified dimensions to find out how big they want to be, then call
463  * measure() on them again with actual numbers if the sum of all the children's
464  * unconstrained sizes is too big or too small.
465  * </p>
466  *
467  * <p>
468  * The measure pass uses two classes to communicate dimensions. The
469  * {@link MeasureSpec} class is used by views to tell their parents how they
470  * want to be measured and positioned. The base LayoutParams class just
471  * describes how big the view wants to be for both width and height. For each
472  * dimension, it can specify one of:
473  * <ul>
474  * <li> an exact number
475  * <li>MATCH_PARENT, which means the view wants to be as big as its parent
476  * (minus padding)
477  * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
478  * enclose its content (plus padding).
479  * </ul>
480  * There are subclasses of LayoutParams for different subclasses of ViewGroup.
481  * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
482  * an X and Y value.
483  * </p>
484  *
485  * <p>
486  * MeasureSpecs are used to push requirements down the tree from parent to
487  * child. A MeasureSpec can be in one of three modes:
488  * <ul>
489  * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
490  * of a child view. For example, a LinearLayout may call measure() on its child
491  * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
492  * tall the child view wants to be given a width of 240 pixels.
493  * <li>EXACTLY: This is used by the parent to impose an exact size on the
494  * child. The child must use this size, and guarantee that all of its
495  * descendants will fit within this size.
496  * <li>AT_MOST: This is used by the parent to impose a maximum size on the
497  * child. The child must guarantee that it and all of its descendants will fit
498  * within this size.
499  * </ul>
500  * </p>
501  *
502  * <p>
503  * To initiate a layout, call {@link #requestLayout}. This method is typically
504  * called by a view on itself when it believes that it can no longer fit within
505  * its current bounds.
506  * </p>
507  *
508  * <a name="Drawing"></a>
509  * <h3>Drawing</h3>
510  * <p>
511  * Drawing is handled by walking the tree and recording the drawing commands of
512  * any View that needs to update. After this, the drawing commands of the
513  * entire tree are issued to screen, clipped to the newly damaged area.
514  * </p>
515  *
516  * <p>
517  * The tree is largely recorded and drawn in order, with parents drawn before
518  * (i.e., behind) their children, with siblings drawn in the order they appear
519  * in the tree. If you set a background drawable for a View, then the View will
520  * draw it before calling back to its <code>onDraw()</code> method. The child
521  * drawing order can be overridden with
522  * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
523  * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
524  * </p>
525  *
526  * <p>
527  * To force a view to draw, call {@link #invalidate()}.
528  * </p>
529  *
530  * <a name="EventHandlingThreading"></a>
531  * <h3>Event Handling and Threading</h3>
532  * <p>
533  * The basic cycle of a view is as follows:
534  * <ol>
535  * <li>An event comes in and is dispatched to the appropriate view. The view
536  * handles the event and notifies any listeners.</li>
537  * <li>If in the course of processing the event, the view's bounds may need
538  * to be changed, the view will call {@link #requestLayout()}.</li>
539  * <li>Similarly, if in the course of processing the event the view's appearance
540  * may need to be changed, the view will call {@link #invalidate()}.</li>
541  * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
542  * the framework will take care of measuring, laying out, and drawing the tree
543  * as appropriate.</li>
544  * </ol>
545  * </p>
546  *
547  * <p><em>Note: The entire view tree is single threaded. You must always be on
548  * the UI thread when calling any method on any view.</em>
549  * If you are doing work on other threads and want to update the state of a view
550  * from that thread, you should use a {@link Handler}.
551  * </p>
552  *
553  * <a name="FocusHandling"></a>
554  * <h3>Focus Handling</h3>
555  * <p>
556  * The framework will handle routine focus movement in response to user input.
557  * This includes changing the focus as views are removed or hidden, or as new
558  * views become available. Views indicate their willingness to take focus
559  * through the {@link #isFocusable} method. To change whether a view can take
560  * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
561  * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
562  * and can change this via {@link #setFocusableInTouchMode(boolean)}.
563  * </p>
564  * <p>
565  * Focus movement is based on an algorithm which finds the nearest neighbor in a
566  * given direction. In rare cases, the default algorithm may not match the
567  * intended behavior of the developer. In these situations, you can provide
568  * explicit overrides by using these XML attributes in the layout file:
569  * <pre>
570  * nextFocusDown
571  * nextFocusLeft
572  * nextFocusRight
573  * nextFocusUp
574  * </pre>
575  * </p>
576  *
577  *
578  * <p>
579  * To get a particular view to take focus, call {@link #requestFocus()}.
580  * </p>
581  *
582  * <a name="TouchMode"></a>
583  * <h3>Touch Mode</h3>
584  * <p>
585  * When a user is navigating a user interface via directional keys such as a D-pad, it is
586  * necessary to give focus to actionable items such as buttons so the user can see
587  * what will take input.  If the device has touch capabilities, however, and the user
588  * begins interacting with the interface by touching it, it is no longer necessary to
589  * always highlight, or give focus to, a particular view.  This motivates a mode
590  * for interaction named 'touch mode'.
591  * </p>
592  * <p>
593  * For a touch capable device, once the user touches the screen, the device
594  * will enter touch mode.  From this point onward, only views for which
595  * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
596  * Other views that are touchable, like buttons, will not take focus when touched; they will
597  * only fire the on click listeners.
598  * </p>
599  * <p>
600  * Any time a user hits a directional key, such as a D-pad direction, the view device will
601  * exit touch mode, and find a view to take focus, so that the user may resume interacting
602  * with the user interface without touching the screen again.
603  * </p>
604  * <p>
605  * The touch mode state is maintained across {@link android.app.Activity}s.  Call
606  * {@link #isInTouchMode} to see whether the device is currently in touch mode.
607  * </p>
608  *
609  * <a name="Scrolling"></a>
610  * <h3>Scrolling</h3>
611  * <p>
612  * The framework provides basic support for views that wish to internally
613  * scroll their content. This includes keeping track of the X and Y scroll
614  * offset as well as mechanisms for drawing scrollbars. See
615  * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
616  * {@link #awakenScrollBars()} for more details.
617  * </p>
618  *
619  * <a name="Tags"></a>
620  * <h3>Tags</h3>
621  * <p>
622  * Unlike IDs, tags are not used to identify views. Tags are essentially an
623  * extra piece of information that can be associated with a view. They are most
624  * often used as a convenience to store data related to views in the views
625  * themselves rather than by putting them in a separate structure.
626  * </p>
627  * <p>
628  * Tags may be specified with character sequence values in layout XML as either
629  * a single tag using the {@link android.R.styleable#View_tag android:tag}
630  * attribute or multiple tags using the {@code <tag>} child element:
631  * <pre>
632  *     &lt;View ...
633  *           android:tag="@string/mytag_value" /&gt;
634  *     &lt;View ...&gt;
635  *         &lt;tag android:id="@+id/mytag"
636  *              android:value="@string/mytag_value" /&gt;
637  *     &lt;/View>
638  * </pre>
639  * </p>
640  * <p>
641  * Tags may also be specified with arbitrary objects from code using
642  * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
643  * </p>
644  *
645  * <a name="Themes"></a>
646  * <h3>Themes</h3>
647  * <p>
648  * By default, Views are created using the theme of the Context object supplied
649  * to their constructor; however, a different theme may be specified by using
650  * the {@link android.R.styleable#View_theme android:theme} attribute in layout
651  * XML or by passing a {@link ContextThemeWrapper} to the constructor from
652  * code.
653  * </p>
654  * <p>
655  * When the {@link android.R.styleable#View_theme android:theme} attribute is
656  * used in XML, the specified theme is applied on top of the inflation
657  * context's theme (see {@link LayoutInflater}) and used for the view itself as
658  * well as any child elements.
659  * </p>
660  * <p>
661  * In the following example, both views will be created using the Material dark
662  * color scheme; however, because an overlay theme is used which only defines a
663  * subset of attributes, the value of
664  * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
665  * the inflation context's theme (e.g. the Activity theme) will be preserved.
666  * <pre>
667  *     &lt;LinearLayout
668  *             ...
669  *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
670  *         &lt;View ...&gt;
671  *     &lt;/LinearLayout&gt;
672  * </pre>
673  * </p>
674  *
675  * <a name="Properties"></a>
676  * <h3>Properties</h3>
677  * <p>
678  * The View class exposes an {@link #ALPHA} property, as well as several transform-related
679  * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
680  * available both in the {@link Property} form as well as in similarly-named setter/getter
681  * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
682  * be used to set persistent state associated with these rendering-related properties on the view.
683  * The properties and methods can also be used in conjunction with
684  * {@link android.animation.Animator Animator}-based animations, described more in the
685  * <a href="#Animation">Animation</a> section.
686  * </p>
687  *
688  * <a name="Animation"></a>
689  * <h3>Animation</h3>
690  * <p>
691  * Starting with Android 3.0, the preferred way of animating views is to use the
692  * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
693  * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
694  * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
695  * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
696  * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
697  * makes animating these View properties particularly easy and efficient.
698  * </p>
699  * <p>
700  * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
701  * You can attach an {@link Animation} object to a view using
702  * {@link #setAnimation(Animation)} or
703  * {@link #startAnimation(Animation)}. The animation can alter the scale,
704  * rotation, translation and alpha of a view over time. If the animation is
705  * attached to a view that has children, the animation will affect the entire
706  * subtree rooted by that node. When an animation is started, the framework will
707  * take care of redrawing the appropriate views until the animation completes.
708  * </p>
709  *
710  * <a name="Security"></a>
711  * <h3>Security</h3>
712  * <p>
713  * Sometimes it is essential that an application be able to verify that an action
714  * is being performed with the full knowledge and consent of the user, such as
715  * granting a permission request, making a purchase or clicking on an advertisement.
716  * Unfortunately, a malicious application could try to spoof the user into
717  * performing these actions, unaware, by concealing the intended purpose of the view.
718  * As a remedy, the framework offers a touch filtering mechanism that can be used to
719  * improve the security of views that provide access to sensitive functionality.
720  * </p><p>
721  * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
722  * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
723  * will discard touches that are received whenever the view's window is obscured by
724  * another visible window.  As a result, the view will not receive touches whenever a
725  * toast, dialog or other window appears above the view's window.
726  * </p><p>
727  * For more fine-grained control over security, consider overriding the
728  * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
729  * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
730  * </p>
731  *
732  * @attr ref android.R.styleable#View_accessibilityHeading
733  * @attr ref android.R.styleable#View_alpha
734  * @attr ref android.R.styleable#View_background
735  * @attr ref android.R.styleable#View_clickable
736  * @attr ref android.R.styleable#View_contentDescription
737  * @attr ref android.R.styleable#View_drawingCacheQuality
738  * @attr ref android.R.styleable#View_duplicateParentState
739  * @attr ref android.R.styleable#View_id
740  * @attr ref android.R.styleable#View_requiresFadingEdge
741  * @attr ref android.R.styleable#View_fadeScrollbars
742  * @attr ref android.R.styleable#View_fadingEdgeLength
743  * @attr ref android.R.styleable#View_filterTouchesWhenObscured
744  * @attr ref android.R.styleable#View_fitsSystemWindows
745  * @attr ref android.R.styleable#View_isScrollContainer
746  * @attr ref android.R.styleable#View_focusable
747  * @attr ref android.R.styleable#View_focusableInTouchMode
748  * @attr ref android.R.styleable#View_focusedByDefault
749  * @attr ref android.R.styleable#View_hapticFeedbackEnabled
750  * @attr ref android.R.styleable#View_keepScreenOn
751  * @attr ref android.R.styleable#View_keyboardNavigationCluster
752  * @attr ref android.R.styleable#View_layerType
753  * @attr ref android.R.styleable#View_layoutDirection
754  * @attr ref android.R.styleable#View_longClickable
755  * @attr ref android.R.styleable#View_minHeight
756  * @attr ref android.R.styleable#View_minWidth
757  * @attr ref android.R.styleable#View_nextClusterForward
758  * @attr ref android.R.styleable#View_nextFocusDown
759  * @attr ref android.R.styleable#View_nextFocusLeft
760  * @attr ref android.R.styleable#View_nextFocusRight
761  * @attr ref android.R.styleable#View_nextFocusUp
762  * @attr ref android.R.styleable#View_onClick
763  * @attr ref android.R.styleable#View_outlineSpotShadowColor
764  * @attr ref android.R.styleable#View_outlineAmbientShadowColor
765  * @attr ref android.R.styleable#View_padding
766  * @attr ref android.R.styleable#View_paddingHorizontal
767  * @attr ref android.R.styleable#View_paddingVertical
768  * @attr ref android.R.styleable#View_paddingBottom
769  * @attr ref android.R.styleable#View_paddingLeft
770  * @attr ref android.R.styleable#View_paddingRight
771  * @attr ref android.R.styleable#View_paddingTop
772  * @attr ref android.R.styleable#View_paddingStart
773  * @attr ref android.R.styleable#View_paddingEnd
774  * @attr ref android.R.styleable#View_saveEnabled
775  * @attr ref android.R.styleable#View_rotation
776  * @attr ref android.R.styleable#View_rotationX
777  * @attr ref android.R.styleable#View_rotationY
778  * @attr ref android.R.styleable#View_scaleX
779  * @attr ref android.R.styleable#View_scaleY
780  * @attr ref android.R.styleable#View_scrollX
781  * @attr ref android.R.styleable#View_scrollY
782  * @attr ref android.R.styleable#View_scrollbarSize
783  * @attr ref android.R.styleable#View_scrollbarStyle
784  * @attr ref android.R.styleable#View_scrollbars
785  * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
786  * @attr ref android.R.styleable#View_scrollbarFadeDuration
787  * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
788  * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
789  * @attr ref android.R.styleable#View_scrollbarThumbVertical
790  * @attr ref android.R.styleable#View_scrollbarTrackVertical
791  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
792  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
793  * @attr ref android.R.styleable#View_stateListAnimator
794  * @attr ref android.R.styleable#View_transitionName
795  * @attr ref android.R.styleable#View_soundEffectsEnabled
796  * @attr ref android.R.styleable#View_tag
797  * @attr ref android.R.styleable#View_textAlignment
798  * @attr ref android.R.styleable#View_textDirection
799  * @attr ref android.R.styleable#View_transformPivotX
800  * @attr ref android.R.styleable#View_transformPivotY
801  * @attr ref android.R.styleable#View_translationX
802  * @attr ref android.R.styleable#View_translationY
803  * @attr ref android.R.styleable#View_translationZ
804  * @attr ref android.R.styleable#View_visibility
805  * @attr ref android.R.styleable#View_theme
806  *
807  * @see android.view.ViewGroup
808  */
809 @UiThread
810 public class View implements Drawable.Callback, KeyEvent.Callback,
811         AccessibilityEventSource {
812     @UnsupportedAppUsage
813     private static final boolean DBG = false;
814 
815     /** @hide */
816     public static boolean DEBUG_DRAW = false;
817 
818     /**
819      * The logging tag used by this class with android.util.Log.
820      */
821     protected static final String VIEW_LOG_TAG = "View";
822 
823     /**
824      * The logging tag used by this class when logging verbose, autofill-related messages.
825      */
826     // NOTE: We cannot use android.view.autofill.Helper.sVerbose because that variable is not
827     // set if a session is not started.
828     private static final String AUTOFILL_LOG_TAG = "View.Autofill";
829 
830     /**
831      * The logging tag used by this class when logging content capture-related messages.
832      */
833     private static final String CONTENT_CAPTURE_LOG_TAG = "View.ContentCapture";
834 
835     private static final boolean DEBUG_CONTENT_CAPTURE = false;
836 
837     /**
838      * When set to true, this view will save its attribute data.
839      *
840      * @hide
841      */
842     public static boolean sDebugViewAttributes = false;
843 
844     /**
845      * When set to this application package view will save its attribute data.
846      *
847      * @hide
848      */
849     public static String sDebugViewAttributesApplicationPackage;
850 
851     /**
852      * Used to mark a View that has no ID.
853      */
854     public static final int NO_ID = -1;
855 
856     /**
857      * Last ID that is given to Views that are no part of activities.
858      *
859      * {@hide}
860      */
861     public static final int LAST_APP_AUTOFILL_ID = Integer.MAX_VALUE / 2;
862 
863     /**
864      * Attribute to find the autofilled highlight
865      *
866      * @see #getAutofilledDrawable()
867      */
868     private static final int[] AUTOFILL_HIGHLIGHT_ATTR =
869             new int[]{android.R.attr.autofilledHighlight};
870 
871     /**
872      * Signals that compatibility booleans have been initialized according to
873      * target SDK versions.
874      */
875     private static boolean sCompatibilityDone = false;
876 
877     /**
878      * Use the old (broken) way of building MeasureSpecs.
879      */
880     private static boolean sUseBrokenMakeMeasureSpec = false;
881 
882     /**
883      * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
884      */
885     static boolean sUseZeroUnspecifiedMeasureSpec = false;
886 
887     /**
888      * Ignore any optimizations using the measure cache.
889      */
890     private static boolean sIgnoreMeasureCache = false;
891 
892     /**
893      * Ignore an optimization that skips unnecessary EXACTLY layout passes.
894      */
895     private static boolean sAlwaysRemeasureExactly = false;
896 
897     /**
898      * Allow setForeground/setBackground to be called (and ignored) on a textureview,
899      * without throwing
900      */
901     static boolean sTextureViewIgnoresDrawableSetters = false;
902 
903     /**
904      * Prior to N, some ViewGroups would not convert LayoutParams properly even though both extend
905      * MarginLayoutParams. For instance, converting LinearLayout.LayoutParams to
906      * RelativeLayout.LayoutParams would lose margin information. This is fixed on N but target API
907      * check is implemented for backwards compatibility.
908      *
909      * {@hide}
910      */
911     protected static boolean sPreserveMarginParamsInLayoutParamConversion;
912 
913     /**
914      * Prior to N, when drag enters into child of a view that has already received an
915      * ACTION_DRAG_ENTERED event, the parent doesn't get a ACTION_DRAG_EXITED event.
916      * ACTION_DRAG_LOCATION and ACTION_DROP were delivered to the parent of a view that returned
917      * false from its event handler for these events.
918      * Starting from N, the parent will get ACTION_DRAG_EXITED event before the child gets its
919      * ACTION_DRAG_ENTERED. ACTION_DRAG_LOCATION and ACTION_DROP are never propagated to the parent.
920      * sCascadedDragDrop is true for pre-N apps for backwards compatibility implementation.
921      */
922     static boolean sCascadedDragDrop;
923 
924     /**
925      * Prior to O, auto-focusable didn't exist and widgets such as ListView use hasFocusable
926      * to determine things like whether or not to permit item click events. We can't break
927      * apps that do this just because more things (clickable things) are now auto-focusable
928      * and they would get different results, so give old behavior to old apps.
929      */
930     static boolean sHasFocusableExcludeAutoFocusable;
931 
932     /**
933      * Prior to O, auto-focusable didn't exist and views marked as clickable weren't implicitly
934      * made focusable by default. As a result, apps could (incorrectly) change the clickable
935      * setting of views off the UI thread. Now that clickable can effect the focusable state,
936      * changing the clickable attribute off the UI thread will cause an exception (since changing
937      * the focusable state checks). In order to prevent apps from crashing, we will handle this
938      * specific case and just not notify parents on new focusables resulting from marking views
939      * clickable from outside the UI thread.
940      */
941     private static boolean sAutoFocusableOffUIThreadWontNotifyParents;
942 
943     /**
944      * Prior to P things like setScaleX() allowed passing float values that were bogus such as
945      * Float.NaN. If the app is targetting P or later then passing these values will result in an
946      * exception being thrown. If the app is targetting an earlier SDK version, then we will
947      * silently clamp these values to avoid crashes elsewhere when the rendering code hits
948      * these bogus values.
949      */
950     private static boolean sThrowOnInvalidFloatProperties;
951 
952     /**
953      * Prior to P, {@code #startDragAndDrop} accepts a builder which produces an empty drag shadow.
954      * Currently zero size SurfaceControl cannot be created thus we create a dummy 1x1 surface
955      * instead.
956      */
957     private static boolean sAcceptZeroSizeDragShadow;
958 
959     /**
960      * Prior to R, {@link #dispatchApplyWindowInsets} had an issue:
961      * <p>The modified insets changed by {@link #onApplyWindowInsets} were passed to the
962      * entire view hierarchy in prefix order, including siblings as well as siblings of parents
963      * further down the hierarchy. This violates the basic concepts of the view hierarchy, and
964      * thus, the hierarchical dispatching mechanism was hard to use for apps.
965      * <p>
966      * In order to make window inset dispatching work properly, we dispatch window insets
967      * in the view hierarchy in a proper hierarchical manner if this flag is set to {@code false}.
968      */
969     static boolean sBrokenInsetsDispatch;
970 
971     /**
972      * Prior to Q, calling
973      * {@link com.android.internal.policy.DecorView#setBackgroundDrawable(Drawable)}
974      * did not call update the window format so the opacity of the background was not correctly
975      * applied to the window. Some applications rely on this misbehavior to work properly.
976      * <p>
977      * From Q, {@link com.android.internal.policy.DecorView#setBackgroundDrawable(Drawable)} is
978      * the same as {@link com.android.internal.policy.DecorView#setWindowBackground(Drawable)}
979      * which updates the window format.
980      * @hide
981      */
982     protected static boolean sBrokenWindowBackground;
983 
984     /**
985      * Prior to R, we were always forcing a layout of the entire hierarchy when insets changed from
986      * the server. This is inefficient and not all apps use it. Instead, we want to rely on apps
987      * calling {@link #requestLayout} when they need to relayout based on an insets change.
988      */
989     static boolean sForceLayoutWhenInsetsChanged;
990 
991     /** @hide */
992     @IntDef({NOT_FOCUSABLE, FOCUSABLE, FOCUSABLE_AUTO})
993     @Retention(RetentionPolicy.SOURCE)
994     public @interface Focusable {}
995 
996     /**
997      * This view does not want keystrokes.
998      * <p>
999      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
1000      * android:focusable}.
1001      */
1002     public static final int NOT_FOCUSABLE = 0x00000000;
1003 
1004     /**
1005      * This view wants keystrokes.
1006      * <p>
1007      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
1008      * android:focusable}.
1009      */
1010     public static final int FOCUSABLE = 0x00000001;
1011 
1012     /**
1013      * This view determines focusability automatically. This is the default.
1014      * <p>
1015      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
1016      * android:focusable}.
1017      */
1018     public static final int FOCUSABLE_AUTO = 0x00000010;
1019 
1020     /**
1021      * Mask for use with setFlags indicating bits used for focus.
1022      */
1023     private static final int FOCUSABLE_MASK = 0x00000011;
1024 
1025     /**
1026      * This view will adjust its padding to fit sytem windows (e.g. status bar)
1027      */
1028     private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
1029 
1030     /** @hide */
1031     @IntDef({VISIBLE, INVISIBLE, GONE})
1032     @Retention(RetentionPolicy.SOURCE)
1033     public @interface Visibility {}
1034 
1035     /**
1036      * This view is visible.
1037      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
1038      * android:visibility}.
1039      */
1040     public static final int VISIBLE = 0x00000000;
1041 
1042     /**
1043      * This view is invisible, but it still takes up space for layout purposes.
1044      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
1045      * android:visibility}.
1046      */
1047     public static final int INVISIBLE = 0x00000004;
1048 
1049     /**
1050      * This view is invisible, and it doesn't take any space for layout
1051      * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
1052      * android:visibility}.
1053      */
1054     public static final int GONE = 0x00000008;
1055 
1056     /**
1057      * Mask for use with setFlags indicating bits used for visibility.
1058      * {@hide}
1059      */
1060     static final int VISIBILITY_MASK = 0x0000000C;
1061 
1062     private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
1063 
1064     /**
1065      * Hint indicating that this view can be autofilled with an email address.
1066      *
1067      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1068      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1069      * value should be <code>{@value #AUTOFILL_HINT_EMAIL_ADDRESS}</code>).
1070      *
1071      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1072      */
1073     public static final String AUTOFILL_HINT_EMAIL_ADDRESS = "emailAddress";
1074 
1075     /**
1076      * Hint indicating that this view can be autofilled with a user's real name.
1077      *
1078      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1079      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1080      * value should be <code>{@value #AUTOFILL_HINT_NAME}</code>).
1081      *
1082      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1083      */
1084     public static final String AUTOFILL_HINT_NAME = "name";
1085 
1086     /**
1087      * Hint indicating that this view can be autofilled with a username.
1088      *
1089      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1090      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1091      * value should be <code>{@value #AUTOFILL_HINT_USERNAME}</code>).
1092      *
1093      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1094      */
1095     public static final String AUTOFILL_HINT_USERNAME = "username";
1096 
1097     /**
1098      * Hint indicating that this view can be autofilled with a password.
1099      *
1100      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1101      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1102      * value should be <code>{@value #AUTOFILL_HINT_PASSWORD}</code>).
1103      *
1104      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1105      */
1106     public static final String AUTOFILL_HINT_PASSWORD = "password";
1107 
1108     /**
1109      * Hint indicating that this view can be autofilled with a phone number.
1110      *
1111      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1112      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1113      * value should be <code>{@value #AUTOFILL_HINT_PHONE}</code>).
1114      *
1115      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1116      */
1117     public static final String AUTOFILL_HINT_PHONE = "phone";
1118 
1119     /**
1120      * Hint indicating that this view can be autofilled with a postal address.
1121      *
1122      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1123      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1124      * value should be <code>{@value #AUTOFILL_HINT_POSTAL_ADDRESS}</code>).
1125      *
1126      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1127      */
1128     public static final String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress";
1129 
1130     /**
1131      * Hint indicating that this view can be autofilled with a postal code.
1132      *
1133      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1134      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1135      * value should be <code>{@value #AUTOFILL_HINT_POSTAL_CODE}</code>).
1136      *
1137      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1138      */
1139     public static final String AUTOFILL_HINT_POSTAL_CODE = "postalCode";
1140 
1141     /**
1142      * Hint indicating that this view can be autofilled with a credit card number.
1143      *
1144      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1145      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1146      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_NUMBER}</code>).
1147      *
1148      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1149      */
1150     public static final String AUTOFILL_HINT_CREDIT_CARD_NUMBER = "creditCardNumber";
1151 
1152     /**
1153      * Hint indicating that this view can be autofilled with a credit card security code.
1154      *
1155      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1156      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1157      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE}</code>).
1158      *
1159      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1160      */
1161     public static final String AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE = "creditCardSecurityCode";
1162 
1163     /**
1164      * Hint indicating that this view can be autofilled with a credit card expiration date.
1165      *
1166      * <p>It should be used when the credit card expiration date is represented by just one view;
1167      * if it is represented by more than one (for example, one view for the month and another view
1168      * for the year), then each of these views should use the hint specific for the unit
1169      * ({@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
1170      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH},
1171      * or {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}).
1172      *
1173      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1174      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1175      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE}</code>).
1176      *
1177      * <p>When annotating a view with this hint, it's recommended to use a date autofill value to
1178      * avoid ambiguity when the autofill service provides a value for it. To understand why a
1179      * value can be ambiguous, consider "April of 2020", which could be represented as either of
1180      * the following options:
1181      *
1182      * <ul>
1183      *   <li>{@code "04/2020"}
1184      *   <li>{@code "4/2020"}
1185      *   <li>{@code "2020/04"}
1186      *   <li>{@code "2020/4"}
1187      *   <li>{@code "April/2020"}
1188      *   <li>{@code "Apr/2020"}
1189      * </ul>
1190      *
1191      * <p>You define a date autofill value for the view by overriding the following methods:
1192      *
1193      * <ol>
1194      *   <li>{@link #getAutofillType()} to return {@link #AUTOFILL_TYPE_DATE}.
1195      *   <li>{@link #getAutofillValue()} to return a
1196      *       {@link AutofillValue#forDate(long) date autofillvalue}.
1197      *   <li>{@link #autofill(AutofillValue)} to expect a data autofillvalue.
1198      * </ol>
1199      *
1200      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1201      */
1202     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE =
1203             "creditCardExpirationDate";
1204 
1205     /**
1206      * Hint indicating that this view can be autofilled with a credit card expiration month.
1207      *
1208      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1209      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1210      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH}</code>).
1211      *
1212      * <p>When annotating a view with this hint, it's recommended to use a text autofill value
1213      * whose value is the numerical representation of the month, starting on {@code 1} to avoid
1214      * ambiguity when the autofill service provides a value for it. To understand why a
1215      * value can be ambiguous, consider "January", which could be represented as either of
1216      *
1217      * <ul>
1218      *   <li>{@code "1"}: recommended way.
1219      *   <li>{@code "0"}: if following the {@link Calendar#MONTH} convention.
1220      *   <li>{@code "January"}: full name, in English.
1221      *   <li>{@code "jan"}: abbreviated name, in English.
1222      *   <li>{@code "Janeiro"}: full name, in another language.
1223      * </ul>
1224      *
1225      * <p>Another recommended approach is to use a date autofill value - see
1226      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE} for more details.
1227      *
1228      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1229      */
1230     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH =
1231             "creditCardExpirationMonth";
1232 
1233     /**
1234      * Hint indicating that this view can be autofilled with a credit card expiration year.
1235      *
1236      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1237      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1238      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}</code>).
1239      *
1240      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1241      */
1242     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR =
1243             "creditCardExpirationYear";
1244 
1245     /**
1246      * Hint indicating that this view can be autofilled with a credit card expiration day.
1247      *
1248      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1249      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1250      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY}</code>).
1251      *
1252      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1253      */
1254     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY = "creditCardExpirationDay";
1255 
1256     /**
1257      * Hints for the autofill services that describes the content of the view.
1258      */
1259     private @Nullable String[] mAutofillHints;
1260 
1261     /**
1262      * Autofill id, lazily created on calls to {@link #getAutofillId()}.
1263      */
1264     private AutofillId mAutofillId;
1265 
1266     /** @hide */
1267     @IntDef(prefix = { "AUTOFILL_TYPE_" }, value = {
1268             AUTOFILL_TYPE_NONE,
1269             AUTOFILL_TYPE_TEXT,
1270             AUTOFILL_TYPE_TOGGLE,
1271             AUTOFILL_TYPE_LIST,
1272             AUTOFILL_TYPE_DATE
1273     })
1274     @Retention(RetentionPolicy.SOURCE)
1275     public @interface AutofillType {}
1276 
1277     /**
1278      * Autofill type for views that cannot be autofilled.
1279      *
1280      * <p>Typically used when the view is read-only; for example, a text label.
1281      *
1282      * @see #getAutofillType()
1283      */
1284     public static final int AUTOFILL_TYPE_NONE = 0;
1285 
1286     /**
1287      * Autofill type for a text field, which is filled by a {@link CharSequence}.
1288      *
1289      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1290      * {@link AutofillValue#forText(CharSequence)}, and the value passed to autofill a
1291      * {@link View} can be fetched through {@link AutofillValue#getTextValue()}.
1292      *
1293      * @see #getAutofillType()
1294      */
1295     public static final int AUTOFILL_TYPE_TEXT = 1;
1296 
1297     /**
1298      * Autofill type for a togglable field, which is filled by a {@code boolean}.
1299      *
1300      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1301      * {@link AutofillValue#forToggle(boolean)}, and the value passed to autofill a
1302      * {@link View} can be fetched through {@link AutofillValue#getToggleValue()}.
1303      *
1304      * @see #getAutofillType()
1305      */
1306     public static final int AUTOFILL_TYPE_TOGGLE = 2;
1307 
1308     /**
1309      * Autofill type for a selection list field, which is filled by an {@code int}
1310      * representing the element index inside the list (starting at {@code 0}).
1311      *
1312      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1313      * {@link AutofillValue#forList(int)}, and the value passed to autofill a
1314      * {@link View} can be fetched through {@link AutofillValue#getListValue()}.
1315      *
1316      * <p>The available options in the selection list are typically provided by
1317      * {@link android.app.assist.AssistStructure.ViewNode#getAutofillOptions()}.
1318      *
1319      * @see #getAutofillType()
1320      */
1321     public static final int AUTOFILL_TYPE_LIST = 3;
1322 
1323     /**
1324      * Autofill type for a field that contains a date, which is represented by a long representing
1325      * the number of milliseconds since the standard base time known as "the epoch", namely
1326      * January 1, 1970, 00:00:00 GMT (see {@link java.util.Date#getTime()}.
1327      *
1328      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1329      * {@link AutofillValue#forDate(long)}, and the values passed to
1330      * autofill a {@link View} can be fetched through {@link AutofillValue#getDateValue()}.
1331      *
1332      * @see #getAutofillType()
1333      */
1334     public static final int AUTOFILL_TYPE_DATE = 4;
1335 
1336     /** @hide */
1337     @IntDef(prefix = { "IMPORTANT_FOR_AUTOFILL_" }, value = {
1338             IMPORTANT_FOR_AUTOFILL_AUTO,
1339             IMPORTANT_FOR_AUTOFILL_YES,
1340             IMPORTANT_FOR_AUTOFILL_NO,
1341             IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
1342             IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
1343     })
1344     @Retention(RetentionPolicy.SOURCE)
1345     public @interface AutofillImportance {}
1346 
1347     /**
1348      * Automatically determine whether a view is important for autofill.
1349      *
1350      * @see #isImportantForAutofill()
1351      * @see #setImportantForAutofill(int)
1352      */
1353     public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0x0;
1354 
1355     /**
1356      * The view is important for autofill, and its children (if any) will be traversed.
1357      *
1358      * @see #isImportantForAutofill()
1359      * @see #setImportantForAutofill(int)
1360      */
1361     public static final int IMPORTANT_FOR_AUTOFILL_YES = 0x1;
1362 
1363     /**
1364      * The view is not important for autofill, but its children (if any) will be traversed.
1365      *
1366      * @see #isImportantForAutofill()
1367      * @see #setImportantForAutofill(int)
1368      */
1369     public static final int IMPORTANT_FOR_AUTOFILL_NO = 0x2;
1370 
1371     /**
1372      * The view is important for autofill, but 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_YES_EXCLUDE_DESCENDANTS = 0x4;
1378 
1379     /**
1380      * The view is not important for autofill, and its children (if any) will not be traversed.
1381      *
1382      * @see #isImportantForAutofill()
1383      * @see #setImportantForAutofill(int)
1384      */
1385     public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 0x8;
1386 
1387     /** @hide */
1388     @IntDef(flag = true, prefix = { "AUTOFILL_FLAG_" }, value = {
1389             AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
1390     })
1391     @Retention(RetentionPolicy.SOURCE)
1392     public @interface AutofillFlags {}
1393 
1394     /**
1395      * Flag requesting you to add views that are marked as not important for autofill
1396      * (see {@link #setImportantForAutofill(int)}) to a {@link ViewStructure}.
1397      */
1398     public static final int AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x1;
1399 
1400     /** @hide */
1401     @IntDef(prefix = { "IMPORTANT_FOR_CONTENT_CAPTURE_" }, value = {
1402             IMPORTANT_FOR_CONTENT_CAPTURE_AUTO,
1403             IMPORTANT_FOR_CONTENT_CAPTURE_YES,
1404             IMPORTANT_FOR_CONTENT_CAPTURE_NO,
1405             IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
1406             IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
1407     })
1408     @Retention(RetentionPolicy.SOURCE)
1409     public @interface ContentCaptureImportance {}
1410 
1411     /**
1412      * Automatically determine whether a view is important for content capture.
1413      *
1414      * @see #isImportantForContentCapture()
1415      * @see #setImportantForContentCapture(int)
1416      */
1417     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_AUTO = 0x0;
1418 
1419     /**
1420      * The view is important for content capture, and its children (if any) will be traversed.
1421      *
1422      * @see #isImportantForContentCapture()
1423      * @see #setImportantForContentCapture(int)
1424      */
1425     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES = 0x1;
1426 
1427     /**
1428      * The view is not important for content capture, but its children (if any) will be traversed.
1429      *
1430      * @see #isImportantForContentCapture()
1431      * @see #setImportantForContentCapture(int)
1432      */
1433     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO = 0x2;
1434 
1435     /**
1436      * The view is important for content capture, but its children (if any) will not be traversed.
1437      *
1438      * @see #isImportantForContentCapture()
1439      * @see #setImportantForContentCapture(int)
1440      */
1441     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS = 0x4;
1442 
1443     /**
1444      * The view is not important for content capture, and its children (if any) will not be
1445      * traversed.
1446      *
1447      * @see #isImportantForContentCapture()
1448      * @see #setImportantForContentCapture(int)
1449      */
1450     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS = 0x8;
1451 
1452     /** {@hide} */
1453     @IntDef(flag = true, prefix = {"SCROLL_CAPTURE_HINT_"},
1454             value = {
1455                     SCROLL_CAPTURE_HINT_AUTO,
1456                     SCROLL_CAPTURE_HINT_EXCLUDE,
1457                     SCROLL_CAPTURE_HINT_INCLUDE,
1458                     SCROLL_CAPTURE_HINT_EXCLUDE_DESCENDANTS
1459     })
1460     @Retention(RetentionPolicy.SOURCE)
1461     public @interface ScrollCaptureHint {}
1462 
1463     /**
1464      * The content of this view will be considered for scroll capture if scrolling is possible.
1465      *
1466      * @see #getScrollCaptureHint()
1467      * @see #setScrollCaptureHint(int)
1468      * @hide
1469      */
1470     public static final int SCROLL_CAPTURE_HINT_AUTO = 0;
1471 
1472     /**
1473      * Explicitly exclcude this view as a potential scroll capture target. The system will not
1474      * consider it. Mutually exclusive with {@link #SCROLL_CAPTURE_HINT_INCLUDE}, which this flag
1475      * takes precedence over.
1476      *
1477      * @see #getScrollCaptureHint()
1478      * @see #setScrollCaptureHint(int)
1479      * @hide
1480      */
1481     public static final int SCROLL_CAPTURE_HINT_EXCLUDE = 0x1;
1482 
1483     /**
1484      * Explicitly include this view as a potential scroll capture target. When locating a scroll
1485      * capture target, this view will be prioritized before others without this flag. Mutually
1486      * exclusive with {@link #SCROLL_CAPTURE_HINT_EXCLUDE}, which takes precedence.
1487      *
1488      * @see #getScrollCaptureHint()
1489      * @see #setScrollCaptureHint(int)
1490      * @hide
1491      */
1492     public static final int SCROLL_CAPTURE_HINT_INCLUDE = 0x2;
1493 
1494     /**
1495      * Explicitly exclude all children of this view as potential scroll capture targets. This view
1496      * is unaffected. Note: Excluded children are not considered, regardless of {@link
1497      * #SCROLL_CAPTURE_HINT_INCLUDE}.
1498      *
1499      * @see #getScrollCaptureHint()
1500      * @see #setScrollCaptureHint(int)
1501      * @hide
1502      */
1503     public static final int SCROLL_CAPTURE_HINT_EXCLUDE_DESCENDANTS = 0x4;
1504 
1505     /**
1506      * This view is enabled. Interpretation varies by subclass.
1507      * Use with ENABLED_MASK when calling setFlags.
1508      * {@hide}
1509      */
1510     static final int ENABLED = 0x00000000;
1511 
1512     /**
1513      * This view is disabled. Interpretation varies by subclass.
1514      * Use with ENABLED_MASK when calling setFlags.
1515      * {@hide}
1516      */
1517     static final int DISABLED = 0x00000020;
1518 
1519    /**
1520     * Mask for use with setFlags indicating bits used for indicating whether
1521     * this view is enabled
1522     * {@hide}
1523     */
1524     static final int ENABLED_MASK = 0x00000020;
1525 
1526     /**
1527      * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
1528      * called and further optimizations will be performed. It is okay to have
1529      * this flag set and a background. Use with DRAW_MASK when calling setFlags.
1530      * {@hide}
1531      */
1532     static final int WILL_NOT_DRAW = 0x00000080;
1533 
1534     /**
1535      * Mask for use with setFlags indicating bits used for indicating whether
1536      * this view is will draw
1537      * {@hide}
1538      */
1539     static final int DRAW_MASK = 0x00000080;
1540 
1541     /**
1542      * <p>This view doesn't show scrollbars.</p>
1543      * {@hide}
1544      */
1545     static final int SCROLLBARS_NONE = 0x00000000;
1546 
1547     /**
1548      * <p>This view shows horizontal scrollbars.</p>
1549      * {@hide}
1550      */
1551     static final int SCROLLBARS_HORIZONTAL = 0x00000100;
1552 
1553     /**
1554      * <p>This view shows vertical scrollbars.</p>
1555      * {@hide}
1556      */
1557     static final int SCROLLBARS_VERTICAL = 0x00000200;
1558 
1559     /**
1560      * <p>Mask for use with setFlags indicating bits used for indicating which
1561      * scrollbars are enabled.</p>
1562      * {@hide}
1563      */
1564     static final int SCROLLBARS_MASK = 0x00000300;
1565 
1566     /**
1567      * Indicates that the view should filter touches when its window is obscured.
1568      * Refer to the class comments for more information about this security feature.
1569      * {@hide}
1570      */
1571     static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
1572 
1573     /**
1574      * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
1575      * that they are optional and should be skipped if the window has
1576      * requested system UI flags that ignore those insets for layout.
1577      * <p>
1578      * This is only used for support library as of Android R. The framework now uses
1579      * {@link #PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS} such that it can skip the legacy
1580      * insets path that loses insets information.
1581      */
1582     static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
1583 
1584     /**
1585      * <p>This view doesn't show fading edges.</p>
1586      * {@hide}
1587      */
1588     static final int FADING_EDGE_NONE = 0x00000000;
1589 
1590     /**
1591      * <p>This view shows horizontal fading edges.</p>
1592      * {@hide}
1593      */
1594     static final int FADING_EDGE_HORIZONTAL = 0x00001000;
1595 
1596     /**
1597      * <p>This view shows vertical fading edges.</p>
1598      * {@hide}
1599      */
1600     static final int FADING_EDGE_VERTICAL = 0x00002000;
1601 
1602     /**
1603      * <p>Mask for use with setFlags indicating bits used for indicating which
1604      * fading edges are enabled.</p>
1605      * {@hide}
1606      */
1607     static final int FADING_EDGE_MASK = 0x00003000;
1608 
1609     /**
1610      * <p>Indicates this view can be clicked. When clickable, a View reacts
1611      * to clicks by notifying the OnClickListener.<p>
1612      * {@hide}
1613      */
1614     static final int CLICKABLE = 0x00004000;
1615 
1616     /**
1617      * <p>Indicates this view is caching its drawing into a bitmap.</p>
1618      * {@hide}
1619      */
1620     static final int DRAWING_CACHE_ENABLED = 0x00008000;
1621 
1622     /**
1623      * <p>Indicates that no icicle should be saved for this view.<p>
1624      * {@hide}
1625      */
1626     static final int SAVE_DISABLED = 0x000010000;
1627 
1628     /**
1629      * <p>Mask for use with setFlags indicating bits used for the saveEnabled
1630      * property.</p>
1631      * {@hide}
1632      */
1633     static final int SAVE_DISABLED_MASK = 0x000010000;
1634 
1635     /**
1636      * <p>Indicates that no drawing cache should ever be created for this view.<p>
1637      * {@hide}
1638      */
1639     static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
1640 
1641     /**
1642      * <p>Indicates this view can take / keep focus when int touch mode.</p>
1643      * {@hide}
1644      */
1645     static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
1646 
1647     /** @hide */
1648     @Retention(RetentionPolicy.SOURCE)
1649     @IntDef(prefix = { "DRAWING_CACHE_QUALITY_" }, value = {
1650             DRAWING_CACHE_QUALITY_LOW,
1651             DRAWING_CACHE_QUALITY_HIGH,
1652             DRAWING_CACHE_QUALITY_AUTO
1653     })
1654     public @interface DrawingCacheQuality {}
1655 
1656     /**
1657      * <p>Enables low quality mode for the drawing cache.</p>
1658      *
1659      * @deprecated The view drawing cache was largely made obsolete with the introduction of
1660      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
1661      * layers are largely unnecessary and can easily result in a net loss in performance due to the
1662      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
1663      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
1664      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
1665      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
1666      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
1667      * software-rendered usages are discouraged and have compatibility issues with hardware-only
1668      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
1669      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
1670      * reports or unit testing the {@link PixelCopy} API is recommended.
1671      */
1672     @Deprecated
1673     public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
1674 
1675     /**
1676      * <p>Enables high quality mode for the drawing cache.</p>
1677      *
1678      * @deprecated The view drawing cache was largely made obsolete with the introduction of
1679      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
1680      * layers are largely unnecessary and can easily result in a net loss in performance due to the
1681      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
1682      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
1683      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
1684      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
1685      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
1686      * software-rendered usages are discouraged and have compatibility issues with hardware-only
1687      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
1688      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
1689      * reports or unit testing the {@link PixelCopy} API is recommended.
1690      */
1691     @Deprecated
1692     public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
1693 
1694     /**
1695      * <p>Enables automatic quality mode for the drawing cache.</p>
1696      *
1697      * @deprecated The view drawing cache was largely made obsolete with the introduction of
1698      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
1699      * layers are largely unnecessary and can easily result in a net loss in performance due to the
1700      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
1701      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
1702      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
1703      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
1704      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
1705      * software-rendered usages are discouraged and have compatibility issues with hardware-only
1706      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
1707      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
1708      * reports or unit testing the {@link PixelCopy} API is recommended.
1709      */
1710     @Deprecated
1711     public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
1712 
1713     private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
1714             DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
1715     };
1716 
1717     /**
1718      * <p>Mask for use with setFlags indicating bits used for the cache
1719      * quality property.</p>
1720      * {@hide}
1721      */
1722     static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
1723 
1724     /**
1725      * <p>
1726      * Indicates this view can be long clicked. When long clickable, a View
1727      * reacts to long clicks by notifying the OnLongClickListener or showing a
1728      * context menu.
1729      * </p>
1730      * {@hide}
1731      */
1732     static final int LONG_CLICKABLE = 0x00200000;
1733 
1734     /**
1735      * <p>Indicates that this view gets its drawable states from its direct parent
1736      * and ignores its original internal states.</p>
1737      *
1738      * @hide
1739      */
1740     static final int DUPLICATE_PARENT_STATE = 0x00400000;
1741 
1742     /**
1743      * <p>
1744      * Indicates this view can be context clicked. When context clickable, a View reacts to a
1745      * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1746      * OnContextClickListener.
1747      * </p>
1748      * {@hide}
1749      */
1750     static final int CONTEXT_CLICKABLE = 0x00800000;
1751 
1752     /** @hide */
1753     @IntDef(prefix = { "SCROLLBARS_" }, value = {
1754             SCROLLBARS_INSIDE_OVERLAY,
1755             SCROLLBARS_INSIDE_INSET,
1756             SCROLLBARS_OUTSIDE_OVERLAY,
1757             SCROLLBARS_OUTSIDE_INSET
1758     })
1759     @Retention(RetentionPolicy.SOURCE)
1760     public @interface ScrollBarStyle {}
1761 
1762     /**
1763      * The scrollbar style to display the scrollbars inside the content area,
1764      * without increasing the padding. The scrollbars will be overlaid with
1765      * translucency on the view's content.
1766      */
1767     public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1768 
1769     /**
1770      * The scrollbar style to display the scrollbars inside the padded area,
1771      * increasing the padding of the view. The scrollbars will not overlap the
1772      * content area of the view.
1773      */
1774     public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1775 
1776     /**
1777      * The scrollbar style to display the scrollbars at the edge of the view,
1778      * without increasing the padding. The scrollbars will be overlaid with
1779      * translucency.
1780      */
1781     public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1782 
1783     /**
1784      * The scrollbar style to display the scrollbars at the edge of the view,
1785      * increasing the padding of the view. The scrollbars will only overlap the
1786      * background, if any.
1787      */
1788     public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1789 
1790     /**
1791      * Mask to check if the scrollbar style is overlay or inset.
1792      * {@hide}
1793      */
1794     static final int SCROLLBARS_INSET_MASK = 0x01000000;
1795 
1796     /**
1797      * Mask to check if the scrollbar style is inside or outside.
1798      * {@hide}
1799      */
1800     static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1801 
1802     /**
1803      * Mask for scrollbar style.
1804      * {@hide}
1805      */
1806     static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1807 
1808     /**
1809      * View flag indicating that the screen should remain on while the
1810      * window containing this view is visible to the user.  This effectively
1811      * takes care of automatically setting the WindowManager's
1812      * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1813      */
1814     public static final int KEEP_SCREEN_ON = 0x04000000;
1815 
1816     /**
1817      * View flag indicating whether this view should have sound effects enabled
1818      * for events such as clicking and touching.
1819      */
1820     public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1821 
1822     /**
1823      * View flag indicating whether this view should have haptic feedback
1824      * enabled for events such as long presses.
1825      */
1826     public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1827 
1828     /**
1829      * <p>Indicates that the view hierarchy should stop saving state when
1830      * it reaches this view.  If state saving is initiated immediately at
1831      * the view, it will be allowed.
1832      * {@hide}
1833      */
1834     static final int PARENT_SAVE_DISABLED = 0x20000000;
1835 
1836     /**
1837      * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1838      * {@hide}
1839      */
1840     static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1841 
1842     private static Paint sDebugPaint;
1843 
1844     /**
1845      * <p>Indicates this view can display a tooltip on hover or long press.</p>
1846      * {@hide}
1847      */
1848     static final int TOOLTIP = 0x40000000;
1849 
1850     /** @hide */
1851     @IntDef(flag = true, prefix = { "FOCUSABLES_" }, value = {
1852             FOCUSABLES_ALL,
1853             FOCUSABLES_TOUCH_MODE
1854     })
1855     @Retention(RetentionPolicy.SOURCE)
1856     public @interface FocusableMode {}
1857 
1858     /**
1859      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1860      * should add all focusable Views regardless if they are focusable in touch mode.
1861      */
1862     public static final int FOCUSABLES_ALL = 0x00000000;
1863 
1864     /**
1865      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1866      * should add only Views focusable in touch mode.
1867      */
1868     public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1869 
1870     /** @hide */
1871     @IntDef(prefix = { "FOCUS_" }, value = {
1872             FOCUS_BACKWARD,
1873             FOCUS_FORWARD,
1874             FOCUS_LEFT,
1875             FOCUS_UP,
1876             FOCUS_RIGHT,
1877             FOCUS_DOWN
1878     })
1879     @Retention(RetentionPolicy.SOURCE)
1880     public @interface FocusDirection {}
1881 
1882     /** @hide */
1883     @IntDef(prefix = { "FOCUS_" }, value = {
1884             FOCUS_LEFT,
1885             FOCUS_UP,
1886             FOCUS_RIGHT,
1887             FOCUS_DOWN
1888     })
1889     @Retention(RetentionPolicy.SOURCE)
1890     public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1891 
1892     /**
1893      * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1894      * item.
1895      */
1896     public static final int FOCUS_BACKWARD = 0x00000001;
1897 
1898     /**
1899      * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1900      * item.
1901      */
1902     public static final int FOCUS_FORWARD = 0x00000002;
1903 
1904     /**
1905      * Use with {@link #focusSearch(int)}. Move focus to the left.
1906      */
1907     public static final int FOCUS_LEFT = 0x00000011;
1908 
1909     /**
1910      * Use with {@link #focusSearch(int)}. Move focus up.
1911      */
1912     public static final int FOCUS_UP = 0x00000021;
1913 
1914     /**
1915      * Use with {@link #focusSearch(int)}. Move focus to the right.
1916      */
1917     public static final int FOCUS_RIGHT = 0x00000042;
1918 
1919     /**
1920      * Use with {@link #focusSearch(int)}. Move focus down.
1921      */
1922     public static final int FOCUS_DOWN = 0x00000082;
1923 
1924     /**
1925      * Bits of {@link #getMeasuredWidthAndState()} and
1926      * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1927      */
1928     public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1929 
1930     /**
1931      * Bits of {@link #getMeasuredWidthAndState()} and
1932      * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1933      */
1934     public static final int MEASURED_STATE_MASK = 0xff000000;
1935 
1936     /**
1937      * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1938      * for functions that combine both width and height into a single int,
1939      * such as {@link #getMeasuredState()} and the childState argument of
1940      * {@link #resolveSizeAndState(int, int, int)}.
1941      */
1942     public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1943 
1944     /**
1945      * Bit of {@link #getMeasuredWidthAndState()} and
1946      * {@link #getMeasuredWidthAndState()} that indicates the measured size
1947      * is smaller that the space the view would like to have.
1948      */
1949     public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1950 
1951     /**
1952      * Base View state sets
1953      */
1954     // Singles
1955     /**
1956      * Indicates the view has no states set. States are used with
1957      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1958      * view depending on its state.
1959      *
1960      * @see android.graphics.drawable.Drawable
1961      * @see #getDrawableState()
1962      */
1963     protected static final int[] EMPTY_STATE_SET;
1964     /**
1965      * Indicates the view is enabled. States are used with
1966      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1967      * view depending on its state.
1968      *
1969      * @see android.graphics.drawable.Drawable
1970      * @see #getDrawableState()
1971      */
1972     protected static final int[] ENABLED_STATE_SET;
1973     /**
1974      * Indicates the view is focused. States are used with
1975      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1976      * view depending on its state.
1977      *
1978      * @see android.graphics.drawable.Drawable
1979      * @see #getDrawableState()
1980      */
1981     protected static final int[] FOCUSED_STATE_SET;
1982     /**
1983      * Indicates the view is selected. States are used with
1984      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1985      * view depending on its state.
1986      *
1987      * @see android.graphics.drawable.Drawable
1988      * @see #getDrawableState()
1989      */
1990     protected static final int[] SELECTED_STATE_SET;
1991     /**
1992      * Indicates the view is pressed. States are used with
1993      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1994      * view depending on its state.
1995      *
1996      * @see android.graphics.drawable.Drawable
1997      * @see #getDrawableState()
1998      */
1999     protected static final int[] PRESSED_STATE_SET;
2000     /**
2001      * Indicates the view's window has focus. States are used with
2002      * {@link android.graphics.drawable.Drawable} to change the drawing of the
2003      * view depending on its state.
2004      *
2005      * @see android.graphics.drawable.Drawable
2006      * @see #getDrawableState()
2007      */
2008     protected static final int[] WINDOW_FOCUSED_STATE_SET;
2009     // Doubles
2010     /**
2011      * Indicates the view is enabled and has the focus.
2012      *
2013      * @see #ENABLED_STATE_SET
2014      * @see #FOCUSED_STATE_SET
2015      */
2016     protected static final int[] ENABLED_FOCUSED_STATE_SET;
2017     /**
2018      * Indicates the view is enabled and selected.
2019      *
2020      * @see #ENABLED_STATE_SET
2021      * @see #SELECTED_STATE_SET
2022      */
2023     protected static final int[] ENABLED_SELECTED_STATE_SET;
2024     /**
2025      * Indicates the view is enabled and that its window has focus.
2026      *
2027      * @see #ENABLED_STATE_SET
2028      * @see #WINDOW_FOCUSED_STATE_SET
2029      */
2030     protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
2031     /**
2032      * Indicates the view is focused and selected.
2033      *
2034      * @see #FOCUSED_STATE_SET
2035      * @see #SELECTED_STATE_SET
2036      */
2037     protected static final int[] FOCUSED_SELECTED_STATE_SET;
2038     /**
2039      * Indicates the view has the focus and that its window has the focus.
2040      *
2041      * @see #FOCUSED_STATE_SET
2042      * @see #WINDOW_FOCUSED_STATE_SET
2043      */
2044     protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
2045     /**
2046      * Indicates the view is selected and that its window has the focus.
2047      *
2048      * @see #SELECTED_STATE_SET
2049      * @see #WINDOW_FOCUSED_STATE_SET
2050      */
2051     protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
2052     // Triples
2053     /**
2054      * Indicates the view is enabled, focused and selected.
2055      *
2056      * @see #ENABLED_STATE_SET
2057      * @see #FOCUSED_STATE_SET
2058      * @see #SELECTED_STATE_SET
2059      */
2060     protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
2061     /**
2062      * Indicates the view is enabled, focused and its window has the focus.
2063      *
2064      * @see #ENABLED_STATE_SET
2065      * @see #FOCUSED_STATE_SET
2066      * @see #WINDOW_FOCUSED_STATE_SET
2067      */
2068     protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
2069     /**
2070      * Indicates the view is enabled, selected and its window has the focus.
2071      *
2072      * @see #ENABLED_STATE_SET
2073      * @see #SELECTED_STATE_SET
2074      * @see #WINDOW_FOCUSED_STATE_SET
2075      */
2076     protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2077     /**
2078      * Indicates the view is focused, selected and its window has the focus.
2079      *
2080      * @see #FOCUSED_STATE_SET
2081      * @see #SELECTED_STATE_SET
2082      * @see #WINDOW_FOCUSED_STATE_SET
2083      */
2084     protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2085     /**
2086      * Indicates the view is enabled, focused, selected and its window
2087      * has the focus.
2088      *
2089      * @see #ENABLED_STATE_SET
2090      * @see #FOCUSED_STATE_SET
2091      * @see #SELECTED_STATE_SET
2092      * @see #WINDOW_FOCUSED_STATE_SET
2093      */
2094     protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2095     /**
2096      * Indicates the view is pressed and its window has the focus.
2097      *
2098      * @see #PRESSED_STATE_SET
2099      * @see #WINDOW_FOCUSED_STATE_SET
2100      */
2101     protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
2102     /**
2103      * Indicates the view is pressed and selected.
2104      *
2105      * @see #PRESSED_STATE_SET
2106      * @see #SELECTED_STATE_SET
2107      */
2108     protected static final int[] PRESSED_SELECTED_STATE_SET;
2109     /**
2110      * Indicates the view is pressed, selected and its window has the focus.
2111      *
2112      * @see #PRESSED_STATE_SET
2113      * @see #SELECTED_STATE_SET
2114      * @see #WINDOW_FOCUSED_STATE_SET
2115      */
2116     protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2117     /**
2118      * Indicates the view is pressed and focused.
2119      *
2120      * @see #PRESSED_STATE_SET
2121      * @see #FOCUSED_STATE_SET
2122      */
2123     protected static final int[] PRESSED_FOCUSED_STATE_SET;
2124     /**
2125      * Indicates the view is pressed, focused and its window has the focus.
2126      *
2127      * @see #PRESSED_STATE_SET
2128      * @see #FOCUSED_STATE_SET
2129      * @see #WINDOW_FOCUSED_STATE_SET
2130      */
2131     protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
2132     /**
2133      * Indicates the view is pressed, focused and selected.
2134      *
2135      * @see #PRESSED_STATE_SET
2136      * @see #SELECTED_STATE_SET
2137      * @see #FOCUSED_STATE_SET
2138      */
2139     protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
2140     /**
2141      * Indicates the view is pressed, focused, selected and its window has the focus.
2142      *
2143      * @see #PRESSED_STATE_SET
2144      * @see #FOCUSED_STATE_SET
2145      * @see #SELECTED_STATE_SET
2146      * @see #WINDOW_FOCUSED_STATE_SET
2147      */
2148     protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2149     /**
2150      * Indicates the view is pressed and enabled.
2151      *
2152      * @see #PRESSED_STATE_SET
2153      * @see #ENABLED_STATE_SET
2154      */
2155     protected static final int[] PRESSED_ENABLED_STATE_SET;
2156     /**
2157      * Indicates the view is pressed, enabled and its window has the focus.
2158      *
2159      * @see #PRESSED_STATE_SET
2160      * @see #ENABLED_STATE_SET
2161      * @see #WINDOW_FOCUSED_STATE_SET
2162      */
2163     protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
2164     /**
2165      * Indicates the view is pressed, enabled and selected.
2166      *
2167      * @see #PRESSED_STATE_SET
2168      * @see #ENABLED_STATE_SET
2169      * @see #SELECTED_STATE_SET
2170      */
2171     protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
2172     /**
2173      * Indicates the view is pressed, enabled, selected and its window has the
2174      * focus.
2175      *
2176      * @see #PRESSED_STATE_SET
2177      * @see #ENABLED_STATE_SET
2178      * @see #SELECTED_STATE_SET
2179      * @see #WINDOW_FOCUSED_STATE_SET
2180      */
2181     protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2182     /**
2183      * Indicates the view is pressed, enabled and focused.
2184      *
2185      * @see #PRESSED_STATE_SET
2186      * @see #ENABLED_STATE_SET
2187      * @see #FOCUSED_STATE_SET
2188      */
2189     protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
2190     /**
2191      * Indicates the view is pressed, enabled, focused and its window has the
2192      * focus.
2193      *
2194      * @see #PRESSED_STATE_SET
2195      * @see #ENABLED_STATE_SET
2196      * @see #FOCUSED_STATE_SET
2197      * @see #WINDOW_FOCUSED_STATE_SET
2198      */
2199     protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
2200     /**
2201      * Indicates the view is pressed, enabled, focused and selected.
2202      *
2203      * @see #PRESSED_STATE_SET
2204      * @see #ENABLED_STATE_SET
2205      * @see #SELECTED_STATE_SET
2206      * @see #FOCUSED_STATE_SET
2207      */
2208     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
2209     /**
2210      * Indicates the view is pressed, enabled, focused, selected and its window
2211      * has the focus.
2212      *
2213      * @see #PRESSED_STATE_SET
2214      * @see #ENABLED_STATE_SET
2215      * @see #SELECTED_STATE_SET
2216      * @see #FOCUSED_STATE_SET
2217      * @see #WINDOW_FOCUSED_STATE_SET
2218      */
2219     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2220 
2221     static {
2222         EMPTY_STATE_SET = StateSet.get(0);
2223 
2224         WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
2225 
2226         SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
2227         SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2228                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
2229 
2230         FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
2231         FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2232                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
2233         FOCUSED_SELECTED_STATE_SET = StateSet.get(
2234                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
2235         FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2236                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2237                         | StateSet.VIEW_STATE_FOCUSED);
2238 
2239         ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
2240         ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2241                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
2242         ENABLED_SELECTED_STATE_SET = StateSet.get(
2243                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
2244         ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2245                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2246                         | StateSet.VIEW_STATE_ENABLED);
2247         ENABLED_FOCUSED_STATE_SET = StateSet.get(
2248                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
2249         ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2250                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2251                         | StateSet.VIEW_STATE_ENABLED);
2252         ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2253                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2254                         | StateSet.VIEW_STATE_ENABLED);
2255         ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2256                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2257                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
2258 
2259         PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
2260         PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2261                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
2262         PRESSED_SELECTED_STATE_SET = StateSet.get(
2263                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
2264         PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2265                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2266                         | StateSet.VIEW_STATE_PRESSED);
2267         PRESSED_FOCUSED_STATE_SET = StateSet.get(
2268                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
2269         PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2270                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2271                         | StateSet.VIEW_STATE_PRESSED);
2272         PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2273                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2274                         | StateSet.VIEW_STATE_PRESSED);
2275         PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2276                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2277                         | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
2278         PRESSED_ENABLED_STATE_SET = StateSet.get(
2279                 StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2280         PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2281                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
2282                         | StateSet.VIEW_STATE_PRESSED);
2283         PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
2284                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
2285                         | StateSet.VIEW_STATE_PRESSED);
2286         PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2287                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2288                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2289         PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
2290                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
2291                         | StateSet.VIEW_STATE_PRESSED);
2292         PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2293                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2294                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2295         PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2296                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2297                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2298         PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2299                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2300                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
2301                         | StateSet.VIEW_STATE_PRESSED);
2302     }
2303 
2304     /**
2305      * Accessibility event types that are dispatched for text population.
2306      */
2307     private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
2308             AccessibilityEvent.TYPE_VIEW_CLICKED
2309             | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
2310             | AccessibilityEvent.TYPE_VIEW_SELECTED
2311             | AccessibilityEvent.TYPE_VIEW_FOCUSED
2312             | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
2313             | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
2314             | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
2315             | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
2316             | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
2317             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
2318             | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
2319 
2320     static final int DEBUG_CORNERS_COLOR = Color.rgb(63, 127, 255);
2321 
2322     static final int DEBUG_CORNERS_SIZE_DIP = 8;
2323 
2324     /**
2325      * Temporary Rect currently for use in setBackground().  This will probably
2326      * be extended in the future to hold our own class with more than just
2327      * a Rect. :)
2328      */
2329     static final ThreadLocal<Rect> sThreadLocal = ThreadLocal.withInitial(Rect::new);
2330 
2331     /**
2332      * Map used to store views' tags.
2333      */
2334     @UnsupportedAppUsage
2335     private SparseArray<Object> mKeyedTags;
2336 
2337     /**
2338      * The next available accessibility id.
2339      */
2340     private static int sNextAccessibilityViewId;
2341 
2342     /**
2343      * The animation currently associated with this view.
2344      * @hide
2345      */
2346     protected Animation mCurrentAnimation = null;
2347 
2348     /**
2349      * Width as measured during measure pass.
2350      * {@hide}
2351      */
2352     @ViewDebug.ExportedProperty(category = "measurement")
2353     @UnsupportedAppUsage
2354     int mMeasuredWidth;
2355 
2356     /**
2357      * Height as measured during measure pass.
2358      * {@hide}
2359      */
2360     @ViewDebug.ExportedProperty(category = "measurement")
2361     @UnsupportedAppUsage
2362     int mMeasuredHeight;
2363 
2364     /**
2365      * Flag to indicate that this view was marked INVALIDATED, or had its display list
2366      * invalidated, prior to the current drawing iteration. If true, the view must re-draw
2367      * its display list. This flag, used only when hw accelerated, allows us to clear the
2368      * flag while retaining this information until it's needed (at getDisplayList() time and
2369      * in drawChild(), when we decide to draw a view's children's display lists into our own).
2370      *
2371      * {@hide}
2372      */
2373     @UnsupportedAppUsage
2374     boolean mRecreateDisplayList = false;
2375 
2376     /**
2377      * The view's identifier.
2378      * {@hide}
2379      *
2380      * @see #setId(int)
2381      * @see #getId()
2382      */
2383     @IdRes
2384     @ViewDebug.ExportedProperty(resolveId = true)
2385     int mID = NO_ID;
2386 
2387     /** The ID of this view for autofill purposes.
2388      * <ul>
2389      *     <li>== {@link #NO_ID}: ID has not been assigned yet
2390      *     <li>&le; {@link #LAST_APP_AUTOFILL_ID}: View is not part of a activity. The ID is
2391      *                                                  unique in the process. This might change
2392      *                                                  over activity lifecycle events.
2393      *     <li>&gt; {@link #LAST_APP_AUTOFILL_ID}: View is part of a activity. The ID is
2394      *                                                  unique in the activity. This stays the same
2395      *                                                  over activity lifecycle events.
2396      */
2397     private int mAutofillViewId = NO_ID;
2398 
2399     // ID for accessibility purposes. This ID must be unique for every window
2400     @UnsupportedAppUsage
2401     private int mAccessibilityViewId = NO_ID;
2402 
2403     private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
2404 
2405     /**
2406      * The view's tag.
2407      * {@hide}
2408      *
2409      * @see #setTag(Object)
2410      * @see #getTag()
2411      */
2412     @UnsupportedAppUsage
2413     protected Object mTag = null;
2414 
2415     /*
2416      * Masks for mPrivateFlags, as generated by dumpFlags():
2417      *
2418      * |-------|-------|-------|-------|
2419      *                                 1 PFLAG_WANTS_FOCUS
2420      *                                1  PFLAG_FOCUSED
2421      *                               1   PFLAG_SELECTED
2422      *                              1    PFLAG_IS_ROOT_NAMESPACE
2423      *                             1     PFLAG_HAS_BOUNDS
2424      *                            1      PFLAG_DRAWN
2425      *                           1       PFLAG_DRAW_ANIMATION
2426      *                          1        PFLAG_SKIP_DRAW
2427      *                        1          PFLAG_REQUEST_TRANSPARENT_REGIONS
2428      *                       1           PFLAG_DRAWABLE_STATE_DIRTY
2429      *                      1            PFLAG_MEASURED_DIMENSION_SET
2430      *                     1             PFLAG_FORCE_LAYOUT
2431      *                    1              PFLAG_LAYOUT_REQUIRED
2432      *                   1               PFLAG_PRESSED
2433      *                  1                PFLAG_DRAWING_CACHE_VALID
2434      *                 1                 PFLAG_ANIMATION_STARTED
2435      *                1                  PFLAG_SAVE_STATE_CALLED
2436      *               1                   PFLAG_ALPHA_SET
2437      *              1                    PFLAG_SCROLL_CONTAINER
2438      *             1                     PFLAG_SCROLL_CONTAINER_ADDED
2439      *            1                      PFLAG_DIRTY
2440      *            1                      PFLAG_DIRTY_MASK
2441      *          1                        PFLAG_OPAQUE_BACKGROUND
2442      *         1                         PFLAG_OPAQUE_SCROLLBARS
2443      *         11                        PFLAG_OPAQUE_MASK
2444      *        1                          PFLAG_PREPRESSED
2445      *       1                           PFLAG_CANCEL_NEXT_UP_EVENT
2446      *      1                            PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH
2447      *     1                             PFLAG_HOVERED
2448      *    1                              PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK
2449      *   1                               PFLAG_ACTIVATED
2450      *  1                                PFLAG_INVALIDATED
2451      * |-------|-------|-------|-------|
2452      */
2453     /** {@hide} */
2454     static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
2455     /** {@hide} */
2456     static final int PFLAG_FOCUSED                     = 0x00000002;
2457     /** {@hide} */
2458     static final int PFLAG_SELECTED                    = 0x00000004;
2459     /** {@hide} */
2460     static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
2461     /** {@hide} */
2462     static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
2463     /** {@hide} */
2464     static final int PFLAG_DRAWN                       = 0x00000020;
2465     /**
2466      * When this flag is set, this view is running an animation on behalf of its
2467      * children and should therefore not cancel invalidate requests, even if they
2468      * lie outside of this view's bounds.
2469      *
2470      * {@hide}
2471      */
2472     static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
2473     /** {@hide} */
2474     static final int PFLAG_SKIP_DRAW                   = 0x00000080;
2475     /** {@hide} */
2476     static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
2477     /** {@hide} */
2478     static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
2479     /** {@hide} */
2480     static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
2481     /** {@hide} */
2482     static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
2483     /** {@hide} */
2484     static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
2485 
2486     private static final int PFLAG_PRESSED             = 0x00004000;
2487 
2488     /** {@hide} */
2489     static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
2490     /**
2491      * Flag used to indicate that this view should be drawn once more (and only once
2492      * more) after its animation has completed.
2493      * {@hide}
2494      */
2495     static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
2496 
2497     private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
2498 
2499     /**
2500      * Indicates that the View returned true when onSetAlpha() was called and that
2501      * the alpha must be restored.
2502      * {@hide}
2503      */
2504     static final int PFLAG_ALPHA_SET                   = 0x00040000;
2505 
2506     /**
2507      * Set by {@link #setScrollContainer(boolean)}.
2508      */
2509     static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
2510 
2511     /**
2512      * Set by {@link #setScrollContainer(boolean)}.
2513      */
2514     static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
2515 
2516     /**
2517      * View flag indicating whether this view was invalidated (fully or partially.)
2518      *
2519      * @hide
2520      */
2521     static final int PFLAG_DIRTY                       = 0x00200000;
2522 
2523     /**
2524      * Mask for {@link #PFLAG_DIRTY}.
2525      *
2526      * @hide
2527      */
2528     static final int PFLAG_DIRTY_MASK                  = 0x00200000;
2529 
2530     /**
2531      * Indicates whether the background is opaque.
2532      *
2533      * @hide
2534      */
2535     static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
2536 
2537     /**
2538      * Indicates whether the scrollbars are opaque.
2539      *
2540      * @hide
2541      */
2542     static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
2543 
2544     /**
2545      * Indicates whether the view is opaque.
2546      *
2547      * @hide
2548      */
2549     static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
2550 
2551     /**
2552      * Indicates a prepressed state;
2553      * the short time between ACTION_DOWN and recognizing
2554      * a 'real' press. Prepressed is used to recognize quick taps
2555      * even when they are shorter than ViewConfiguration.getTapTimeout().
2556      *
2557      * @hide
2558      */
2559     private static final int PFLAG_PREPRESSED          = 0x02000000;
2560 
2561     /**
2562      * Indicates whether the view is temporarily detached.
2563      *
2564      * @hide
2565      */
2566     static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
2567 
2568     /**
2569      * Indicates that we should awaken scroll bars once attached
2570      *
2571      * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
2572      * during window attachment and it is no longer needed. Feel free to repurpose it.
2573      *
2574      * @hide
2575      */
2576     private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
2577 
2578     /**
2579      * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
2580      * @hide
2581      */
2582     private static final int PFLAG_HOVERED             = 0x10000000;
2583 
2584     /**
2585      * Flag set by {@link AutofillManager} if it needs to be notified when this view is clicked.
2586      */
2587     private static final int PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK = 0x20000000;
2588 
2589     /** {@hide} */
2590     static final int PFLAG_ACTIVATED                   = 0x40000000;
2591 
2592     /**
2593      * Indicates that this view was specifically invalidated, not just dirtied because some
2594      * child view was invalidated. The flag is used to determine when we need to recreate
2595      * a view's display list (as opposed to just returning a reference to its existing
2596      * display list).
2597      *
2598      * @hide
2599      */
2600     static final int PFLAG_INVALIDATED                 = 0x80000000;
2601 
2602     /* End of masks for mPrivateFlags */
2603 
2604     /*
2605      * Masks for mPrivateFlags2, as generated by dumpFlags():
2606      *
2607      * |-------|-------|-------|-------|
2608      *                                 1 PFLAG2_DRAG_CAN_ACCEPT
2609      *                                1  PFLAG2_DRAG_HOVERED
2610      *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
2611      *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
2612      *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
2613      *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
2614      *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
2615      *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
2616      *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
2617      *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
2618      *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
2619      *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
2620      *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
2621      *                         111       PFLAG2_TEXT_DIRECTION_MASK
2622      *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
2623      *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
2624      *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
2625      *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
2626      *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
2627      *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
2628      *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
2629      *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
2630      *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
2631      *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
2632      *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
2633      *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
2634      *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
2635      *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
2636      *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
2637      *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
2638      *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
2639      *     1                             PFLAG2_VIEW_QUICK_REJECTED
2640      *    1                              PFLAG2_PADDING_RESOLVED
2641      *   1                               PFLAG2_DRAWABLE_RESOLVED
2642      *  1                                PFLAG2_HAS_TRANSIENT_STATE
2643      * |-------|-------|-------|-------|
2644      */
2645 
2646     /**
2647      * Indicates that this view has reported that it can accept the current drag's content.
2648      * Cleared when the drag operation concludes.
2649      * @hide
2650      */
2651     static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
2652 
2653     /**
2654      * Indicates that this view is currently directly under the drag location in a
2655      * drag-and-drop operation involving content that it can accept.  Cleared when
2656      * the drag exits the view, or when the drag operation concludes.
2657      * @hide
2658      */
2659     static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
2660 
2661     /** @hide */
2662     @IntDef(prefix = { "LAYOUT_DIRECTION_" }, value = {
2663             LAYOUT_DIRECTION_LTR,
2664             LAYOUT_DIRECTION_RTL,
2665             LAYOUT_DIRECTION_INHERIT,
2666             LAYOUT_DIRECTION_LOCALE
2667     })
2668     @Retention(RetentionPolicy.SOURCE)
2669     // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
2670     public @interface LayoutDir {}
2671 
2672     /** @hide */
2673     @IntDef(prefix = { "LAYOUT_DIRECTION_" }, value = {
2674             LAYOUT_DIRECTION_LTR,
2675             LAYOUT_DIRECTION_RTL
2676     })
2677     @Retention(RetentionPolicy.SOURCE)
2678     public @interface ResolvedLayoutDir {}
2679 
2680     /**
2681      * A flag to indicate that the layout direction of this view has not been defined yet.
2682      * @hide
2683      */
2684     public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
2685 
2686     /**
2687      * Horizontal layout direction of this view is from Left to Right.
2688      * Use with {@link #setLayoutDirection}.
2689      */
2690     public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
2691 
2692     /**
2693      * Horizontal layout direction of this view is from Right to Left.
2694      * Use with {@link #setLayoutDirection}.
2695      */
2696     public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
2697 
2698     /**
2699      * Horizontal layout direction of this view is inherited from its parent.
2700      * Use with {@link #setLayoutDirection}.
2701      */
2702     public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
2703 
2704     /**
2705      * Horizontal layout direction of this view is from deduced from the default language
2706      * script for the locale. Use with {@link #setLayoutDirection}.
2707      */
2708     public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
2709 
2710     /**
2711      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2712      * @hide
2713      */
2714     static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
2715 
2716     /**
2717      * Mask for use with private flags indicating bits used for horizontal layout direction.
2718      * @hide
2719      */
2720     static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2721 
2722     /**
2723      * Indicates whether the view horizontal layout direction has been resolved and drawn to the
2724      * right-to-left direction.
2725      * @hide
2726      */
2727     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2728 
2729     /**
2730      * Indicates whether the view horizontal layout direction has been resolved.
2731      * @hide
2732      */
2733     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2734 
2735     /**
2736      * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
2737      * @hide
2738      */
2739     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
2740             << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2741 
2742     /*
2743      * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
2744      * flag value.
2745      * @hide
2746      */
2747     private static final int[] LAYOUT_DIRECTION_FLAGS = {
2748             LAYOUT_DIRECTION_LTR,
2749             LAYOUT_DIRECTION_RTL,
2750             LAYOUT_DIRECTION_INHERIT,
2751             LAYOUT_DIRECTION_LOCALE
2752     };
2753 
2754     /**
2755      * Default horizontal layout direction.
2756      */
2757     private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
2758 
2759     /**
2760      * Default horizontal layout direction.
2761      * @hide
2762      */
2763     static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
2764 
2765     /**
2766      * Text direction is inherited through {@link ViewGroup}
2767      */
2768     public static final int TEXT_DIRECTION_INHERIT = 0;
2769 
2770     /**
2771      * Text direction is using "first strong algorithm". The first strong directional character
2772      * determines the paragraph direction. If there is no strong directional character, the
2773      * paragraph direction is the view's resolved layout direction.
2774      */
2775     public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2776 
2777     /**
2778      * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2779      * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2780      * If there are neither, the paragraph direction is the view's resolved layout direction.
2781      */
2782     public static final int TEXT_DIRECTION_ANY_RTL = 2;
2783 
2784     /**
2785      * Text direction is forced to LTR.
2786      */
2787     public static final int TEXT_DIRECTION_LTR = 3;
2788 
2789     /**
2790      * Text direction is forced to RTL.
2791      */
2792     public static final int TEXT_DIRECTION_RTL = 4;
2793 
2794     /**
2795      * Text direction is coming from the system Locale.
2796      */
2797     public static final int TEXT_DIRECTION_LOCALE = 5;
2798 
2799     /**
2800      * Text direction is using "first strong algorithm". The first strong directional character
2801      * determines the paragraph direction. If there is no strong directional character, the
2802      * paragraph direction is LTR.
2803      */
2804     public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2805 
2806     /**
2807      * Text direction is using "first strong algorithm". The first strong directional character
2808      * determines the paragraph direction. If there is no strong directional character, the
2809      * paragraph direction is RTL.
2810      */
2811     public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2812 
2813     /**
2814      * Default text direction is inherited
2815      */
2816     private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2817 
2818     /**
2819      * Default resolved text direction
2820      * @hide
2821      */
2822     static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2823 
2824     /**
2825      * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2826      * @hide
2827      */
2828     static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2829 
2830     /**
2831      * Mask for use with private flags indicating bits used for text direction.
2832      * @hide
2833      */
2834     static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2835             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2836 
2837     /**
2838      * Array of text direction flags for mapping attribute "textDirection" to correct
2839      * flag value.
2840      * @hide
2841      */
2842     private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2843             TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2844             TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2845             TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2846             TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2847             TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2848             TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2849             TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2850             TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2851     };
2852 
2853     /**
2854      * Indicates whether the view text direction has been resolved.
2855      * @hide
2856      */
2857     static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2858             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2859 
2860     /**
2861      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2862      * @hide
2863      */
2864     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2865 
2866     /**
2867      * Mask for use with private flags indicating bits used for resolved text direction.
2868      * @hide
2869      */
2870     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2871             << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2872 
2873     /**
2874      * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2875      * @hide
2876      */
2877     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2878             TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2879 
2880     /** @hide */
2881     @IntDef(prefix = { "TEXT_ALIGNMENT_" }, value = {
2882             TEXT_ALIGNMENT_INHERIT,
2883             TEXT_ALIGNMENT_GRAVITY,
2884             TEXT_ALIGNMENT_CENTER,
2885             TEXT_ALIGNMENT_TEXT_START,
2886             TEXT_ALIGNMENT_TEXT_END,
2887             TEXT_ALIGNMENT_VIEW_START,
2888             TEXT_ALIGNMENT_VIEW_END
2889     })
2890     @Retention(RetentionPolicy.SOURCE)
2891     public @interface TextAlignment {}
2892 
2893     /**
2894      * Default text alignment. The text alignment of this View is inherited from its parent.
2895      * Use with {@link #setTextAlignment(int)}
2896      */
2897     public static final int TEXT_ALIGNMENT_INHERIT = 0;
2898 
2899     /**
2900      * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2901      * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph's text direction.
2902      *
2903      * Use with {@link #setTextAlignment(int)}
2904      */
2905     public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2906 
2907     /**
2908      * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2909      *
2910      * Use with {@link #setTextAlignment(int)}
2911      */
2912     public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2913 
2914     /**
2915      * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2916      *
2917      * Use with {@link #setTextAlignment(int)}
2918      */
2919     public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2920 
2921     /**
2922      * Center the paragraph, e.g. ALIGN_CENTER.
2923      *
2924      * Use with {@link #setTextAlignment(int)}
2925      */
2926     public static final int TEXT_ALIGNMENT_CENTER = 4;
2927 
2928     /**
2929      * Align to the start of the view, which is ALIGN_LEFT if the view's resolved
2930      * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2931      *
2932      * Use with {@link #setTextAlignment(int)}
2933      */
2934     public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2935 
2936     /**
2937      * Align to the end of the view, which is ALIGN_RIGHT if the view's resolved
2938      * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2939      *
2940      * Use with {@link #setTextAlignment(int)}
2941      */
2942     public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2943 
2944     /**
2945      * Default text alignment is inherited
2946      */
2947     private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2948 
2949     /**
2950      * Default resolved text alignment
2951      * @hide
2952      */
2953     static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2954 
2955     /**
2956       * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2957       * @hide
2958       */
2959     static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2960 
2961     /**
2962       * Mask for use with private flags indicating bits used for text alignment.
2963       * @hide
2964       */
2965     static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2966 
2967     /**
2968      * Array of text direction flags for mapping attribute "textAlignment" to correct
2969      * flag value.
2970      * @hide
2971      */
2972     private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2973             TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2974             TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2975             TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2976             TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2977             TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2978             TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2979             TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2980     };
2981 
2982     /**
2983      * Indicates whether the view text alignment has been resolved.
2984      * @hide
2985      */
2986     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2987 
2988     /**
2989      * Bit shift to get the resolved text alignment.
2990      * @hide
2991      */
2992     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2993 
2994     /**
2995      * Mask for use with private flags indicating bits used for text alignment.
2996      * @hide
2997      */
2998     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2999             << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
3000 
3001     /**
3002      * Indicates whether if the view text alignment has been resolved to gravity
3003      */
3004     private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
3005             TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
3006 
3007     // Accessiblity constants for mPrivateFlags2
3008 
3009     /**
3010      * Shift for the bits in {@link #mPrivateFlags2} related to the
3011      * "importantForAccessibility" attribute.
3012      */
3013     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
3014 
3015     /**
3016      * Automatically determine whether a view is important for accessibility.
3017      */
3018     public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
3019 
3020     /**
3021      * The view is important for accessibility.
3022      */
3023     public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
3024 
3025     /**
3026      * The view is not important for accessibility.
3027      */
3028     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
3029 
3030     /**
3031      * The view is not important for accessibility, nor are any of its
3032      * descendant views.
3033      */
3034     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
3035 
3036     /**
3037      * The default whether the view is important for accessibility.
3038      */
3039     static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
3040 
3041     /**
3042      * Mask for obtaining the bits which specify how to determine
3043      * whether a view is important for accessibility.
3044      */
3045     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
3046         | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
3047         | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
3048         << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
3049 
3050     /**
3051      * Shift for the bits in {@link #mPrivateFlags2} related to the
3052      * "accessibilityLiveRegion" attribute.
3053      */
3054     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
3055 
3056     /**
3057      * Live region mode specifying that accessibility services should not
3058      * automatically announce changes to this view. This is the default live
3059      * region mode for most views.
3060      * <p>
3061      * Use with {@link #setAccessibilityLiveRegion(int)}.
3062      */
3063     public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
3064 
3065     /**
3066      * Live region mode specifying that accessibility services should announce
3067      * changes to this view.
3068      * <p>
3069      * Use with {@link #setAccessibilityLiveRegion(int)}.
3070      */
3071     public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
3072 
3073     /**
3074      * Live region mode specifying that accessibility services should interrupt
3075      * ongoing speech to immediately announce changes to this view.
3076      * <p>
3077      * Use with {@link #setAccessibilityLiveRegion(int)}.
3078      */
3079     public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
3080 
3081     /**
3082      * The default whether the view is important for accessibility.
3083      */
3084     static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
3085 
3086     /**
3087      * Mask for obtaining the bits which specify a view's accessibility live
3088      * region mode.
3089      */
3090     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
3091             | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
3092             << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
3093 
3094     /**
3095      * Flag indicating whether a view has accessibility focus.
3096      */
3097     static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
3098 
3099     /**
3100      * Flag whether the accessibility state of the subtree rooted at this view changed.
3101      */
3102     static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
3103 
3104     /**
3105      * Flag indicating whether a view failed the quickReject() check in draw(). This condition
3106      * is used to check whether later changes to the view's transform should invalidate the
3107      * view to force the quickReject test to run again.
3108      */
3109     static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
3110 
3111     /**
3112      * Flag indicating that start/end padding has been resolved into left/right padding
3113      * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
3114      * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
3115      * during measurement. In some special cases this is required such as when an adapter-based
3116      * view measures prospective children without attaching them to a window.
3117      */
3118     static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
3119 
3120     /**
3121      * Flag indicating that the start/end drawables has been resolved into left/right ones.
3122      */
3123     static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
3124 
3125     /**
3126      * Indicates that the view is tracking some sort of transient state
3127      * that the app should not need to be aware of, but that the framework
3128      * should take special care to preserve.
3129      */
3130     static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
3131 
3132     /**
3133      * Group of bits indicating that RTL properties resolution is done.
3134      */
3135     static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
3136             PFLAG2_TEXT_DIRECTION_RESOLVED |
3137             PFLAG2_TEXT_ALIGNMENT_RESOLVED |
3138             PFLAG2_PADDING_RESOLVED |
3139             PFLAG2_DRAWABLE_RESOLVED;
3140 
3141     // There are a couple of flags left in mPrivateFlags2
3142 
3143     /* End of masks for mPrivateFlags2 */
3144 
3145     /*
3146      * Masks for mPrivateFlags3, as generated by dumpFlags():
3147      *
3148      * |-------|-------|-------|-------|
3149      *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
3150      *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
3151      *                               1   PFLAG3_IS_LAID_OUT
3152      *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
3153      *                             1     PFLAG3_CALLED_SUPER
3154      *                            1      PFLAG3_APPLYING_INSETS
3155      *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
3156      *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
3157      *                         1         PFLAG3_SCROLL_INDICATOR_TOP
3158      *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
3159      *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
3160      *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
3161      *                     1             PFLAG3_SCROLL_INDICATOR_START
3162      *                    1              PFLAG3_SCROLL_INDICATOR_END
3163      *                   1               PFLAG3_ASSIST_BLOCKED
3164      *                  1                PFLAG3_CLUSTER
3165      *                 1                 PFLAG3_IS_AUTOFILLED
3166      *                1                  PFLAG3_FINGER_DOWN
3167      *               1                   PFLAG3_FOCUSED_BY_DEFAULT
3168      *           1111                    PFLAG3_IMPORTANT_FOR_AUTOFILL
3169      *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
3170      *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
3171      *        1                          PFLAG3_TEMPORARY_DETACH
3172      *       1                           PFLAG3_NO_REVEAL_ON_FOCUS
3173      *      1                            PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT
3174      *     1                             PFLAG3_SCREEN_READER_FOCUSABLE
3175      *    1                              PFLAG3_AGGREGATED_VISIBLE
3176      *   1                               PFLAG3_AUTOFILLID_EXPLICITLY_SET
3177      *  1                                PFLAG3_ACCESSIBILITY_HEADING
3178      * |-------|-------|-------|-------|
3179      */
3180 
3181     /**
3182      * Flag indicating that view has a transform animation set on it. This is used to track whether
3183      * an animation is cleared between successive frames, in order to tell the associated
3184      * DisplayList to clear its animation matrix.
3185      */
3186     static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
3187 
3188     /**
3189      * Flag indicating that view has an alpha animation set on it. This is used to track whether an
3190      * animation is cleared between successive frames, in order to tell the associated
3191      * DisplayList to restore its alpha value.
3192      */
3193     static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
3194 
3195     /**
3196      * Flag indicating that the view has been through at least one layout since it
3197      * was last attached to a window.
3198      */
3199     static final int PFLAG3_IS_LAID_OUT = 0x4;
3200 
3201     /**
3202      * Flag indicating that a call to measure() was skipped and should be done
3203      * instead when layout() is invoked.
3204      */
3205     static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
3206 
3207     /**
3208      * Flag indicating that an overridden method correctly called down to
3209      * the superclass implementation as required by the API spec.
3210      */
3211     static final int PFLAG3_CALLED_SUPER = 0x10;
3212 
3213     /**
3214      * Flag indicating that we're in the process of applying window insets.
3215      */
3216     static final int PFLAG3_APPLYING_INSETS = 0x20;
3217 
3218     /**
3219      * Flag indicating that we're in the process of fitting system windows using the old method.
3220      */
3221     static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
3222 
3223     /**
3224      * Flag indicating that nested scrolling is enabled for this view.
3225      * The view will optionally cooperate with views up its parent chain to allow for
3226      * integrated nested scrolling along the same axis.
3227      */
3228     static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
3229 
3230     /**
3231      * Flag indicating that the bottom scroll indicator should be displayed
3232      * when this view can scroll up.
3233      */
3234     static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
3235 
3236     /**
3237      * Flag indicating that the bottom scroll indicator should be displayed
3238      * when this view can scroll down.
3239      */
3240     static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
3241 
3242     /**
3243      * Flag indicating that the left scroll indicator should be displayed
3244      * when this view can scroll left.
3245      */
3246     static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
3247 
3248     /**
3249      * Flag indicating that the right scroll indicator should be displayed
3250      * when this view can scroll right.
3251      */
3252     static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
3253 
3254     /**
3255      * Flag indicating that the start scroll indicator should be displayed
3256      * when this view can scroll in the start direction.
3257      */
3258     static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
3259 
3260     /**
3261      * Flag indicating that the end scroll indicator should be displayed
3262      * when this view can scroll in the end direction.
3263      */
3264     static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
3265 
3266     static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
3267 
3268     static final int SCROLL_INDICATORS_NONE = 0x0000;
3269 
3270     /**
3271      * Mask for use with setFlags indicating bits used for indicating which
3272      * scroll indicators are enabled.
3273      */
3274     static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
3275             | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
3276             | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
3277             | PFLAG3_SCROLL_INDICATOR_END;
3278 
3279     /**
3280      * Left-shift required to translate between public scroll indicator flags
3281      * and internal PFLAGS3 flags. When used as a right-shift, translates
3282      * PFLAGS3 flags to public flags.
3283      */
3284     static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
3285 
3286     /** @hide */
3287     @Retention(RetentionPolicy.SOURCE)
3288     @IntDef(flag = true, prefix = { "SCROLL_INDICATOR_" }, value = {
3289             SCROLL_INDICATOR_TOP,
3290             SCROLL_INDICATOR_BOTTOM,
3291             SCROLL_INDICATOR_LEFT,
3292             SCROLL_INDICATOR_RIGHT,
3293             SCROLL_INDICATOR_START,
3294             SCROLL_INDICATOR_END,
3295     })
3296     public @interface ScrollIndicators {}
3297 
3298     /**
3299      * Scroll indicator direction for the top edge of the view.
3300      *
3301      * @see #setScrollIndicators(int)
3302      * @see #setScrollIndicators(int, int)
3303      * @see #getScrollIndicators()
3304      */
3305     public static final int SCROLL_INDICATOR_TOP =
3306             PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3307 
3308     /**
3309      * Scroll indicator direction for the bottom edge of the view.
3310      *
3311      * @see #setScrollIndicators(int)
3312      * @see #setScrollIndicators(int, int)
3313      * @see #getScrollIndicators()
3314      */
3315     public static final int SCROLL_INDICATOR_BOTTOM =
3316             PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3317 
3318     /**
3319      * Scroll indicator direction for the left edge of the view.
3320      *
3321      * @see #setScrollIndicators(int)
3322      * @see #setScrollIndicators(int, int)
3323      * @see #getScrollIndicators()
3324      */
3325     public static final int SCROLL_INDICATOR_LEFT =
3326             PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3327 
3328     /**
3329      * Scroll indicator direction for the right edge of the view.
3330      *
3331      * @see #setScrollIndicators(int)
3332      * @see #setScrollIndicators(int, int)
3333      * @see #getScrollIndicators()
3334      */
3335     public static final int SCROLL_INDICATOR_RIGHT =
3336             PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3337 
3338     /**
3339      * Scroll indicator direction for the starting edge of the view.
3340      * <p>
3341      * Resolved according to the view's layout direction, see
3342      * {@link #getLayoutDirection()} for more information.
3343      *
3344      * @see #setScrollIndicators(int)
3345      * @see #setScrollIndicators(int, int)
3346      * @see #getScrollIndicators()
3347      */
3348     public static final int SCROLL_INDICATOR_START =
3349             PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3350 
3351     /**
3352      * Scroll indicator direction for the ending edge of the view.
3353      * <p>
3354      * Resolved according to the view's layout direction, see
3355      * {@link #getLayoutDirection()} for more information.
3356      *
3357      * @see #setScrollIndicators(int)
3358      * @see #setScrollIndicators(int, int)
3359      * @see #getScrollIndicators()
3360      */
3361     public static final int SCROLL_INDICATOR_END =
3362             PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3363 
3364     /**
3365      * <p>Indicates that we are allowing {@link ViewStructure} to traverse
3366      * into this view.<p>
3367      */
3368     static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
3369 
3370     /**
3371      * Flag indicating that the view is a root of a keyboard navigation cluster.
3372      *
3373      * @see #isKeyboardNavigationCluster()
3374      * @see #setKeyboardNavigationCluster(boolean)
3375      */
3376     private static final int PFLAG3_CLUSTER = 0x8000;
3377 
3378     /**
3379      * Flag indicating that the view is autofilled
3380      *
3381      * @see #isAutofilled()
3382      * @see #setAutofilled(boolean, boolean)
3383      */
3384     private static final int PFLAG3_IS_AUTOFILLED = 0x10000;
3385 
3386     /**
3387      * Indicates that the user is currently touching the screen.
3388      * Currently used for the tooltip positioning only.
3389      */
3390     private static final int PFLAG3_FINGER_DOWN = 0x20000;
3391 
3392     /**
3393      * Flag indicating that this view is the default-focus view.
3394      *
3395      * @see #isFocusedByDefault()
3396      * @see #setFocusedByDefault(boolean)
3397      */
3398     private static final int PFLAG3_FOCUSED_BY_DEFAULT = 0x40000;
3399 
3400     /**
3401      * Shift for the bits in {@link #mPrivateFlags3} related to the
3402      * "importantForAutofill" attribute.
3403      */
3404     static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT = 19;
3405 
3406     /**
3407      * Mask for obtaining the bits which specify how to determine
3408      * whether a view is important for autofill.
3409      */
3410     static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK = (IMPORTANT_FOR_AUTOFILL_AUTO
3411             | IMPORTANT_FOR_AUTOFILL_YES | IMPORTANT_FOR_AUTOFILL_NO
3412             | IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
3413             | IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS)
3414             << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
3415 
3416     /**
3417      * Whether this view has rendered elements that overlap (see {@link
3418      * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
3419      * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
3420      * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
3421      * determined by whatever {@link #hasOverlappingRendering()} returns.
3422      */
3423     private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
3424 
3425     /**
3426      * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
3427      * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
3428      */
3429     private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
3430 
3431     /**
3432      * Flag indicating that the view is temporarily detached from the parent view.
3433      *
3434      * @see #onStartTemporaryDetach()
3435      * @see #onFinishTemporaryDetach()
3436      */
3437     static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
3438 
3439     /**
3440      * Flag indicating that the view does not wish to be revealed within its parent
3441      * hierarchy when it gains focus. Expressed in the negative since the historical
3442      * default behavior is to reveal on focus; this flag suppresses that behavior.
3443      *
3444      * @see #setRevealOnFocusHint(boolean)
3445      * @see #getRevealOnFocusHint()
3446      */
3447     private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
3448 
3449     /**
3450      * Flag indicating that when layout is completed we should notify
3451      * that the view was entered for autofill purposes. To minimize
3452      * showing autofill for views not visible to the user we evaluate
3453      * user visibility which cannot be done until the view is laid out.
3454      */
3455     static final int PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT = 0x8000000;
3456 
3457     /**
3458      * Works like focusable for screen readers, but without the side effects on input focus.
3459      * @see #setScreenReaderFocusable(boolean)
3460      */
3461     private static final int PFLAG3_SCREEN_READER_FOCUSABLE = 0x10000000;
3462 
3463     /**
3464      * The last aggregated visibility. Used to detect when it truly changes.
3465      */
3466     private static final int PFLAG3_AGGREGATED_VISIBLE = 0x20000000;
3467 
3468     /**
3469      * Used to indicate that {@link #mAutofillId} was explicitly set through
3470      * {@link #setAutofillId(AutofillId)}.
3471      */
3472     private static final int PFLAG3_AUTOFILLID_EXPLICITLY_SET = 0x40000000;
3473 
3474     /**
3475      * Indicates if the View is a heading for accessibility purposes
3476      */
3477     private static final int PFLAG3_ACCESSIBILITY_HEADING = 0x80000000;
3478 
3479     /* End of masks for mPrivateFlags3 */
3480 
3481     /*
3482      * Masks for mPrivateFlags4, as generated by dumpFlags():
3483      *
3484      * |-------|-------|-------|-------|
3485      *                             1111 PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK
3486      *                            1     PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED
3487      *                           1      PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED
3488      *                          1       PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED
3489      *                         1        PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE
3490      *                         11       PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK
3491      *                        1         PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS
3492      *                       1          PFLAG4_AUTOFILL_HIDE_HIGHLIGHT
3493      *                     11           PFLAG4_SCROLL_CAPTURE_HINT_MASK
3494      * |-------|-------|-------|-------|
3495      */
3496 
3497     /**
3498      * Mask for obtaining the bits which specify how to determine
3499      * whether a view is important for autofill.
3500      *
3501      * <p>NOTE: the important for content capture values were the first flags added and are set in
3502      * the rightmost position, so we don't need to shift them
3503      */
3504     private static final int PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK =
3505             IMPORTANT_FOR_CONTENT_CAPTURE_AUTO | IMPORTANT_FOR_CONTENT_CAPTURE_YES
3506             | IMPORTANT_FOR_CONTENT_CAPTURE_NO
3507             | IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
3508             | IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS;
3509 
3510     /*
3511      * Variables used to control when the IntelligenceManager.notifyNodeAdded()/removed() methods
3512      * should be called.
3513      *
3514      * The idea is to call notifyAppeared() after the view is layout and visible, then call
3515      * notifyDisappeared() when it's gone (without known when it was removed from the parent).
3516      */
3517     private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED = 0x10;
3518     private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED = 0x20;
3519 
3520     /*
3521      * Flags used to cache the value returned by isImportantForContentCapture while the view
3522      * hierarchy is being traversed.
3523      */
3524     private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED = 0x40;
3525     private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE = 0x80;
3526 
3527     private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK =
3528             PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED
3529             | PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
3530 
3531     /**
3532      * @see #OPTIONAL_FITS_SYSTEM_WINDOWS
3533      */
3534     static final int PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS = 0x000000100;
3535 
3536     /**
3537      * Flag indicating the field should not have yellow highlight when autofilled.
3538      */
3539     private static final int PFLAG4_AUTOFILL_HIDE_HIGHLIGHT = 0x200;
3540 
3541     /**
3542      * Shift for the bits in {@link #mPrivateFlags4} related to scroll capture.
3543      */
3544     static final int PFLAG4_SCROLL_CAPTURE_HINT_SHIFT = 10;
3545 
3546     static final int PFLAG4_SCROLL_CAPTURE_HINT_MASK = (SCROLL_CAPTURE_HINT_INCLUDE
3547             | SCROLL_CAPTURE_HINT_EXCLUDE | SCROLL_CAPTURE_HINT_EXCLUDE_DESCENDANTS)
3548             << PFLAG4_SCROLL_CAPTURE_HINT_SHIFT;
3549 
3550     /* End of masks for mPrivateFlags4 */
3551 
3552     /** @hide */
3553     protected static final int VIEW_STRUCTURE_FOR_ASSIST = 0;
3554     /** @hide */
3555     protected  static final int VIEW_STRUCTURE_FOR_AUTOFILL = 1;
3556     /** @hide */
3557     protected  static final int VIEW_STRUCTURE_FOR_CONTENT_CAPTURE = 2;
3558 
3559     /** @hide */
3560     @IntDef(flag = true, prefix = { "VIEW_STRUCTURE_FOR" }, value = {
3561             VIEW_STRUCTURE_FOR_ASSIST,
3562             VIEW_STRUCTURE_FOR_AUTOFILL,
3563             VIEW_STRUCTURE_FOR_CONTENT_CAPTURE
3564     })
3565     @Retention(RetentionPolicy.SOURCE)
3566     public @interface ViewStructureType {}
3567 
3568     /**
3569      * Always allow a user to over-scroll this view, provided it is a
3570      * view that can scroll.
3571      *
3572      * @see #getOverScrollMode()
3573      * @see #setOverScrollMode(int)
3574      */
3575     public static final int OVER_SCROLL_ALWAYS = 0;
3576 
3577     /**
3578      * Allow a user to over-scroll this view only if the content is large
3579      * enough to meaningfully scroll, provided it is a view that can scroll.
3580      *
3581      * @see #getOverScrollMode()
3582      * @see #setOverScrollMode(int)
3583      */
3584     public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
3585 
3586     /**
3587      * Never allow a user to over-scroll this view.
3588      *
3589      * @see #getOverScrollMode()
3590      * @see #setOverScrollMode(int)
3591      */
3592     public static final int OVER_SCROLL_NEVER = 2;
3593 
3594     /**
3595      * Special constant for {@link #setSystemUiVisibility(int)}: View has
3596      * requested the system UI (status bar) to be visible (the default).
3597      *
3598      * @see #setSystemUiVisibility(int)
3599      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
3600      * instead.
3601      */
3602     @Deprecated
3603     public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
3604 
3605     /**
3606      * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
3607      * system UI to enter an unobtrusive "low profile" mode.
3608      *
3609      * <p>This is for use in games, book readers, video players, or any other
3610      * "immersive" application where the usual system chrome is deemed too distracting.
3611      *
3612      * <p>In low profile mode, the status bar and/or navigation icons may dim.
3613      *
3614      * @see #setSystemUiVisibility(int)
3615      * @deprecated Low profile mode is deprecated. Hide the system bars instead if the application
3616      * needs to be in a unobtrusive mode. Use {@link WindowInsetsController#hide(int)} with
3617      * {@link Type#systemBars()}.
3618      */
3619     @Deprecated
3620     public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
3621 
3622     /**
3623      * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
3624      * system navigation be temporarily hidden.
3625      *
3626      * <p>This is an even less obtrusive state than that called for by
3627      * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
3628      * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
3629      * those to disappear. This is useful (in conjunction with the
3630      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
3631      * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
3632      * window flags) for displaying content using every last pixel on the display.
3633      *
3634      * <p>There is a limitation: because navigation controls are so important, the least user
3635      * interaction will cause them to reappear immediately.  When this happens, both
3636      * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
3637      * so that both elements reappear at the same time.
3638      *
3639      * @see #setSystemUiVisibility(int)
3640      * @deprecated Use {@link WindowInsetsController#hide(int)} with {@link Type#navigationBars()}
3641      * instead.
3642      */
3643     @Deprecated
3644     public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
3645 
3646     /**
3647      * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
3648      * into the normal fullscreen mode so that its content can take over the screen
3649      * while still allowing the user to interact with the application.
3650      *
3651      * <p>This has the same visual effect as
3652      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
3653      * WindowManager.LayoutParams.FLAG_FULLSCREEN},
3654      * meaning that non-critical screen decorations (such as the status bar) will be
3655      * hidden while the user is in the View's window, focusing the experience on
3656      * that content.  Unlike the window flag, if you are using ActionBar in
3657      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3658      * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
3659      * hide the action bar.
3660      *
3661      * <p>This approach to going fullscreen is best used over the window flag when
3662      * it is a transient state -- that is, the application does this at certain
3663      * points in its user interaction where it wants to allow the user to focus
3664      * on content, but not as a continuous state.  For situations where the application
3665      * would like to simply stay full screen the entire time (such as a game that
3666      * wants to take over the screen), the
3667      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
3668      * is usually a better approach.  The state set here will be removed by the system
3669      * in various situations (such as the user moving to another application) like
3670      * the other system UI states.
3671      *
3672      * <p>When using this flag, the application should provide some easy facility
3673      * for the user to go out of it.  A common example would be in an e-book
3674      * reader, where tapping on the screen brings back whatever screen and UI
3675      * decorations that had been hidden while the user was immersed in reading
3676      * the book.
3677      *
3678      * @see #setSystemUiVisibility(int)
3679      * @deprecated Use {@link WindowInsetsController#hide(int)} with {@link Type#statusBars()}
3680      * instead.
3681      */
3682     @Deprecated
3683     public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
3684 
3685     /**
3686      * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
3687      * flags, we would like a stable view of the content insets given to
3688      * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
3689      * will always represent the worst case that the application can expect
3690      * as a continuous state.  In the stock Android UI this is the space for
3691      * the system bar, nav bar, and status bar, but not more transient elements
3692      * such as an input method.
3693      *
3694      * The stable layout your UI sees is based on the system UI modes you can
3695      * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
3696      * then you will get a stable layout for changes of the
3697      * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
3698      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
3699      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
3700      * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
3701      * with a stable layout.  (Note that you should avoid using
3702      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
3703      *
3704      * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
3705      * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
3706      * then a hidden status bar will be considered a "stable" state for purposes
3707      * here.  This allows your UI to continually hide the status bar, while still
3708      * using the system UI flags to hide the action bar while still retaining
3709      * a stable layout.  Note that changing the window fullscreen flag will never
3710      * provide a stable layout for a clean transition.
3711      *
3712      * <p>If you are using ActionBar in
3713      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3714      * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
3715      * insets it adds to those given to the application.
3716      *
3717      * @deprecated Use {@link WindowInsets#getInsetsIgnoringVisibility(int)} instead to retrieve
3718      * insets that don't change when system bars change visibility state.
3719      */
3720     @Deprecated
3721     public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
3722 
3723     /**
3724      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3725      * to be laid out as if it has requested
3726      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
3727      * allows it to avoid artifacts when switching in and out of that mode, at
3728      * the expense that some of its user interface may be covered by screen
3729      * decorations when they are shown.  You can perform layout of your inner
3730      * UI elements to account for the navigation system UI through the
3731      * {@link #fitSystemWindows(Rect)} method.
3732      *
3733      * @deprecated For floating windows, use {@link LayoutParams#setFitInsetsTypes(int)} with
3734      * {@link Type#navigationBars()}. For non-floating windows that fill the screen, call
3735      * {@link Window#setDecorFitsSystemWindows(boolean)} with {@code false}.
3736      */
3737     public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
3738 
3739     /**
3740      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3741      * to be laid out as if it has requested
3742      * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
3743      * allows it to avoid artifacts when switching in and out of that mode, at
3744      * the expense that some of its user interface may be covered by screen
3745      * decorations when they are shown.  You can perform layout of your inner
3746      * UI elements to account for non-fullscreen system UI through the
3747      * {@link #fitSystemWindows(Rect)} method.
3748      *
3749      * <p>Note: on displays that have a {@link DisplayCutout}, the window may still be placed
3750      *  differently than if {@link #SYSTEM_UI_FLAG_FULLSCREEN} was set, if the
3751      *  window's {@link WindowManager.LayoutParams#layoutInDisplayCutoutMode
3752      *  layoutInDisplayCutoutMode} is
3753      *  {@link WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
3754      *  LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT}. To avoid this, use either of the other modes.
3755      *
3756      * @see WindowManager.LayoutParams#layoutInDisplayCutoutMode
3757      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
3758      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
3759      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
3760      *
3761      * @deprecated For floating windows, use {@link LayoutParams#setFitInsetsTypes(int)} with
3762      * {@link Type#statusBars()} ()}. For non-floating windows that fill the screen, call
3763      * {@link Window#setDecorFitsSystemWindows(boolean)} with {@code false}.
3764      */
3765     @Deprecated
3766     public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
3767 
3768     /**
3769      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3770      * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
3771      * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
3772      * user interaction.
3773      * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
3774      * has an effect when used in combination with that flag.</p>
3775      *
3776      * @deprecated Use {@link WindowInsetsController#BEHAVIOR_SHOW_BARS_BY_SWIPE} instead.
3777      */
3778     @Deprecated
3779     public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
3780 
3781     /**
3782      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3783      * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
3784      * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
3785      * experience while also hiding the system bars.  If this flag is not set,
3786      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
3787      * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
3788      * if the user swipes from the top of the screen.
3789      * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
3790      * system gestures, such as swiping from the top of the screen.  These transient system bars
3791      * will overlay app's content, may have some degree of transparency, and will automatically
3792      * hide after a short timeout.
3793      * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
3794      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
3795      * with one or both of those flags.</p>
3796      *
3797      * @deprecated Use {@link WindowInsetsController#BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE} instead.
3798      */
3799     @Deprecated
3800     public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
3801 
3802     /**
3803      * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
3804      * is compatible with light status bar backgrounds.
3805      *
3806      * <p>For this to take effect, the window must request
3807      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3808      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3809      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
3810      *         FLAG_TRANSLUCENT_STATUS}.
3811      *
3812      * @see android.R.attr#windowLightStatusBar
3813      * @deprecated Use {@link WindowInsetsController#APPEARANCE_LIGHT_STATUS_BARS} instead.
3814      */
3815     @Deprecated
3816     public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
3817 
3818     /**
3819      * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3820      * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3821      */
3822     private static final int SYSTEM_UI_RESERVED_LEGACY1 = 0x00004000;
3823 
3824     /**
3825      * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3826      * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3827      */
3828     private static final int SYSTEM_UI_RESERVED_LEGACY2 = 0x00010000;
3829 
3830     /**
3831      * Flag for {@link #setSystemUiVisibility(int)}: Requests the navigation bar to draw in a mode
3832      * that is compatible with light navigation bar backgrounds.
3833      *
3834      * <p>For this to take effect, the window must request
3835      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3836      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3837      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION
3838      *         FLAG_TRANSLUCENT_NAVIGATION}.
3839      *
3840      * @see android.R.attr#windowLightNavigationBar
3841      * @deprecated Use {@link WindowInsetsController#APPEARANCE_LIGHT_NAVIGATION_BARS} instead.
3842      */
3843     @Deprecated
3844     public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010;
3845 
3846     /**
3847      * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
3848      */
3849     @Deprecated
3850     public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
3851 
3852     /**
3853      * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
3854      */
3855     @Deprecated
3856     public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
3857 
3858     /**
3859      * @hide
3860      *
3861      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3862      * out of the public fields to keep the undefined bits out of the developer's way.
3863      *
3864      * Flag to make the status bar not expandable.  Unless you also
3865      * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
3866      */
3867     @UnsupportedAppUsage
3868     public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
3869 
3870     /**
3871      * @hide
3872      *
3873      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3874      * out of the public fields to keep the undefined bits out of the developer's way.
3875      *
3876      * Flag to hide notification icons and scrolling ticker text.
3877      */
3878     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
3879 
3880     /**
3881      * @hide
3882      *
3883      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3884      * out of the public fields to keep the undefined bits out of the developer's way.
3885      *
3886      * Flag to disable incoming notification alerts.  This will not block
3887      * icons, but it will block sound, vibrating and other visual or aural notifications.
3888      */
3889     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
3890 
3891     /**
3892      * @hide
3893      *
3894      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3895      * out of the public fields to keep the undefined bits out of the developer's way.
3896      *
3897      * Flag to hide only the scrolling ticker.  Note that
3898      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
3899      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
3900      */
3901     public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
3902 
3903     /**
3904      * @hide
3905      *
3906      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3907      * out of the public fields to keep the undefined bits out of the developer's way.
3908      *
3909      * Flag to hide the center system info area.
3910      */
3911     public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
3912 
3913     /**
3914      * @hide
3915      *
3916      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3917      * out of the public fields to keep the undefined bits out of the developer's way.
3918      *
3919      * Flag to hide only the home button.  Don't use this
3920      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3921      */
3922     @UnsupportedAppUsage
3923     public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
3924 
3925     /**
3926      * @hide
3927      *
3928      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3929      * out of the public fields to keep the undefined bits out of the developer's way.
3930      *
3931      * Flag to hide only the back button. Don't use this
3932      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3933      */
3934     @UnsupportedAppUsage
3935     public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
3936 
3937     /**
3938      * @hide
3939      *
3940      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3941      * out of the public fields to keep the undefined bits out of the developer's way.
3942      *
3943      * Flag to hide only the clock.  You might use this if your activity has
3944      * its own clock making the status bar's clock redundant.
3945      */
3946     public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
3947 
3948     /**
3949      * @hide
3950      *
3951      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3952      * out of the public fields to keep the undefined bits out of the developer's way.
3953      *
3954      * Flag to hide only the recent apps button. Don't use this
3955      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3956      */
3957     @UnsupportedAppUsage
3958     public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
3959 
3960     /**
3961      * @hide
3962      *
3963      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3964      * out of the public fields to keep the undefined bits out of the developer's way.
3965      *
3966      * Flag to disable the global search gesture. Don't use this
3967      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3968      */
3969     public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
3970 
3971     /**
3972      * @hide
3973      *
3974      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3975      * out of the public fields to keep the undefined bits out of the developer's way.
3976      *
3977      * Flag to specify that the status bar is displayed in transient mode.
3978      */
3979     public static final int STATUS_BAR_TRANSIENT = 0x04000000;
3980 
3981     /**
3982      * @hide
3983      *
3984      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3985      * out of the public fields to keep the undefined bits out of the developer's way.
3986      *
3987      * Flag to specify that the navigation bar is displayed in transient mode.
3988      */
3989     @UnsupportedAppUsage
3990     public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
3991 
3992     /**
3993      * @hide
3994      *
3995      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3996      * out of the public fields to keep the undefined bits out of the developer's way.
3997      *
3998      * Flag to specify that the hidden status bar would like to be shown.
3999      */
4000     public static final int STATUS_BAR_UNHIDE = 0x10000000;
4001 
4002     /**
4003      * @hide
4004      *
4005      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4006      * out of the public fields to keep the undefined bits out of the developer's way.
4007      *
4008      * Flag to specify that the hidden navigation bar would like to be shown.
4009      */
4010     public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
4011 
4012     /**
4013      * @hide
4014      *
4015      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4016      * out of the public fields to keep the undefined bits out of the developer's way.
4017      *
4018      * Flag to specify that the status bar is displayed in translucent mode.
4019      */
4020     public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
4021 
4022     /**
4023      * @hide
4024      *
4025      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4026      * out of the public fields to keep the undefined bits out of the developer's way.
4027      *
4028      * Flag to specify that the navigation bar is displayed in translucent mode.
4029      */
4030     public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
4031 
4032     /**
4033      * @hide
4034      *
4035      * Makes navigation bar transparent (but not the status bar).
4036      */
4037     public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
4038 
4039     /**
4040      * @hide
4041      *
4042      * Makes status bar transparent (but not the navigation bar).
4043      */
4044     public static final int STATUS_BAR_TRANSPARENT = 0x00000008;
4045 
4046     /**
4047      * @hide
4048      *
4049      * Makes both status bar and navigation bar transparent.
4050      */
4051     public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
4052             | STATUS_BAR_TRANSPARENT;
4053 
4054     /**
4055      * @hide
4056      */
4057     public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
4058 
4059     /**
4060      * These are the system UI flags that can be cleared by events outside
4061      * of an application.  Currently this is just the ability to tap on the
4062      * screen while hiding the navigation bar to have it return.
4063      * @hide
4064      */
4065     public static final int SYSTEM_UI_CLEARABLE_FLAGS =
4066             SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
4067             | SYSTEM_UI_FLAG_FULLSCREEN;
4068 
4069     /**
4070      * Flags that can impact the layout in relation to system UI.
4071      *
4072      * @deprecated System UI layout flags are deprecated.
4073      */
4074     @Deprecated
4075     public static final int SYSTEM_UI_LAYOUT_FLAGS =
4076             SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
4077             | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
4078 
4079     /** @hide */
4080     @IntDef(flag = true, prefix = { "FIND_VIEWS_" }, value = {
4081             FIND_VIEWS_WITH_TEXT,
4082             FIND_VIEWS_WITH_CONTENT_DESCRIPTION
4083     })
4084     @Retention(RetentionPolicy.SOURCE)
4085     public @interface FindViewFlags {}
4086 
4087     /**
4088      * Find views that render the specified text.
4089      *
4090      * @see #findViewsWithText(ArrayList, CharSequence, int)
4091      */
4092     public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
4093 
4094     /**
4095      * Find find views that contain the specified content description.
4096      *
4097      * @see #findViewsWithText(ArrayList, CharSequence, int)
4098      */
4099     public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
4100 
4101     /**
4102      * Find views that contain {@link AccessibilityNodeProvider}. Such
4103      * a View is a root of virtual view hierarchy and may contain the searched
4104      * text. If this flag is set Views with providers are automatically
4105      * added and it is a responsibility of the client to call the APIs of
4106      * the provider to determine whether the virtual tree rooted at this View
4107      * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
4108      * representing the virtual views with this text.
4109      *
4110      * @see #findViewsWithText(ArrayList, CharSequence, int)
4111      *
4112      * @hide
4113      */
4114     public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
4115 
4116     /**
4117      * The undefined cursor position.
4118      *
4119      * @hide
4120      */
4121     public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
4122 
4123     /**
4124      * Indicates that the screen has changed state and is now off.
4125      *
4126      * @see #onScreenStateChanged(int)
4127      */
4128     public static final int SCREEN_STATE_OFF = 0x0;
4129 
4130     /**
4131      * Indicates that the screen has changed state and is now on.
4132      *
4133      * @see #onScreenStateChanged(int)
4134      */
4135     public static final int SCREEN_STATE_ON = 0x1;
4136 
4137     /**
4138      * Indicates no axis of view scrolling.
4139      */
4140     public static final int SCROLL_AXIS_NONE = 0;
4141 
4142     /**
4143      * Indicates scrolling along the horizontal axis.
4144      */
4145     public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
4146 
4147     /**
4148      * Indicates scrolling along the vertical axis.
4149      */
4150     public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
4151 
4152     /**
4153      * Controls the over-scroll mode for this view.
4154      * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
4155      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
4156      * and {@link #OVER_SCROLL_NEVER}.
4157      */
4158     private int mOverScrollMode;
4159 
4160     /**
4161      * The parent this view is attached to.
4162      * {@hide}
4163      *
4164      * @see #getParent()
4165      */
4166     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4167     protected ViewParent mParent;
4168 
4169     /**
4170      * {@hide}
4171      *
4172      * Not available for general use. If you need help, hang up and then dial one of the following
4173      * public APIs:
4174      *
4175      * @see #isAttachedToWindow() for current attach state
4176      * @see #onAttachedToWindow() for subclasses performing work when becoming attached
4177      * @see #onDetachedFromWindow() for subclasses performing work when becoming detached
4178      * @see OnAttachStateChangeListener for other code performing work on attach/detach
4179      * @see #getHandler() for posting messages to this view's UI thread/looper
4180      * @see #getParent() for interacting with the parent chain
4181      * @see #getWindowToken() for the current window token
4182      * @see #getRootView() for the view at the root of the attached hierarchy
4183      * @see #getDisplay() for the Display this view is presented on
4184      * @see #getRootWindowInsets() for the current insets applied to the whole attached window
4185      * @see #hasWindowFocus() for whether the attached window is currently focused
4186      * @see #getWindowVisibility() for checking the visibility of the attached window
4187      */
4188     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4189     AttachInfo mAttachInfo;
4190 
4191     /**
4192      * {@hide}
4193      */
4194     @ViewDebug.ExportedProperty(flagMapping = {
4195         @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
4196                 name = "FORCE_LAYOUT"),
4197         @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
4198                 name = "LAYOUT_REQUIRED"),
4199         @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
4200             name = "DRAWING_CACHE_INVALID", outputIf = false),
4201         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
4202         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
4203         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
4204     }, formatToHexString = true)
4205 
4206     /* @hide */
4207     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769414)
4208     public int mPrivateFlags;
4209     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768943)
4210     int mPrivateFlags2;
4211     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 129147060)
4212     int mPrivateFlags3;
4213 
4214     private int mPrivateFlags4;
4215 
4216     /**
4217      * This view's request for the visibility of the status bar.
4218      * @hide
4219      */
4220     @ViewDebug.ExportedProperty(flagMapping = {
4221             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
4222                     equals = SYSTEM_UI_FLAG_LOW_PROFILE,
4223                     name = "LOW_PROFILE"),
4224             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
4225                     equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
4226                     name = "HIDE_NAVIGATION"),
4227             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_FULLSCREEN,
4228                     equals = SYSTEM_UI_FLAG_FULLSCREEN,
4229                     name = "FULLSCREEN"),
4230             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_STABLE,
4231                     equals = SYSTEM_UI_FLAG_LAYOUT_STABLE,
4232                     name = "LAYOUT_STABLE"),
4233             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
4234                     equals = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
4235                     name = "LAYOUT_HIDE_NAVIGATION"),
4236             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
4237                     equals = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
4238                     name = "LAYOUT_FULLSCREEN"),
4239             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE,
4240                     equals = SYSTEM_UI_FLAG_IMMERSIVE,
4241                     name = "IMMERSIVE"),
4242             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
4243                     equals = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
4244                     name = "IMMERSIVE_STICKY"),
4245             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
4246                     equals = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
4247                     name = "LIGHT_STATUS_BAR"),
4248             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
4249                     equals = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
4250                     name = "LIGHT_NAVIGATION_BAR"),
4251             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_EXPAND,
4252                     equals = STATUS_BAR_DISABLE_EXPAND,
4253                     name = "STATUS_BAR_DISABLE_EXPAND"),
4254             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
4255                     equals = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
4256                     name = "STATUS_BAR_DISABLE_NOTIFICATION_ICONS"),
4257             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
4258                     equals = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
4259                     name = "STATUS_BAR_DISABLE_NOTIFICATION_ALERTS"),
4260             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
4261                     equals = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
4262                     name = "STATUS_BAR_DISABLE_NOTIFICATION_TICKER"),
4263             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SYSTEM_INFO,
4264                     equals = STATUS_BAR_DISABLE_SYSTEM_INFO,
4265                     name = "STATUS_BAR_DISABLE_SYSTEM_INFO"),
4266             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_HOME,
4267                     equals = STATUS_BAR_DISABLE_HOME,
4268                     name = "STATUS_BAR_DISABLE_HOME"),
4269             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_BACK,
4270                     equals = STATUS_BAR_DISABLE_BACK,
4271                     name = "STATUS_BAR_DISABLE_BACK"),
4272             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_CLOCK,
4273                     equals = STATUS_BAR_DISABLE_CLOCK,
4274                     name = "STATUS_BAR_DISABLE_CLOCK"),
4275             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_RECENT,
4276                     equals = STATUS_BAR_DISABLE_RECENT,
4277                     name = "STATUS_BAR_DISABLE_RECENT"),
4278             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SEARCH,
4279                     equals = STATUS_BAR_DISABLE_SEARCH,
4280                     name = "STATUS_BAR_DISABLE_SEARCH"),
4281             @ViewDebug.FlagToString(mask = STATUS_BAR_TRANSIENT,
4282                     equals = STATUS_BAR_TRANSIENT,
4283                     name = "STATUS_BAR_TRANSIENT"),
4284             @ViewDebug.FlagToString(mask = NAVIGATION_BAR_TRANSIENT,
4285                     equals = NAVIGATION_BAR_TRANSIENT,
4286                     name = "NAVIGATION_BAR_TRANSIENT"),
4287             @ViewDebug.FlagToString(mask = STATUS_BAR_UNHIDE,
4288                     equals = STATUS_BAR_UNHIDE,
4289                     name = "STATUS_BAR_UNHIDE"),
4290             @ViewDebug.FlagToString(mask = NAVIGATION_BAR_UNHIDE,
4291                     equals = NAVIGATION_BAR_UNHIDE,
4292                     name = "NAVIGATION_BAR_UNHIDE"),
4293             @ViewDebug.FlagToString(mask = STATUS_BAR_TRANSLUCENT,
4294                     equals = STATUS_BAR_TRANSLUCENT,
4295                     name = "STATUS_BAR_TRANSLUCENT"),
4296             @ViewDebug.FlagToString(mask = NAVIGATION_BAR_TRANSLUCENT,
4297                     equals = NAVIGATION_BAR_TRANSLUCENT,
4298                     name = "NAVIGATION_BAR_TRANSLUCENT"),
4299             @ViewDebug.FlagToString(mask = NAVIGATION_BAR_TRANSPARENT,
4300                     equals = NAVIGATION_BAR_TRANSPARENT,
4301                     name = "NAVIGATION_BAR_TRANSPARENT"),
4302             @ViewDebug.FlagToString(mask = STATUS_BAR_TRANSPARENT,
4303                     equals = STATUS_BAR_TRANSPARENT,
4304                     name = "STATUS_BAR_TRANSPARENT")
4305     }, formatToHexString = true)
4306     int mSystemUiVisibility;
4307 
4308     /**
4309      * Reference count for transient state.
4310      * @see #setHasTransientState(boolean)
4311      */
4312     int mTransientStateCount = 0;
4313 
4314     /**
4315      * Count of how many windows this view has been attached to.
4316      */
4317     int mWindowAttachCount;
4318 
4319     /**
4320      * The layout parameters associated with this view and used by the parent
4321      * {@link android.view.ViewGroup} to determine how this view should be
4322      * laid out.
4323      *
4324      * The field should not be used directly. Instead {@link #getLayoutParams()} and {@link
4325      * #setLayoutParams(ViewGroup.LayoutParams)} should be used. The setter guarantees internal
4326      * state correctness of the class.
4327      * {@hide}
4328      */
4329     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4330     protected ViewGroup.LayoutParams mLayoutParams;
4331 
4332     /**
4333      * The view flags hold various views states.
4334      *
4335      * Use {@link #setTransitionVisibility(int)} to change the visibility of this view without
4336      * triggering updates.
4337      * {@hide}
4338      */
4339     @ViewDebug.ExportedProperty(formatToHexString = true)
4340     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4341     int mViewFlags;
4342 
4343     static class TransformationInfo {
4344         /**
4345          * The transform matrix for the View. This transform is calculated internally
4346          * based on the translation, rotation, and scale properties.
4347          *
4348          * Do *not* use this variable directly; instead call getMatrix(), which will
4349          * load the value from the View's RenderNode.
4350          */
4351         private final Matrix mMatrix = new Matrix();
4352 
4353         /**
4354          * The inverse transform matrix for the View. This transform is calculated
4355          * internally based on the translation, rotation, and scale properties.
4356          *
4357          * Do *not* use this variable directly; instead call getInverseMatrix(),
4358          * which will load the value from the View's RenderNode.
4359          */
4360         private Matrix mInverseMatrix;
4361 
4362         /**
4363          * The opacity of the View. This is a value from 0 to 1, where 0 means
4364          * completely transparent and 1 means completely opaque.
4365          */
4366         @ViewDebug.ExportedProperty
4367         private float mAlpha = 1f;
4368 
4369         /**
4370          * The opacity of the view as manipulated by the Fade transition. This is a
4371          * property only used by transitions, which is composited with the other alpha
4372          * values to calculate the final visual alpha value.
4373          */
4374         float mTransitionAlpha = 1f;
4375     }
4376 
4377     /** @hide */
4378     @UnsupportedAppUsage
4379     public TransformationInfo mTransformationInfo;
4380 
4381     /**
4382      * Current clip bounds. to which all drawing of this view are constrained.
4383      */
4384     @ViewDebug.ExportedProperty(category = "drawing")
4385     Rect mClipBounds = null;
4386 
4387     private boolean mLastIsOpaque;
4388 
4389     /**
4390      * The distance in pixels from the left edge of this view's parent
4391      * to the left edge of this view.
4392      * {@hide}
4393      */
4394     @ViewDebug.ExportedProperty(category = "layout")
4395     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4396     protected int mLeft;
4397     /**
4398      * The distance in pixels from the left edge of this view's parent
4399      * to the right edge of this view.
4400      * {@hide}
4401      */
4402     @ViewDebug.ExportedProperty(category = "layout")
4403     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4404     protected int mRight;
4405     /**
4406      * The distance in pixels from the top edge of this view's parent
4407      * to the top edge of this view.
4408      * {@hide}
4409      */
4410     @ViewDebug.ExportedProperty(category = "layout")
4411     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4412     protected int mTop;
4413     /**
4414      * The distance in pixels from the top edge of this view's parent
4415      * to the bottom edge of this view.
4416      * {@hide}
4417      */
4418     @ViewDebug.ExportedProperty(category = "layout")
4419     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4420     protected int mBottom;
4421 
4422     /**
4423      * The offset, in pixels, by which the content of this view is scrolled
4424      * horizontally.
4425      * Please use {@link View#getScrollX()} and {@link View#setScrollX(int)} instead of
4426      * accessing these directly.
4427      * {@hide}
4428      */
4429     @ViewDebug.ExportedProperty(category = "scrolling")
4430     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4431     protected int mScrollX;
4432     /**
4433      * The offset, in pixels, by which the content of this view is scrolled
4434      * vertically.
4435      * Please use {@link View#getScrollY()} and {@link View#setScrollY(int)} instead of
4436      * accessing these directly.
4437      * {@hide}
4438      */
4439     @ViewDebug.ExportedProperty(category = "scrolling")
4440     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4441     protected int mScrollY;
4442 
4443     /**
4444      * The final computed left padding in pixels that is used for drawing. This is the distance in
4445      * pixels between the left edge of this view and the left edge of its content.
4446      * {@hide}
4447      */
4448     @ViewDebug.ExportedProperty(category = "padding")
4449     @UnsupportedAppUsage
4450     protected int mPaddingLeft = 0;
4451     /**
4452      * The final computed right padding in pixels that is used for drawing. This is the distance in
4453      * pixels between the right edge of this view and the right edge of its content.
4454      * {@hide}
4455      */
4456     @ViewDebug.ExportedProperty(category = "padding")
4457     @UnsupportedAppUsage
4458     protected int mPaddingRight = 0;
4459     /**
4460      * The final computed top padding in pixels that is used for drawing. This is the distance in
4461      * pixels between the top edge of this view and the top edge of its content.
4462      * {@hide}
4463      */
4464     @ViewDebug.ExportedProperty(category = "padding")
4465     @UnsupportedAppUsage
4466     protected int mPaddingTop;
4467     /**
4468      * The final computed bottom padding in pixels that is used for drawing. This is the distance in
4469      * pixels between the bottom edge of this view and the bottom edge of its content.
4470      * {@hide}
4471      */
4472     @ViewDebug.ExportedProperty(category = "padding")
4473     @UnsupportedAppUsage
4474     protected int mPaddingBottom;
4475 
4476     /**
4477      * The layout insets in pixels, that is the distance in pixels between the
4478      * visible edges of this view its bounds.
4479      */
4480     private Insets mLayoutInsets;
4481 
4482     /**
4483      * Briefly describes the state of the view and is primarily used for accessibility support.
4484      */
4485     private CharSequence mStateDescription;
4486 
4487     /**
4488      * Briefly describes the view and is primarily used for accessibility support.
4489      */
4490     private CharSequence mContentDescription;
4491 
4492     /**
4493      * If this view represents a distinct part of the window, it can have a title that labels the
4494      * area.
4495      */
4496     private CharSequence mAccessibilityPaneTitle;
4497 
4498     /**
4499      * Specifies the id of a view for which this view serves as a label for
4500      * accessibility purposes.
4501      */
4502     private int mLabelForId = View.NO_ID;
4503 
4504     /**
4505      * Predicate for matching labeled view id with its label for
4506      * accessibility purposes.
4507      */
4508     private MatchLabelForPredicate mMatchLabelForPredicate;
4509 
4510     /**
4511      * Specifies a view before which this one is visited in accessibility traversal.
4512      */
4513     private int mAccessibilityTraversalBeforeId = NO_ID;
4514 
4515     /**
4516      * Specifies a view after which this one is visited in accessibility traversal.
4517      */
4518     private int mAccessibilityTraversalAfterId = NO_ID;
4519 
4520     /**
4521      * Predicate for matching a view by its id.
4522      */
4523     private MatchIdPredicate mMatchIdPredicate;
4524 
4525     /**
4526      * The right padding after RTL resolution, but before taking account of scroll bars.
4527      *
4528      * @hide
4529      */
4530     @ViewDebug.ExportedProperty(category = "padding")
4531     protected int mUserPaddingRight;
4532 
4533     /**
4534      * The resolved bottom padding before taking account of scroll bars.
4535      *
4536      * @hide
4537      */
4538     @ViewDebug.ExportedProperty(category = "padding")
4539     protected int mUserPaddingBottom;
4540 
4541     /**
4542      * The left padding after RTL resolution, but before taking account of scroll bars.
4543      *
4544      * @hide
4545      */
4546     @ViewDebug.ExportedProperty(category = "padding")
4547     protected int mUserPaddingLeft;
4548 
4549     /**
4550      * Cache the paddingStart set by the user to append to the scrollbar's size.
4551      *
4552      */
4553     @ViewDebug.ExportedProperty(category = "padding")
4554     int mUserPaddingStart;
4555 
4556     /**
4557      * Cache the paddingEnd set by the user to append to the scrollbar's size.
4558      *
4559      */
4560     @ViewDebug.ExportedProperty(category = "padding")
4561     int mUserPaddingEnd;
4562 
4563     /**
4564      * The left padding as set by a setter method, a background's padding, or via XML property
4565      * resolution. This value is the padding before LTR resolution or taking account of scrollbars.
4566      *
4567      * @hide
4568      */
4569     int mUserPaddingLeftInitial;
4570 
4571     /**
4572      * The right padding as set by a setter method, a background's padding, or via XML property
4573      * resolution. This value is the padding before LTR resolution or taking account of scrollbars.
4574      *
4575      * @hide
4576      */
4577     int mUserPaddingRightInitial;
4578 
4579     /**
4580      * Default undefined padding
4581      */
4582     private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
4583 
4584     /**
4585      * Cache if a left padding has been defined explicitly via padding, horizontal padding,
4586      * or leftPadding in XML, or by setPadding(...) or setRelativePadding(...)
4587      */
4588     private boolean mLeftPaddingDefined = false;
4589 
4590     /**
4591      * Cache if a right padding has been defined explicitly via padding, horizontal padding,
4592      * or rightPadding in XML, or by setPadding(...) or setRelativePadding(...)
4593      */
4594     private boolean mRightPaddingDefined = false;
4595 
4596     /**
4597      * @hide
4598      */
4599     int mOldWidthMeasureSpec = Integer.MIN_VALUE;
4600     /**
4601      * @hide
4602      */
4603     int mOldHeightMeasureSpec = Integer.MIN_VALUE;
4604 
4605     private LongSparseLongArray mMeasureCache;
4606 
4607     @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
4608     @UnsupportedAppUsage
4609     private Drawable mBackground;
4610     private TintInfo mBackgroundTint;
4611 
4612     @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
4613     private ForegroundInfo mForegroundInfo;
4614 
4615     private Drawable mScrollIndicatorDrawable;
4616 
4617     /**
4618      * RenderNode used for backgrounds.
4619      * <p>
4620      * When non-null and valid, this is expected to contain an up-to-date copy
4621      * of the background drawable. It is cleared on temporary detach, and reset
4622      * on cleanup.
4623      * @hide
4624      */
4625     RenderNode mBackgroundRenderNode;
4626 
4627     @UnsupportedAppUsage
4628     private int mBackgroundResource;
4629     private boolean mBackgroundSizeChanged;
4630 
4631     /** The default focus highlight.
4632      * @see #mDefaultFocusHighlightEnabled
4633      * @see Drawable#hasFocusStateSpecified()
4634      */
4635     private Drawable mDefaultFocusHighlight;
4636     private Drawable mDefaultFocusHighlightCache;
4637     private boolean mDefaultFocusHighlightSizeChanged;
4638     /**
4639      * True if the default focus highlight is needed on the target device.
4640      */
4641     private static boolean sUseDefaultFocusHighlight;
4642 
4643     /**
4644      * True if zero-sized views can be focused.
4645      */
4646     private static boolean sCanFocusZeroSized;
4647 
4648     /**
4649      * Always assign focus if a focusable View is available.
4650      */
4651     private static boolean sAlwaysAssignFocus;
4652 
4653     private String mTransitionName;
4654 
4655     static class TintInfo {
4656         ColorStateList mTintList;
4657         BlendMode mBlendMode;
4658         boolean mHasTintMode;
4659         boolean mHasTintList;
4660     }
4661 
4662     private static class ForegroundInfo {
4663         private Drawable mDrawable;
4664         private TintInfo mTintInfo;
4665         private int mGravity = Gravity.FILL;
4666         private boolean mInsidePadding = true;
4667         private boolean mBoundsChanged = true;
4668         private final Rect mSelfBounds = new Rect();
4669         private final Rect mOverlayBounds = new Rect();
4670     }
4671 
4672     static class ListenerInfo {
4673 
4674         @UnsupportedAppUsage
ListenerInfo()4675         ListenerInfo() {
4676         }
4677 
4678         /**
4679          * Listener used to dispatch focus change events.
4680          * This field should be made private, so it is hidden from the SDK.
4681          * {@hide}
4682          */
4683         @UnsupportedAppUsage
4684         protected OnFocusChangeListener mOnFocusChangeListener;
4685 
4686         /**
4687          * Listeners for layout change events.
4688          */
4689         private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
4690 
4691         protected OnScrollChangeListener mOnScrollChangeListener;
4692 
4693         /**
4694          * Listeners for attach events.
4695          */
4696         private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
4697 
4698         /**
4699          * Listener used to dispatch click events.
4700          * This field should be made private, so it is hidden from the SDK.
4701          * {@hide}
4702          */
4703         @UnsupportedAppUsage
4704         public OnClickListener mOnClickListener;
4705 
4706         /**
4707          * Listener used to dispatch long click events.
4708          * This field should be made private, so it is hidden from the SDK.
4709          * {@hide}
4710          */
4711         @UnsupportedAppUsage
4712         protected OnLongClickListener mOnLongClickListener;
4713 
4714         /**
4715          * Listener used to dispatch context click events. This field should be made private, so it
4716          * is hidden from the SDK.
4717          * {@hide}
4718          */
4719         protected OnContextClickListener mOnContextClickListener;
4720 
4721         /**
4722          * Listener used to build the context menu.
4723          * This field should be made private, so it is hidden from the SDK.
4724          * {@hide}
4725          */
4726         @UnsupportedAppUsage
4727         protected OnCreateContextMenuListener mOnCreateContextMenuListener;
4728 
4729         @UnsupportedAppUsage
4730         private OnKeyListener mOnKeyListener;
4731 
4732         @UnsupportedAppUsage
4733         private OnTouchListener mOnTouchListener;
4734 
4735         @UnsupportedAppUsage
4736         private OnHoverListener mOnHoverListener;
4737 
4738         @UnsupportedAppUsage
4739         private OnGenericMotionListener mOnGenericMotionListener;
4740 
4741         @UnsupportedAppUsage
4742         private OnDragListener mOnDragListener;
4743 
4744         private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
4745 
4746         OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
4747 
4748         OnCapturedPointerListener mOnCapturedPointerListener;
4749 
4750         private ArrayList<OnUnhandledKeyEventListener> mUnhandledKeyListeners;
4751 
4752         WindowInsetsAnimation.Callback mWindowInsetsAnimationCallback;
4753 
4754         /**
4755          * This lives here since it's only valid for interactive views.
4756          */
4757         private List<Rect> mSystemGestureExclusionRects;
4758 
4759         /**
4760          * Used to track {@link #mSystemGestureExclusionRects}
4761          */
4762         public RenderNode.PositionUpdateListener mPositionUpdateListener;
4763 
4764         /**
4765          * Allows the application to implement custom scroll capture support.
4766          */
4767         ScrollCaptureCallback mScrollCaptureCallback;
4768     }
4769 
4770     @UnsupportedAppUsage
4771     ListenerInfo mListenerInfo;
4772 
4773     private static class TooltipInfo {
4774         /**
4775          * Text to be displayed in a tooltip popup.
4776          */
4777         @Nullable
4778         CharSequence mTooltipText;
4779 
4780         /**
4781          * View-relative position of the tooltip anchor point.
4782          */
4783         int mAnchorX;
4784         int mAnchorY;
4785 
4786         /**
4787          * The tooltip popup.
4788          */
4789         @Nullable
4790         TooltipPopup mTooltipPopup;
4791 
4792         /**
4793          * Set to true if the tooltip was shown as a result of a long click.
4794          */
4795         boolean mTooltipFromLongClick;
4796 
4797         /**
4798          * Keep these Runnables so that they can be used to reschedule.
4799          */
4800         Runnable mShowTooltipRunnable;
4801         Runnable mHideTooltipRunnable;
4802 
4803         /**
4804          * Hover move is ignored if it is within this distance in pixels from the previous one.
4805          */
4806         int mHoverSlop;
4807 
4808         /**
4809          * Update the anchor position if it significantly (that is by at least mHoverSlop)
4810          * different from the previously stored position. Ignoring insignificant changes
4811          * filters out the jitter which is typical for such input sources as stylus.
4812          *
4813          * @return True if the position has been updated.
4814          */
updateAnchorPos(MotionEvent event)4815         private boolean updateAnchorPos(MotionEvent event) {
4816             final int newAnchorX = (int) event.getX();
4817             final int newAnchorY = (int) event.getY();
4818             if (Math.abs(newAnchorX - mAnchorX) <= mHoverSlop
4819                     && Math.abs(newAnchorY - mAnchorY) <= mHoverSlop) {
4820                 return false;
4821             }
4822             mAnchorX = newAnchorX;
4823             mAnchorY = newAnchorY;
4824             return true;
4825         }
4826 
4827         /**
4828          *  Clear the anchor position to ensure that the next change is considered significant.
4829          */
clearAnchorPos()4830         private void clearAnchorPos() {
4831             mAnchorX = Integer.MAX_VALUE;
4832             mAnchorY = Integer.MAX_VALUE;
4833         }
4834     }
4835 
4836     TooltipInfo mTooltipInfo;
4837 
4838     // Temporary values used to hold (x,y) coordinates when delegating from the
4839     // two-arg performLongClick() method to the legacy no-arg version.
4840     private float mLongClickX = Float.NaN;
4841     private float mLongClickY = Float.NaN;
4842 
4843     /**
4844      * The application environment this view lives in.
4845      * This field should be made private, so it is hidden from the SDK.
4846      * {@hide}
4847      */
4848     @ViewDebug.ExportedProperty(deepExport = true)
4849     @UnsupportedAppUsage
4850     protected Context mContext;
4851 
4852     @UnsupportedAppUsage
4853     private final Resources mResources;
4854 
4855     @UnsupportedAppUsage
4856     private ScrollabilityCache mScrollCache;
4857 
4858     private int[] mDrawableState = null;
4859 
4860     ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
4861 
4862     /**
4863      * Animator that automatically runs based on state changes.
4864      */
4865     private StateListAnimator mStateListAnimator;
4866 
4867     /**
4868      * When this view has focus and the next focus is {@link #FOCUS_LEFT},
4869      * the user may specify which view to go to next.
4870      */
4871     private int mNextFocusLeftId = View.NO_ID;
4872 
4873     /**
4874      * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
4875      * the user may specify which view to go to next.
4876      */
4877     private int mNextFocusRightId = View.NO_ID;
4878 
4879     /**
4880      * When this view has focus and the next focus is {@link #FOCUS_UP},
4881      * the user may specify which view to go to next.
4882      */
4883     private int mNextFocusUpId = View.NO_ID;
4884 
4885     /**
4886      * When this view has focus and the next focus is {@link #FOCUS_DOWN},
4887      * the user may specify which view to go to next.
4888      */
4889     private int mNextFocusDownId = View.NO_ID;
4890 
4891     /**
4892      * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
4893      * the user may specify which view to go to next.
4894      */
4895     int mNextFocusForwardId = View.NO_ID;
4896 
4897     /**
4898      * User-specified next keyboard navigation cluster in the {@link #FOCUS_FORWARD} direction.
4899      *
4900      * @see #findUserSetNextKeyboardNavigationCluster(View, int)
4901      */
4902     int mNextClusterForwardId = View.NO_ID;
4903 
4904     /**
4905      * Whether this View should use a default focus highlight when it gets focused but doesn't
4906      * have {@link android.R.attr#state_focused} defined in its background.
4907      */
4908     boolean mDefaultFocusHighlightEnabled = true;
4909 
4910     private CheckForLongPress mPendingCheckForLongPress;
4911     @UnsupportedAppUsage
4912     private CheckForTap mPendingCheckForTap = null;
4913     private PerformClick mPerformClick;
4914     private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
4915     private SendAccessibilityEventThrottle mSendStateChangedAccessibilityEvent;
4916     private UnsetPressedState mUnsetPressedState;
4917 
4918     /**
4919      * Whether the long press's action has been invoked.  The tap's action is invoked on the
4920      * up event while a long press is invoked as soon as the long press duration is reached, so
4921      * a long press could be performed before the tap is checked, in which case the tap's action
4922      * should not be invoked.
4923      */
4924     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
4925     private boolean mHasPerformedLongPress;
4926 
4927     /**
4928      * Whether a context click button is currently pressed down. This is true when the stylus is
4929      * touching the screen and the primary button has been pressed, or if a mouse's right button is
4930      * pressed. This is false once the button is released or if the stylus has been lifted.
4931      */
4932     private boolean mInContextButtonPress;
4933 
4934     /**
4935      * Whether the next up event should be ignored for the purposes of gesture recognition. This is
4936      * true after a stylus button press has occured, when the next up event should not be recognized
4937      * as a tap.
4938      */
4939     private boolean mIgnoreNextUpEvent;
4940 
4941     /**
4942      * The minimum height of the view. We'll try our best to have the height
4943      * of this view to at least this amount.
4944      */
4945     @ViewDebug.ExportedProperty(category = "measurement")
4946     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4947     private int mMinHeight;
4948 
4949     /**
4950      * The minimum width of the view. We'll try our best to have the width
4951      * of this view to at least this amount.
4952      */
4953     @ViewDebug.ExportedProperty(category = "measurement")
4954     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4955     private int mMinWidth;
4956 
4957     /**
4958      * The delegate to handle touch events that are physically in this view
4959      * but should be handled by another view.
4960      */
4961     private TouchDelegate mTouchDelegate = null;
4962 
4963     /**
4964      * While touch exploration is in use, set to true when hovering across boundaries and
4965      * inside the touch area of the delegate at receiving {@link MotionEvent#ACTION_HOVER_ENTER}
4966      * or {@link MotionEvent#ACTION_HOVER_MOVE}. False when leaving boundaries or receiving a
4967      * {@link MotionEvent#ACTION_HOVER_EXIT}.
4968      * Note that children of view group are excluded in the touch area.
4969      * @see #dispatchTouchExplorationHoverEvent
4970      */
4971     private boolean mHoveringTouchDelegate = false;
4972 
4973     /**
4974      * Solid color to use as a background when creating the drawing cache. Enables
4975      * the cache to use 16 bit bitmaps instead of 32 bit.
4976      */
4977     private int mDrawingCacheBackgroundColor = 0;
4978 
4979     /**
4980      * Special tree observer used when mAttachInfo is null.
4981      */
4982     private ViewTreeObserver mFloatingTreeObserver;
4983 
4984     /**
4985      * Cache the touch slop from the context that created the view.
4986      */
4987     private int mTouchSlop;
4988 
4989     /**
4990      * Cache the ambiguous gesture multiplier from the context that created the view.
4991      */
4992     private float mAmbiguousGestureMultiplier;
4993 
4994     /**
4995      * Object that handles automatic animation of view properties.
4996      */
4997     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
4998     private ViewPropertyAnimator mAnimator = null;
4999 
5000     /**
5001      * List of registered FrameMetricsObservers.
5002      */
5003     private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
5004 
5005     /**
5006      * Flag indicating that a drag can cross window boundaries.  When
5007      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
5008      * with this flag set, all visible applications with targetSdkVersion >=
5009      * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
5010      * in the drag operation and receive the dragged content.
5011      *
5012      * <p>If this is the only flag set, then the drag recipient will only have access to text data
5013      * and intents contained in the {@link ClipData} object. Access to URIs contained in the
5014      * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p>
5015      */
5016     public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
5017 
5018     /**
5019      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
5020      * request read access to the content URI(s) contained in the {@link ClipData} object.
5021      * @see android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION
5022      */
5023     public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
5024 
5025     /**
5026      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
5027      * request write access to the content URI(s) contained in the {@link ClipData} object.
5028      * @see android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION
5029      */
5030     public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
5031 
5032     /**
5033      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
5034      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
5035      * reboots until explicitly revoked with
5036      * {@link android.content.Context#revokeUriPermission(Uri, int)} Context.revokeUriPermission}.
5037      * @see android.content.Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION
5038      */
5039     public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
5040             Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
5041 
5042     /**
5043      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
5044      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
5045      * match against the original granted URI.
5046      * @see android.content.Intent#FLAG_GRANT_PREFIX_URI_PERMISSION
5047      */
5048     public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
5049             Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
5050 
5051     /**
5052      * Flag indicating that the drag shadow will be opaque.  When
5053      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
5054      * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
5055      */
5056     public static final int DRAG_FLAG_OPAQUE = 1 << 9;
5057 
5058     /**
5059      * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
5060      */
5061     private float mVerticalScrollFactor;
5062 
5063     /**
5064      * Position of the vertical scroll bar.
5065      */
5066     @UnsupportedAppUsage
5067     private int mVerticalScrollbarPosition;
5068 
5069     /**
5070      * Position the scroll bar at the default position as determined by the system.
5071      */
5072     public static final int SCROLLBAR_POSITION_DEFAULT = 0;
5073 
5074     /**
5075      * Position the scroll bar along the left edge.
5076      */
5077     public static final int SCROLLBAR_POSITION_LEFT = 1;
5078 
5079     /**
5080      * Position the scroll bar along the right edge.
5081      */
5082     public static final int SCROLLBAR_POSITION_RIGHT = 2;
5083 
5084     /**
5085      * Indicates that the view does not have a layer.
5086      *
5087      * @see #getLayerType()
5088      * @see #setLayerType(int, android.graphics.Paint)
5089      * @see #LAYER_TYPE_SOFTWARE
5090      * @see #LAYER_TYPE_HARDWARE
5091      */
5092     public static final int LAYER_TYPE_NONE = 0;
5093 
5094     /**
5095      * <p>Indicates that the view has a software layer. A software layer is backed
5096      * by a bitmap and causes the view to be rendered using Android's software
5097      * rendering pipeline, even if hardware acceleration is enabled.</p>
5098      *
5099      * <p>Software layers have various usages:</p>
5100      * <p>When the application is not using hardware acceleration, a software layer
5101      * is useful to apply a specific color filter and/or blending mode and/or
5102      * translucency to a view and all its children.</p>
5103      * <p>When the application is using hardware acceleration, a software layer
5104      * is useful to render drawing primitives not supported by the hardware
5105      * accelerated pipeline. It can also be used to cache a complex view tree
5106      * into a texture and reduce the complexity of drawing operations. For instance,
5107      * when animating a complex view tree with a translation, a software layer can
5108      * be used to render the view tree only once.</p>
5109      * <p>Software layers should be avoided when the affected view tree updates
5110      * often. Every update will require to re-render the software layer, which can
5111      * potentially be slow (particularly when hardware acceleration is turned on
5112      * since the layer will have to be uploaded into a hardware texture after every
5113      * update.)</p>
5114      *
5115      * @see #getLayerType()
5116      * @see #setLayerType(int, android.graphics.Paint)
5117      * @see #LAYER_TYPE_NONE
5118      * @see #LAYER_TYPE_HARDWARE
5119      */
5120     public static final int LAYER_TYPE_SOFTWARE = 1;
5121 
5122     /**
5123      * <p>Indicates that the view has a hardware layer. A hardware layer is backed
5124      * by a hardware specific texture (generally Frame Buffer Objects or FBO on
5125      * OpenGL hardware) and causes the view to be rendered using Android's hardware
5126      * rendering pipeline, but only if hardware acceleration is turned on for the
5127      * view hierarchy. When hardware acceleration is turned off, hardware layers
5128      * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
5129      *
5130      * <p>A hardware layer is useful to apply a specific color filter and/or
5131      * blending mode and/or translucency to a view and all its children.</p>
5132      * <p>A hardware layer can be used to cache a complex view tree into a
5133      * texture and reduce the complexity of drawing operations. For instance,
5134      * when animating a complex view tree with a translation, a hardware layer can
5135      * be used to render the view tree only once.</p>
5136      * <p>A hardware layer can also be used to increase the rendering quality when
5137      * rotation transformations are applied on a view. It can also be used to
5138      * prevent potential clipping issues when applying 3D transforms on a view.</p>
5139      *
5140      * @see #getLayerType()
5141      * @see #setLayerType(int, android.graphics.Paint)
5142      * @see #LAYER_TYPE_NONE
5143      * @see #LAYER_TYPE_SOFTWARE
5144      */
5145     public static final int LAYER_TYPE_HARDWARE = 2;
5146 
5147     /** @hide */
5148     @IntDef(prefix = { "LAYER_TYPE_" }, value = {
5149             LAYER_TYPE_NONE,
5150             LAYER_TYPE_SOFTWARE,
5151             LAYER_TYPE_HARDWARE
5152     })
5153     @Retention(RetentionPolicy.SOURCE)
5154     public @interface LayerType {}
5155 
5156     @ViewDebug.ExportedProperty(category = "drawing", mapping = {
5157             @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
5158             @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
5159             @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
5160     })
5161     int mLayerType = LAYER_TYPE_NONE;
5162     Paint mLayerPaint;
5163 
5164     /**
5165      * Set to true when drawing cache is enabled and cannot be created.
5166      *
5167      * @hide
5168      */
5169     @UnsupportedAppUsage
5170     public boolean mCachingFailed;
5171     @UnsupportedAppUsage
5172     private Bitmap mDrawingCache;
5173     @UnsupportedAppUsage
5174     private Bitmap mUnscaledDrawingCache;
5175 
5176     /**
5177      * RenderNode holding View properties, potentially holding a DisplayList of View content.
5178      * <p>
5179      * When non-null and valid, this is expected to contain an up-to-date copy
5180      * of the View content. Its DisplayList content is cleared on temporary detach and reset on
5181      * cleanup.
5182      */
5183     @UnsupportedAppUsage
5184     final RenderNode mRenderNode;
5185 
5186     /**
5187      * Set to true when the view is sending hover accessibility events because it
5188      * is the innermost hovered view.
5189      */
5190     private boolean mSendingHoverAccessibilityEvents;
5191 
5192     /**
5193      * Delegate for injecting accessibility functionality.
5194      */
5195     @UnsupportedAppUsage
5196     AccessibilityDelegate mAccessibilityDelegate;
5197 
5198     /**
5199      * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
5200      * and add/remove objects to/from the overlay directly through the Overlay methods.
5201      */
5202     ViewOverlay mOverlay;
5203 
5204     /**
5205      * The currently active parent view for receiving delegated nested scrolling events.
5206      * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
5207      * by {@link #stopNestedScroll()} at the same point where we clear
5208      * requestDisallowInterceptTouchEvent.
5209      */
5210     private ViewParent mNestedScrollingParent;
5211 
5212     /**
5213      * Consistency verifier for debugging purposes.
5214      * @hide
5215      */
5216     protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
5217             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
5218                     new InputEventConsistencyVerifier(this, 0) : null;
5219 
5220     private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
5221 
5222     private int[] mTempNestedScrollConsumed;
5223 
5224     /**
5225      * An overlay is going to draw this View instead of being drawn as part of this
5226      * View's parent. mGhostView is the View in the Overlay that must be invalidated
5227      * when this view is invalidated.
5228      */
5229     GhostView mGhostView;
5230 
5231     /**
5232      * Holds pairs of adjacent attribute data: attribute name followed by its value.
5233      * @hide
5234      */
5235     @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
5236     public String[] mAttributes;
5237 
5238     /**
5239      * Maps a Resource id to its name.
5240      */
5241     private static SparseArray<String> mAttributeMap;
5242 
5243     /**
5244      * Queue of pending runnables. Used to postpone calls to post() until this
5245      * view is attached and has a handler.
5246      */
5247     private HandlerActionQueue mRunQueue;
5248 
5249     /**
5250      * The pointer icon when the mouse hovers on this view. The default is null.
5251      */
5252     private PointerIcon mPointerIcon;
5253 
5254     /**
5255      * @hide
5256      */
5257     @UnsupportedAppUsage
5258     String mStartActivityRequestWho;
5259 
5260     @Nullable
5261     private RoundScrollbarRenderer mRoundScrollbarRenderer;
5262 
5263     /** Used to delay visibility updates sent to the autofill manager */
5264     private Handler mVisibilityChangeForAutofillHandler;
5265 
5266     /**
5267      * Used when app developers explicitly set the {@link ContentCaptureSession} associated with the
5268      * view (through {@link #setContentCaptureSession(ContentCaptureSession)}.
5269      */
5270     @Nullable
5271     private ContentCaptureSession mContentCaptureSession;
5272 
5273     /**
5274      * Whether {@link ContentCaptureSession} is cached, resets on {@link #invalidate()}.
5275      */
5276     private boolean mContentCaptureSessionCached;
5277 
5278     @LayoutRes
5279     private int mSourceLayoutId = ID_NULL;
5280 
5281     @Nullable
5282     private SparseIntArray mAttributeSourceResId;
5283 
5284     @Nullable
5285     private SparseArray<int[]> mAttributeResolutionStacks;
5286 
5287     @StyleRes
5288     private int mExplicitStyle;
5289 
5290     /**
5291      * Specifies which input source classes should provide unbuffered input events to this view
5292      *
5293      * @see View#requestUnbufferedDispatch(int)
5294      */
5295     @InputSourceClass
5296     int mUnbufferedInputSource = InputDevice.SOURCE_CLASS_NONE;
5297 
5298     /**
5299      * Simple constructor to use when creating a view from code.
5300      *
5301      * @param context The Context the view is running in, through which it can
5302      *        access the current theme, resources, etc.
5303      */
View(Context context)5304     public View(Context context) {
5305         mContext = context;
5306         mResources = context != null ? context.getResources() : null;
5307         mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | FOCUSABLE_AUTO;
5308         // Set some flags defaults
5309         mPrivateFlags2 =
5310                 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
5311                 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
5312                 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
5313                 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
5314                 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
5315                 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
5316 
5317         final ViewConfiguration configuration = ViewConfiguration.get(context);
5318         mTouchSlop = configuration.getScaledTouchSlop();
5319         mAmbiguousGestureMultiplier = configuration.getScaledAmbiguousGestureMultiplier();
5320 
5321         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
5322         mUserPaddingStart = UNDEFINED_PADDING;
5323         mUserPaddingEnd = UNDEFINED_PADDING;
5324         mRenderNode = RenderNode.create(getClass().getName(), new ViewAnimationHostBridge(this));
5325 
5326         if (!sCompatibilityDone && context != null) {
5327             final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
5328 
5329             // Older apps may need this compatibility hack for measurement.
5330             sUseBrokenMakeMeasureSpec = targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1;
5331 
5332             // Older apps expect onMeasure() to always be called on a layout pass, regardless
5333             // of whether a layout was requested on that View.
5334             sIgnoreMeasureCache = targetSdkVersion < Build.VERSION_CODES.KITKAT;
5335 
5336             Canvas.sCompatibilityRestore = targetSdkVersion < Build.VERSION_CODES.M;
5337             Canvas.sCompatibilitySetBitmap = targetSdkVersion < Build.VERSION_CODES.O;
5338             Canvas.setCompatibilityVersion(targetSdkVersion);
5339 
5340             // In M and newer, our widgets can pass a "hint" value in the size
5341             // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
5342             // know what the expected parent size is going to be, so e.g. list items can size
5343             // themselves at 1/3 the size of their container. It breaks older apps though,
5344             // specifically apps that use some popular open source libraries.
5345             sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < Build.VERSION_CODES.M;
5346 
5347             // Old versions of the platform would give different results from
5348             // LinearLayout measurement passes using EXACTLY and non-EXACTLY
5349             // modes, so we always need to run an additional EXACTLY pass.
5350             sAlwaysRemeasureExactly = targetSdkVersion <= Build.VERSION_CODES.M;
5351 
5352             // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
5353             // On N+, we throw, but that breaks compatibility with apps that use these methods.
5354             sTextureViewIgnoresDrawableSetters = targetSdkVersion <= Build.VERSION_CODES.M;
5355 
5356             // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
5357             // in apps so we target check it to avoid breaking existing apps.
5358             sPreserveMarginParamsInLayoutParamConversion =
5359                     targetSdkVersion >= Build.VERSION_CODES.N;
5360 
5361             sCascadedDragDrop = targetSdkVersion < Build.VERSION_CODES.N;
5362 
5363             sHasFocusableExcludeAutoFocusable = targetSdkVersion < Build.VERSION_CODES.O;
5364 
5365             sAutoFocusableOffUIThreadWontNotifyParents = targetSdkVersion < Build.VERSION_CODES.O;
5366 
5367             sUseDefaultFocusHighlight = context.getResources().getBoolean(
5368                     com.android.internal.R.bool.config_useDefaultFocusHighlight);
5369 
5370             sThrowOnInvalidFloatProperties = targetSdkVersion >= Build.VERSION_CODES.P;
5371 
5372             sCanFocusZeroSized = targetSdkVersion < Build.VERSION_CODES.P;
5373 
5374             sAlwaysAssignFocus = targetSdkVersion < Build.VERSION_CODES.P;
5375 
5376             sAcceptZeroSizeDragShadow = targetSdkVersion < Build.VERSION_CODES.P;
5377 
5378             sBrokenInsetsDispatch = ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_FULL
5379                     || targetSdkVersion < Build.VERSION_CODES.R;
5380 
5381             sBrokenWindowBackground = targetSdkVersion < Build.VERSION_CODES.Q;
5382 
5383             GradientDrawable.sWrapNegativeAngleMeasurements =
5384                     targetSdkVersion >= Build.VERSION_CODES.Q;
5385 
5386             sForceLayoutWhenInsetsChanged = targetSdkVersion < Build.VERSION_CODES.R;
5387 
5388             sCompatibilityDone = true;
5389         }
5390     }
5391 
5392     /**
5393      * Constructor that is called when inflating a view from XML. This is called
5394      * when a view is being constructed from an XML file, supplying attributes
5395      * that were specified in the XML file. This version uses a default style of
5396      * 0, so the only attribute values applied are those in the Context's Theme
5397      * and the given AttributeSet.
5398      *
5399      * <p>
5400      * The method onFinishInflate() will be called after all children have been
5401      * added.
5402      *
5403      * @param context The Context the view is running in, through which it can
5404      *        access the current theme, resources, etc.
5405      * @param attrs The attributes of the XML tag that is inflating the view.
5406      * @see #View(Context, AttributeSet, int)
5407      */
5408     public View(Context context, @Nullable AttributeSet attrs) {
5409         this(context, attrs, 0);
5410     }
5411 
5412     /**
5413      * Perform inflation from XML and apply a class-specific base style from a
5414      * theme attribute. This constructor of View allows subclasses to use their
5415      * own base style when they are inflating. For example, a Button class's
5416      * constructor would call this version of the super class constructor and
5417      * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
5418      * allows the theme's button style to modify all of the base view attributes
5419      * (in particular its background) as well as the Button class's attributes.
5420      *
5421      * @param context The Context the view is running in, through which it can
5422      *        access the current theme, resources, etc.
5423      * @param attrs The attributes of the XML tag that is inflating the view.
5424      * @param defStyleAttr An attribute in the current theme that contains a
5425      *        reference to a style resource that supplies default values for
5426      *        the view. Can be 0 to not look for defaults.
5427      * @see #View(Context, AttributeSet)
5428      */
5429     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
5430         this(context, attrs, defStyleAttr, 0);
5431     }
5432 
5433     /**
5434      * Perform inflation from XML and apply a class-specific base style from a
5435      * theme attribute or style resource. This constructor of View allows
5436      * subclasses to use their own base style when they are inflating.
5437      * <p>
5438      * When determining the final value of a particular attribute, there are
5439      * four inputs that come into play:
5440      * <ol>
5441      * <li>Any attribute values in the given AttributeSet.
5442      * <li>The style resource specified in the AttributeSet (named "style").
5443      * <li>The default style specified by <var>defStyleAttr</var>.
5444      * <li>The default style specified by <var>defStyleRes</var>.
5445      * <li>The base values in this theme.
5446      * </ol>
5447      * <p>
5448      * Each of these inputs is considered in-order, with the first listed taking
5449      * precedence over the following ones. In other words, if in the
5450      * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
5451      * , then the button's text will <em>always</em> be black, regardless of
5452      * what is specified in any of the styles.
5453      *
5454      * @param context The Context the view is running in, through which it can
5455      *        access the current theme, resources, etc.
5456      * @param attrs The attributes of the XML tag that is inflating the view.
5457      * @param defStyleAttr An attribute in the current theme that contains a
5458      *        reference to a style resource that supplies default values for
5459      *        the view. Can be 0 to not look for defaults.
5460      * @param defStyleRes A resource identifier of a style resource that
5461      *        supplies default values for the view, used only if
5462      *        defStyleAttr is 0 or can not be found in the theme. Can be 0
5463      *        to not look for defaults.
5464      * @see #View(Context, AttributeSet, int)
5465      */
5466     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
5467         this(context);
5468 
5469         mSourceLayoutId = Resources.getAttributeSetSourceResId(attrs);
5470 
5471         final TypedArray a = context.obtainStyledAttributes(
5472                 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
5473 
5474         retrieveExplicitStyle(context.getTheme(), attrs);
5475         saveAttributeDataForStyleable(context, com.android.internal.R.styleable.View, attrs, a,
5476                 defStyleAttr, defStyleRes);
5477 
5478         if (sDebugViewAttributes) {
5479             saveAttributeData(attrs, a);
5480         }
5481 
5482         Drawable background = null;
5483 
5484         int leftPadding = -1;
5485         int topPadding = -1;
5486         int rightPadding = -1;
5487         int bottomPadding = -1;
5488         int startPadding = UNDEFINED_PADDING;
5489         int endPadding = UNDEFINED_PADDING;
5490 
5491         int padding = -1;
5492         int paddingHorizontal = -1;
5493         int paddingVertical = -1;
5494 
5495         int viewFlagValues = 0;
5496         int viewFlagMasks = 0;
5497 
5498         boolean setScrollContainer = false;
5499 
5500         int x = 0;
5501         int y = 0;
5502 
5503         float tx = 0;
5504         float ty = 0;
5505         float tz = 0;
5506         float elevation = 0;
5507         float rotation = 0;
5508         float rotationX = 0;
5509         float rotationY = 0;
5510         float sx = 1f;
5511         float sy = 1f;
5512         boolean transformSet = false;
5513 
5514         int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
5515         int overScrollMode = mOverScrollMode;
5516         boolean initializeScrollbars = false;
5517         boolean initializeScrollIndicators = false;
5518 
5519         boolean startPaddingDefined = false;
5520         boolean endPaddingDefined = false;
5521         boolean leftPaddingDefined = false;
5522         boolean rightPaddingDefined = false;
5523 
5524         final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
5525 
5526         // Set default values.
5527         viewFlagValues |= FOCUSABLE_AUTO;
5528         viewFlagMasks |= FOCUSABLE_AUTO;
5529 
5530         final int N = a.getIndexCount();
5531         for (int i = 0; i < N; i++) {
5532             int attr = a.getIndex(i);
5533             switch (attr) {
5534                 case com.android.internal.R.styleable.View_background:
5535                     background = a.getDrawable(attr);
5536                     break;
5537                 case com.android.internal.R.styleable.View_padding:
5538                     padding = a.getDimensionPixelSize(attr, -1);
5539                     mUserPaddingLeftInitial = padding;
5540                     mUserPaddingRightInitial = padding;
5541                     leftPaddingDefined = true;
5542                     rightPaddingDefined = true;
5543                     break;
5544                 case com.android.internal.R.styleable.View_paddingHorizontal:
5545                     paddingHorizontal = a.getDimensionPixelSize(attr, -1);
5546                     mUserPaddingLeftInitial = paddingHorizontal;
5547                     mUserPaddingRightInitial = paddingHorizontal;
5548                     leftPaddingDefined = true;
5549                     rightPaddingDefined = true;
5550                     break;
5551                 case com.android.internal.R.styleable.View_paddingVertical:
5552                     paddingVertical = a.getDimensionPixelSize(attr, -1);
5553                     break;
5554                 case com.android.internal.R.styleable.View_paddingLeft:
5555                     leftPadding = a.getDimensionPixelSize(attr, -1);
5556                     mUserPaddingLeftInitial = leftPadding;
5557                     leftPaddingDefined = true;
5558                     break;
5559                 case com.android.internal.R.styleable.View_paddingTop:
5560                     topPadding = a.getDimensionPixelSize(attr, -1);
5561                     break;
5562                 case com.android.internal.R.styleable.View_paddingRight:
5563                     rightPadding = a.getDimensionPixelSize(attr, -1);
5564                     mUserPaddingRightInitial = rightPadding;
5565                     rightPaddingDefined = true;
5566                     break;
5567                 case com.android.internal.R.styleable.View_paddingBottom:
5568                     bottomPadding = a.getDimensionPixelSize(attr, -1);
5569                     break;
5570                 case com.android.internal.R.styleable.View_paddingStart:
5571                     startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
5572                     startPaddingDefined = (startPadding != UNDEFINED_PADDING);
5573                     break;
5574                 case com.android.internal.R.styleable.View_paddingEnd:
5575                     endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
5576                     endPaddingDefined = (endPadding != UNDEFINED_PADDING);
5577                     break;
5578                 case com.android.internal.R.styleable.View_scrollX:
5579                     x = a.getDimensionPixelOffset(attr, 0);
5580                     break;
5581                 case com.android.internal.R.styleable.View_scrollY:
5582                     y = a.getDimensionPixelOffset(attr, 0);
5583                     break;
5584                 case com.android.internal.R.styleable.View_alpha:
5585                     setAlpha(a.getFloat(attr, 1f));
5586                     break;
5587                 case com.android.internal.R.styleable.View_transformPivotX:
5588                     setPivotX(a.getDimension(attr, 0));
5589                     break;
5590                 case com.android.internal.R.styleable.View_transformPivotY:
5591                     setPivotY(a.getDimension(attr, 0));
5592                     break;
5593                 case com.android.internal.R.styleable.View_translationX:
5594                     tx = a.getDimension(attr, 0);
5595                     transformSet = true;
5596                     break;
5597                 case com.android.internal.R.styleable.View_translationY:
5598                     ty = a.getDimension(attr, 0);
5599                     transformSet = true;
5600                     break;
5601                 case com.android.internal.R.styleable.View_translationZ:
5602                     tz = a.getDimension(attr, 0);
5603                     transformSet = true;
5604                     break;
5605                 case com.android.internal.R.styleable.View_elevation:
5606                     elevation = a.getDimension(attr, 0);
5607                     transformSet = true;
5608                     break;
5609                 case com.android.internal.R.styleable.View_rotation:
5610                     rotation = a.getFloat(attr, 0);
5611                     transformSet = true;
5612                     break;
5613                 case com.android.internal.R.styleable.View_rotationX:
5614                     rotationX = a.getFloat(attr, 0);
5615                     transformSet = true;
5616                     break;
5617                 case com.android.internal.R.styleable.View_rotationY:
5618                     rotationY = a.getFloat(attr, 0);
5619                     transformSet = true;
5620                     break;
5621                 case com.android.internal.R.styleable.View_scaleX:
5622                     sx = a.getFloat(attr, 1f);
5623                     transformSet = true;
5624                     break;
5625                 case com.android.internal.R.styleable.View_scaleY:
5626                     sy = a.getFloat(attr, 1f);
5627                     transformSet = true;
5628                     break;
5629                 case com.android.internal.R.styleable.View_id:
5630                     mID = a.getResourceId(attr, NO_ID);
5631                     break;
5632                 case com.android.internal.R.styleable.View_tag:
5633                     mTag = a.getText(attr);
5634                     break;
5635                 case com.android.internal.R.styleable.View_fitsSystemWindows:
5636                     if (a.getBoolean(attr, false)) {
5637                         viewFlagValues |= FITS_SYSTEM_WINDOWS;
5638                         viewFlagMasks |= FITS_SYSTEM_WINDOWS;
5639                     }
5640                     break;
5641                 case com.android.internal.R.styleable.View_focusable:
5642                     viewFlagValues = (viewFlagValues & ~FOCUSABLE_MASK) | getFocusableAttribute(a);
5643                     if ((viewFlagValues & FOCUSABLE_AUTO) == 0) {
5644                         viewFlagMasks |= FOCUSABLE_MASK;
5645                     }
5646                     break;
5647                 case com.android.internal.R.styleable.View_focusableInTouchMode:
5648                     if (a.getBoolean(attr, false)) {
5649                         // unset auto focus since focusableInTouchMode implies explicit focusable
5650                         viewFlagValues &= ~FOCUSABLE_AUTO;
5651                         viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
5652                         viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
5653                     }
5654                     break;
5655                 case com.android.internal.R.styleable.View_clickable:
5656                     if (a.getBoolean(attr, false)) {
5657                         viewFlagValues |= CLICKABLE;
5658                         viewFlagMasks |= CLICKABLE;
5659                     }
5660                     break;
5661                 case com.android.internal.R.styleable.View_longClickable:
5662                     if (a.getBoolean(attr, false)) {
5663                         viewFlagValues |= LONG_CLICKABLE;
5664                         viewFlagMasks |= LONG_CLICKABLE;
5665                     }
5666                     break;
5667                 case com.android.internal.R.styleable.View_contextClickable:
5668                     if (a.getBoolean(attr, false)) {
5669                         viewFlagValues |= CONTEXT_CLICKABLE;
5670                         viewFlagMasks |= CONTEXT_CLICKABLE;
5671                     }
5672                     break;
5673                 case com.android.internal.R.styleable.View_saveEnabled:
5674                     if (!a.getBoolean(attr, true)) {
5675                         viewFlagValues |= SAVE_DISABLED;
5676                         viewFlagMasks |= SAVE_DISABLED_MASK;
5677                     }
5678                     break;
5679                 case com.android.internal.R.styleable.View_duplicateParentState:
5680                     if (a.getBoolean(attr, false)) {
5681                         viewFlagValues |= DUPLICATE_PARENT_STATE;
5682                         viewFlagMasks |= DUPLICATE_PARENT_STATE;
5683                     }
5684                     break;
5685                 case com.android.internal.R.styleable.View_visibility:
5686                     final int visibility = a.getInt(attr, 0);
5687                     if (visibility != 0) {
5688                         viewFlagValues |= VISIBILITY_FLAGS[visibility];
5689                         viewFlagMasks |= VISIBILITY_MASK;
5690                     }
5691                     break;
5692                 case com.android.internal.R.styleable.View_layoutDirection:
5693                     // Clear any layout direction flags (included resolved bits) already set
5694                     mPrivateFlags2 &=
5695                             ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
5696                     // Set the layout direction flags depending on the value of the attribute
5697                     final int layoutDirection = a.getInt(attr, -1);
5698                     final int value = (layoutDirection != -1) ?
5699                             LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
5700                     mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
5701                     break;
5702                 case com.android.internal.R.styleable.View_drawingCacheQuality:
5703                     final int cacheQuality = a.getInt(attr, 0);
5704                     if (cacheQuality != 0) {
5705                         viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
5706                         viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
5707                     }
5708                     break;
5709                 case com.android.internal.R.styleable.View_contentDescription:
5710                     setContentDescription(a.getString(attr));
5711                     break;
5712                 case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
5713                     setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
5714                     break;
5715                 case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
5716                     setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
5717                     break;
5718                 case com.android.internal.R.styleable.View_labelFor:
5719                     setLabelFor(a.getResourceId(attr, NO_ID));
5720                     break;
5721                 case com.android.internal.R.styleable.View_soundEffectsEnabled:
5722                     if (!a.getBoolean(attr, true)) {
5723                         viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
5724                         viewFlagMasks |= SOUND_EFFECTS_ENABLED;
5725                     }
5726                     break;
5727                 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
5728                     if (!a.getBoolean(attr, true)) {
5729                         viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
5730                         viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
5731                     }
5732                     break;
5733                 case R.styleable.View_scrollbars:
5734                     final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
5735                     if (scrollbars != SCROLLBARS_NONE) {
5736                         viewFlagValues |= scrollbars;
5737                         viewFlagMasks |= SCROLLBARS_MASK;
5738                         initializeScrollbars = true;
5739                     }
5740                     break;
5741                 //noinspection deprecation
5742                 case R.styleable.View_fadingEdge:
5743                     if (targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
5744                         // Ignore the attribute starting with ICS
5745                         break;
5746                     }
5747                     // With builds < ICS, fall through and apply fading edges
5748                 case R.styleable.View_requiresFadingEdge:
5749                     final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
5750                     if (fadingEdge != FADING_EDGE_NONE) {
5751                         viewFlagValues |= fadingEdge;
5752                         viewFlagMasks |= FADING_EDGE_MASK;
5753                         initializeFadingEdgeInternal(a);
5754                     }
5755                     break;
5756                 case R.styleable.View_scrollbarStyle:
5757                     scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
5758                     if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
5759                         viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
5760                         viewFlagMasks |= SCROLLBARS_STYLE_MASK;
5761                     }
5762                     break;
5763                 case R.styleable.View_isScrollContainer:
5764                     setScrollContainer = true;
5765                     if (a.getBoolean(attr, false)) {
5766                         setScrollContainer(true);
5767                     }
5768                     break;
5769                 case com.android.internal.R.styleable.View_keepScreenOn:
5770                     if (a.getBoolean(attr, false)) {
5771                         viewFlagValues |= KEEP_SCREEN_ON;
5772                         viewFlagMasks |= KEEP_SCREEN_ON;
5773                     }
5774                     break;
5775                 case R.styleable.View_filterTouchesWhenObscured:
5776                     if (a.getBoolean(attr, false)) {
5777                         viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
5778                         viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
5779                     }
5780                     break;
5781                 case R.styleable.View_nextFocusLeft:
5782                     mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
5783                     break;
5784                 case R.styleable.View_nextFocusRight:
5785                     mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
5786                     break;
5787                 case R.styleable.View_nextFocusUp:
5788                     mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
5789                     break;
5790                 case R.styleable.View_nextFocusDown:
5791                     mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
5792                     break;
5793                 case R.styleable.View_nextFocusForward:
5794                     mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
5795                     break;
5796                 case R.styleable.View_nextClusterForward:
5797                     mNextClusterForwardId = a.getResourceId(attr, View.NO_ID);
5798                     break;
5799                 case R.styleable.View_minWidth:
5800                     mMinWidth = a.getDimensionPixelSize(attr, 0);
5801                     break;
5802                 case R.styleable.View_minHeight:
5803                     mMinHeight = a.getDimensionPixelSize(attr, 0);
5804                     break;
5805                 case R.styleable.View_onClick:
5806                     if (context.isRestricted()) {
5807                         throw new IllegalStateException("The android:onClick attribute cannot "
5808                                 + "be used within a restricted context");
5809                     }
5810 
5811                     final String handlerName = a.getString(attr);
5812                     if (handlerName != null) {
5813                         setOnClickListener(new DeclaredOnClickListener(this, handlerName));
5814                     }
5815                     break;
5816                 case R.styleable.View_overScrollMode:
5817                     overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
5818                     break;
5819                 case R.styleable.View_verticalScrollbarPosition:
5820                     mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
5821                     break;
5822                 case R.styleable.View_layerType:
5823                     setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
5824                     break;
5825                 case R.styleable.View_textDirection:
5826                     // Clear any text direction flag already set
5827                     mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
5828                     // Set the text direction flags depending on the value of the attribute
5829                     final int textDirection = a.getInt(attr, -1);
5830                     if (textDirection != -1) {
5831                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
5832                     }
5833                     break;
5834                 case R.styleable.View_textAlignment:
5835                     // Clear any text alignment flag already set
5836                     mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
5837                     // Set the text alignment flag depending on the value of the attribute
5838                     final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
5839                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
5840                     break;
5841                 case R.styleable.View_importantForAccessibility:
5842                     setImportantForAccessibility(a.getInt(attr,
5843                             IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
5844                     break;
5845                 case R.styleable.View_accessibilityLiveRegion:
5846                     setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
5847                     break;
5848                 case R.styleable.View_transitionName:
5849                     setTransitionName(a.getString(attr));
5850                     break;
5851                 case R.styleable.View_nestedScrollingEnabled:
5852                     setNestedScrollingEnabled(a.getBoolean(attr, false));
5853                     break;
5854                 case R.styleable.View_stateListAnimator:
5855                     setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
5856                             a.getResourceId(attr, 0)));
5857                     break;
5858                 case R.styleable.View_backgroundTint:
5859                     // This will get applied later during setBackground().
5860                     if (mBackgroundTint == null) {
5861                         mBackgroundTint = new TintInfo();
5862                     }
5863                     mBackgroundTint.mTintList = a.getColorStateList(
5864                             R.styleable.View_backgroundTint);
5865                     mBackgroundTint.mHasTintList = true;
5866                     break;
5867                 case R.styleable.View_backgroundTintMode:
5868                     // This will get applied later during setBackground().
5869                     if (mBackgroundTint == null) {
5870                         mBackgroundTint = new TintInfo();
5871                     }
5872                     mBackgroundTint.mBlendMode = Drawable.parseBlendMode(a.getInt(
5873                             R.styleable.View_backgroundTintMode, -1), null);
5874                     mBackgroundTint.mHasTintMode = true;
5875                     break;
5876                 case R.styleable.View_outlineProvider:
5877                     setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
5878                             PROVIDER_BACKGROUND));
5879                     break;
5880                 case R.styleable.View_foreground:
5881                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5882                         setForeground(a.getDrawable(attr));
5883                     }
5884                     break;
5885                 case R.styleable.View_foregroundGravity:
5886                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5887                         setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
5888                     }
5889                     break;
5890                 case R.styleable.View_foregroundTintMode:
5891                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5892                         setForegroundTintBlendMode(
5893                                 Drawable.parseBlendMode(a.getInt(attr, -1),
5894                                         null));
5895                     }
5896                     break;
5897                 case R.styleable.View_foregroundTint:
5898                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5899                         setForegroundTintList(a.getColorStateList(attr));
5900                     }
5901                     break;
5902                 case R.styleable.View_foregroundInsidePadding:
5903                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5904                         if (mForegroundInfo == null) {
5905                             mForegroundInfo = new ForegroundInfo();
5906                         }
5907                         mForegroundInfo.mInsidePadding = a.getBoolean(attr,
5908                                 mForegroundInfo.mInsidePadding);
5909                     }
5910                     break;
5911                 case R.styleable.View_scrollIndicators:
5912                     final int scrollIndicators =
5913                             (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
5914                                     & SCROLL_INDICATORS_PFLAG3_MASK;
5915                     if (scrollIndicators != 0) {
5916                         mPrivateFlags3 |= scrollIndicators;
5917                         initializeScrollIndicators = true;
5918                     }
5919                     break;
5920                 case R.styleable.View_pointerIcon:
5921                     final int resourceId = a.getResourceId(attr, 0);
5922                     if (resourceId != 0) {
5923                         setPointerIcon(PointerIcon.load(
5924                                 context.getResources(), resourceId));
5925                     } else {
5926                         final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
5927                         if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
5928                             setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
5929                         }
5930                     }
5931                     break;
5932                 case R.styleable.View_forceHasOverlappingRendering:
5933                     if (a.peekValue(attr) != null) {
5934                         forceHasOverlappingRendering(a.getBoolean(attr, true));
5935                     }
5936                     break;
5937                 case R.styleable.View_tooltipText:
5938                     setTooltipText(a.getText(attr));
5939                     break;
5940                 case R.styleable.View_keyboardNavigationCluster:
5941                     if (a.peekValue(attr) != null) {
5942                         setKeyboardNavigationCluster(a.getBoolean(attr, true));
5943                     }
5944                     break;
5945                 case R.styleable.View_focusedByDefault:
5946                     if (a.peekValue(attr) != null) {
5947                         setFocusedByDefault(a.getBoolean(attr, true));
5948                     }
5949                     break;
5950                 case R.styleable.View_autofillHints:
5951                     if (a.peekValue(attr) != null) {
5952                         CharSequence[] rawHints = null;
5953                         String rawString = null;
5954 
5955                         if (a.getType(attr) == TypedValue.TYPE_REFERENCE) {
5956                             int resId = a.getResourceId(attr, 0);
5957 
5958                             try {
5959                                 rawHints = a.getTextArray(attr);
5960                             } catch (Resources.NotFoundException e) {
5961                                 rawString = getResources().getString(resId);
5962                             }
5963                         } else {
5964                             rawString = a.getString(attr);
5965                         }
5966 
5967                         if (rawHints == null) {
5968                             if (rawString == null) {
5969                                 throw new IllegalArgumentException(
5970                                         "Could not resolve autofillHints");
5971                             } else {
5972                                 rawHints = rawString.split(",");
5973                             }
5974                         }
5975 
5976                         String[] hints = new String[rawHints.length];
5977 
5978                         int numHints = rawHints.length;
5979                         for (int rawHintNum = 0; rawHintNum < numHints; rawHintNum++) {
5980                             hints[rawHintNum] = rawHints[rawHintNum].toString().trim();
5981                         }
5982                         setAutofillHints(hints);
5983                     }
5984                     break;
5985                 case R.styleable.View_importantForAutofill:
5986                     if (a.peekValue(attr) != null) {
5987                         setImportantForAutofill(a.getInt(attr, IMPORTANT_FOR_AUTOFILL_AUTO));
5988                     }
5989                     break;
5990                 case R.styleable.View_importantForContentCapture:
5991                     if (a.peekValue(attr) != null) {
5992                         setImportantForContentCapture(a.getInt(attr,
5993                                 IMPORTANT_FOR_CONTENT_CAPTURE_AUTO));
5994                     }
5995                 case R.styleable.View_defaultFocusHighlightEnabled:
5996                     if (a.peekValue(attr) != null) {
5997                         setDefaultFocusHighlightEnabled(a.getBoolean(attr, true));
5998                     }
5999                     break;
6000                 case R.styleable.View_screenReaderFocusable:
6001                     if (a.peekValue(attr) != null) {
6002                         setScreenReaderFocusable(a.getBoolean(attr, false));
6003                     }
6004                     break;
6005                 case R.styleable.View_accessibilityPaneTitle:
6006                     if (a.peekValue(attr) != null) {
6007                         setAccessibilityPaneTitle(a.getString(attr));
6008                     }
6009                     break;
6010                 case R.styleable.View_outlineSpotShadowColor:
6011                     setOutlineSpotShadowColor(a.getColor(attr, Color.BLACK));
6012                     break;
6013                 case R.styleable.View_outlineAmbientShadowColor:
6014                     setOutlineAmbientShadowColor(a.getColor(attr, Color.BLACK));
6015                     break;
6016                 case com.android.internal.R.styleable.View_accessibilityHeading:
6017                     setAccessibilityHeading(a.getBoolean(attr, false));
6018                     break;
6019                 case R.styleable.View_forceDarkAllowed:
6020                     mRenderNode.setForceDarkAllowed(a.getBoolean(attr, true));
6021                     break;
6022                 case R.styleable.View_scrollCaptureHint:
6023                     setScrollCaptureHint((a.getInt(attr, SCROLL_CAPTURE_HINT_AUTO)));
6024                     break;
6025             }
6026         }
6027 
6028         setOverScrollMode(overScrollMode);
6029 
6030         // Cache start/end user padding as we cannot fully resolve padding here (we don't have yet
6031         // the resolved layout direction). Those cached values will be used later during padding
6032         // resolution.
6033         mUserPaddingStart = startPadding;
6034         mUserPaddingEnd = endPadding;
6035 
6036         if (background != null) {
6037             setBackground(background);
6038         }
6039 
6040         // setBackground above will record that padding is currently provided by the background.
6041         // If we have padding specified via xml, record that here instead and use it.
6042         mLeftPaddingDefined = leftPaddingDefined;
6043         mRightPaddingDefined = rightPaddingDefined;
6044 
6045         // Valid paddingHorizontal/paddingVertical beats leftPadding, rightPadding, topPadding,
6046         // bottomPadding, and padding set by background.  Valid padding beats everything.
6047         if (padding >= 0) {
6048             leftPadding = padding;
6049             topPadding = padding;
6050             rightPadding = padding;
6051             bottomPadding = padding;
6052             mUserPaddingLeftInitial = padding;
6053             mUserPaddingRightInitial = padding;
6054         } else {
6055             if (paddingHorizontal >= 0) {
6056                 leftPadding = paddingHorizontal;
6057                 rightPadding = paddingHorizontal;
6058                 mUserPaddingLeftInitial = paddingHorizontal;
6059                 mUserPaddingRightInitial = paddingHorizontal;
6060             }
6061             if (paddingVertical >= 0) {
6062                 topPadding = paddingVertical;
6063                 bottomPadding = paddingVertical;
6064             }
6065         }
6066 
6067         if (isRtlCompatibilityMode()) {
6068             // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
6069             // left / right padding are used if defined (meaning here nothing to do). If they are not
6070             // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
6071             // start / end and resolve them as left / right (layout direction is not taken into account).
6072             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
6073             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
6074             // defined.
6075             if (!mLeftPaddingDefined && startPaddingDefined) {
6076                 leftPadding = startPadding;
6077             }
6078             mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
6079             if (!mRightPaddingDefined && endPaddingDefined) {
6080                 rightPadding = endPadding;
6081             }
6082             mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
6083         } else {
6084             // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
6085             // values defined. Otherwise, left /right values are used.
6086             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
6087             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
6088             // defined.
6089             final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
6090 
6091             if (mLeftPaddingDefined && !hasRelativePadding) {
6092                 mUserPaddingLeftInitial = leftPadding;
6093             }
6094             if (mRightPaddingDefined && !hasRelativePadding) {
6095                 mUserPaddingRightInitial = rightPadding;
6096             }
6097         }
6098 
6099         // mPaddingTop and mPaddingBottom may have been set by setBackground(Drawable) so must pass
6100         // them on if topPadding or bottomPadding are not valid.
6101         internalSetPadding(
6102                 mUserPaddingLeftInitial,
6103                 topPadding >= 0 ? topPadding : mPaddingTop,
6104                 mUserPaddingRightInitial,
6105                 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
6106 
6107         if (viewFlagMasks != 0) {
6108             setFlags(viewFlagValues, viewFlagMasks);
6109         }
6110 
6111         if (initializeScrollbars) {
6112             initializeScrollbarsInternal(a);
6113         }
6114 
6115         if (initializeScrollIndicators) {
6116             initializeScrollIndicatorsInternal();
6117         }
6118 
6119         a.recycle();
6120 
6121         // Needs to be called after mViewFlags is set
6122         if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
6123             recomputePadding();
6124         }
6125 
6126         if (x != 0 || y != 0) {
6127             scrollTo(x, y);
6128         }
6129 
6130         if (transformSet) {
6131             setTranslationX(tx);
6132             setTranslationY(ty);
6133             setTranslationZ(tz);
6134             setElevation(elevation);
6135             setRotation(rotation);
6136             setRotationX(rotationX);
6137             setRotationY(rotationY);
6138             setScaleX(sx);
6139             setScaleY(sy);
6140         }
6141 
6142         if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
6143             setScrollContainer(true);
6144         }
6145 
6146         computeOpaqueFlags();
6147     }
6148 
6149     /**
6150      * Returns the ordered list of resource ID that are considered when resolving attribute values
6151      * for this {@link View}. The list will include layout resource ID if the View is inflated from
6152      * XML. It will also include a set of explicit styles if specified in XML using
6153      * {@code style="..."}. Finally, it will include the default styles resolved from the theme.
6154      *
6155      * <p>
6156      * <b>Note:</b> this method will only return actual values if the view attribute debugging
6157      * is enabled in Android developer options.
6158      *
6159      * @param attribute Attribute resource ID for which the resolution stack should be returned.
6160      * @return ordered list of resource ID that are considered when resolving attribute values for
6161      * this {@link View}.
6162      */
6163     @NonNull
6164     public int[] getAttributeResolutionStack(@AttrRes int attribute) {
6165         if (!sDebugViewAttributes
6166                 || mAttributeResolutionStacks == null
6167                 || mAttributeResolutionStacks.get(attribute) == null) {
6168             return new int[0];
6169         }
6170         int[] attributeResolutionStack = mAttributeResolutionStacks.get(attribute);
6171         int stackSize = attributeResolutionStack.length;
6172         if (mSourceLayoutId != ID_NULL) {
6173             stackSize++;
6174         }
6175 
6176         int currentIndex = 0;
6177         int[] stack = new int[stackSize];
6178 
6179         if (mSourceLayoutId != ID_NULL) {
6180             stack[currentIndex] = mSourceLayoutId;
6181             currentIndex++;
6182         }
6183         for (int i = 0; i < attributeResolutionStack.length; i++) {
6184             stack[currentIndex] = attributeResolutionStack[i];
6185             currentIndex++;
6186         }
6187         return stack;
6188     }
6189 
6190     /**
6191      * Returns the mapping of attribute resource ID to source resource ID where the attribute value
6192      * was set. Source resource ID can either be a layout resource ID, if the value was set in XML
6193      * within the View tag, or a style resource ID, if the attribute was set in a style. The source
6194      * resource value will be one of the resource IDs from {@link #getAttributeSourceResourceMap()}.
6195      *
6196      * <p>
6197      * <b>Note:</b> this method will only return actual values if the view attribute debugging
6198      * is enabled in Android developer options.
6199      *
6200      * @return mapping of attribute resource ID to source resource ID where the attribute value
6201      * was set.
6202      */
6203     @NonNull
6204     public Map<Integer, Integer> getAttributeSourceResourceMap() {
6205         HashMap<Integer, Integer> map = new HashMap<>();
6206         if (!sDebugViewAttributes || mAttributeSourceResId == null) {
6207             return map;
6208         }
6209         for (int i = 0; i < mAttributeSourceResId.size(); i++) {
6210             map.put(mAttributeSourceResId.keyAt(i), mAttributeSourceResId.valueAt(i));
6211         }
6212         return map;
6213     }
6214 
6215     /**
6216      * Returns the resource ID for the style specified using {@code style="..."} in the
6217      * {@link AttributeSet}'s backing XML element or {@link Resources#ID_NULL} otherwise if not
6218      * specified or otherwise not applicable.
6219      * <p>
6220      * Each {@link View} can have an explicit style specified in the layout file.
6221      * This style is used first during the {@link View} attribute resolution, then if an attribute
6222      * is not defined there the resource system looks at default style and theme as fallbacks.
6223      *
6224      * <p>
6225      * <b>Note:</b> this method will only return actual values if the view attribute debugging
6226      * is enabled in Android developer options.
6227      *
6228      * @return The resource ID for the style specified using {@code style="..."} in the
6229      *      {@link AttributeSet}'s backing XML element or {@link Resources#ID_NULL} otherwise
6230      *      if not specified or otherwise not applicable.
6231      */
6232     @StyleRes
6233     public int getExplicitStyle() {
6234         if (!sDebugViewAttributes) {
6235             return ID_NULL;
6236         }
6237         return mExplicitStyle;
6238     }
6239 
6240     /**
6241      * An implementation of OnClickListener that attempts to lazily load a
6242      * named click handling method from a parent or ancestor context.
6243      */
6244     private static class DeclaredOnClickListener implements OnClickListener {
6245         private final View mHostView;
6246         private final String mMethodName;
6247 
6248         private Method mResolvedMethod;
6249         private Context mResolvedContext;
6250 
6251         public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
6252             mHostView = hostView;
6253             mMethodName = methodName;
6254         }
6255 
6256         @Override
6257         public void onClick(@NonNull View v) {
6258             if (mResolvedMethod == null) {
6259                 resolveMethod(mHostView.getContext(), mMethodName);
6260             }
6261 
6262             try {
6263                 mResolvedMethod.invoke(mResolvedContext, v);
6264             } catch (IllegalAccessException e) {
6265                 throw new IllegalStateException(
6266                         "Could not execute non-public method for android:onClick", e);
6267             } catch (InvocationTargetException e) {
6268                 throw new IllegalStateException(
6269                         "Could not execute method for android:onClick", e);
6270             }
6271         }
6272 
6273         @NonNull
6274         private void resolveMethod(@Nullable Context context, @NonNull String name) {
6275             while (context != null) {
6276                 try {
6277                     if (!context.isRestricted()) {
6278                         final Method method = context.getClass().getMethod(mMethodName, View.class);
6279                         if (method != null) {
6280                             mResolvedMethod = method;
6281                             mResolvedContext = context;
6282                             return;
6283                         }
6284                     }
6285                 } catch (NoSuchMethodException e) {
6286                     // Failed to find method, keep searching up the hierarchy.
6287                 }
6288 
6289                 if (context instanceof ContextWrapper) {
6290                     context = ((ContextWrapper) context).getBaseContext();
6291                 } else {
6292                     // Can't search up the hierarchy, null out and fail.
6293                     context = null;
6294                 }
6295             }
6296 
6297             final int id = mHostView.getId();
6298             final String idText = id == NO_ID ? "" : " with id '"
6299                     + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
6300             throw new IllegalStateException("Could not find method " + mMethodName
6301                     + "(View) in a parent or ancestor Context for android:onClick "
6302                     + "attribute defined on view " + mHostView.getClass() + idText);
6303         }
6304     }
6305 
6306     /**
6307      * Non-public constructor for use in testing
6308      */
6309     @UnsupportedAppUsage
6310     View() {
6311         mResources = null;
6312         mRenderNode = RenderNode.create(getClass().getName(), new ViewAnimationHostBridge(this));
6313     }
6314 
6315     /**
6316      * Returns {@code true} when the View is attached and the system developer setting to show
6317      * the layout bounds is enabled or {@code false} otherwise.
6318      */
6319     public final boolean isShowingLayoutBounds() {
6320         return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
6321     }
6322 
6323     /**
6324      * Used to test isShowingLayoutBounds(). This sets the local value used
6325      * by that function. This method does nothing if the layout isn't attached.
6326      *
6327      * @hide
6328      */
6329     @TestApi
6330     public final void setShowingLayoutBounds(boolean debugLayout) {
6331         if (mAttachInfo != null) {
6332             mAttachInfo.mDebugLayout = debugLayout;
6333         }
6334     }
6335 
6336     private static SparseArray<String> getAttributeMap() {
6337         if (mAttributeMap == null) {
6338             mAttributeMap = new SparseArray<>();
6339         }
6340         return mAttributeMap;
6341     }
6342 
6343     private void retrieveExplicitStyle(@NonNull Resources.Theme theme,
6344             @Nullable AttributeSet attrs) {
6345         if (!sDebugViewAttributes) {
6346             return;
6347         }
6348         mExplicitStyle = theme.getExplicitStyle(attrs);
6349     }
6350 
6351     /**
6352      * Stores debugging information about attributes. This should be called in a constructor by
6353      * every custom {@link View} that uses a custom styleable. If the custom view does not call it,
6354      * then the custom attributes used by this view will not be visible in layout inspection tools.
6355      *
6356      *  @param context Context under which this view is created.
6357      * @param styleable A reference to styleable array R.styleable.Foo
6358      * @param attrs AttributeSet used to construct this view.
6359      * @param t Resolved {@link TypedArray} returned by a call to
6360      *        {@link Resources#obtainAttributes(AttributeSet, int[])}.
6361      * @param defStyleAttr Default style attribute passed into the view constructor.
6362      * @param defStyleRes Default style resource passed into the view constructor.
6363      */
6364     public final void saveAttributeDataForStyleable(@NonNull Context context,
6365             @NonNull int[] styleable, @Nullable AttributeSet attrs, @NonNull TypedArray t,
6366             int defStyleAttr, int defStyleRes) {
6367         if (!sDebugViewAttributes) {
6368             return;
6369         }
6370 
6371         int[] attributeResolutionStack = context.getTheme().getAttributeResolutionStack(
6372                 defStyleAttr, defStyleRes, mExplicitStyle);
6373 
6374         if (mAttributeResolutionStacks == null) {
6375             mAttributeResolutionStacks = new SparseArray<>();
6376         }
6377 
6378         if (mAttributeSourceResId == null) {
6379             mAttributeSourceResId = new SparseIntArray();
6380         }
6381 
6382         final int indexCount = t.getIndexCount();
6383         for (int j = 0; j < indexCount; ++j) {
6384             final int index = t.getIndex(j);
6385             mAttributeSourceResId.append(styleable[index], t.getSourceResourceId(index, 0));
6386             mAttributeResolutionStacks.append(styleable[index], attributeResolutionStack);
6387         }
6388     }
6389 
6390     private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
6391         final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
6392         final int indexCount = t.getIndexCount();
6393         final String[] attributes = new String[(attrsCount + indexCount) * 2];
6394 
6395         int i = 0;
6396 
6397         // Store raw XML attributes.
6398         for (int j = 0; j < attrsCount; ++j) {
6399             attributes[i] = attrs.getAttributeName(j);
6400             attributes[i + 1] = attrs.getAttributeValue(j);
6401             i += 2;
6402         }
6403 
6404         // Store resolved styleable attributes.
6405         final Resources res = t.getResources();
6406         final SparseArray<String> attributeMap = getAttributeMap();
6407         for (int j = 0; j < indexCount; ++j) {
6408             final int index = t.getIndex(j);
6409             if (!t.hasValueOrEmpty(index)) {
6410                 // Value is undefined. Skip it.
6411                 continue;
6412             }
6413 
6414             final int resourceId = t.getResourceId(index, 0);
6415             if (resourceId == 0) {
6416                 // Value is not a reference. Skip it.
6417                 continue;
6418             }
6419 
6420             String resourceName = attributeMap.get(resourceId);
6421             if (resourceName == null) {
6422                 try {
6423                     resourceName = res.getResourceName(resourceId);
6424                 } catch (Resources.NotFoundException e) {
6425                     resourceName = "0x" + Integer.toHexString(resourceId);
6426                 }
6427                 attributeMap.put(resourceId, resourceName);
6428             }
6429 
6430             attributes[i] = resourceName;
6431             attributes[i + 1] = t.getString(index);
6432             i += 2;
6433         }
6434 
6435         // Trim to fit contents.
6436         final String[] trimmed = new String[i];
6437         System.arraycopy(attributes, 0, trimmed, 0, i);
6438         mAttributes = trimmed;
6439     }
6440 
6441     @Override
6442     public String toString() {
6443         StringBuilder out = new StringBuilder(128);
6444         out.append(getClass().getName());
6445         out.append('{');
6446         out.append(Integer.toHexString(System.identityHashCode(this)));
6447         out.append(' ');
6448         switch (mViewFlags&VISIBILITY_MASK) {
6449             case VISIBLE: out.append('V'); break;
6450             case INVISIBLE: out.append('I'); break;
6451             case GONE: out.append('G'); break;
6452             default: out.append('.'); break;
6453         }
6454         out.append((mViewFlags & FOCUSABLE) == FOCUSABLE ? 'F' : '.');
6455         out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
6456         out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
6457         out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
6458         out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
6459         out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
6460         out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
6461         out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
6462         out.append(' ');
6463         out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
6464         out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
6465         out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
6466         if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
6467             out.append('p');
6468         } else {
6469             out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
6470         }
6471         out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
6472         out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
6473         out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
6474         out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
6475         out.append(' ');
6476         out.append(mLeft);
6477         out.append(',');
6478         out.append(mTop);
6479         out.append('-');
6480         out.append(mRight);
6481         out.append(',');
6482         out.append(mBottom);
6483         final int id = getId();
6484         if (id != NO_ID) {
6485             out.append(" #");
6486             out.append(Integer.toHexString(id));
6487             final Resources r = mResources;
6488             if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
6489                 try {
6490                     String pkgname;
6491                     switch (id&0xff000000) {
6492                         case 0x7f000000:
6493                             pkgname="app";
6494                             break;
6495                         case 0x01000000:
6496                             pkgname="android";
6497                             break;
6498                         default:
6499                             pkgname = r.getResourcePackageName(id);
6500                             break;
6501                     }
6502                     String typename = r.getResourceTypeName(id);
6503                     String entryname = r.getResourceEntryName(id);
6504                     out.append(" ");
6505                     out.append(pkgname);
6506                     out.append(":");
6507                     out.append(typename);
6508                     out.append("/");
6509                     out.append(entryname);
6510                 } catch (Resources.NotFoundException e) {
6511                 }
6512             }
6513         }
6514         if (mAutofillId != null) {
6515             out.append(" aid="); out.append(mAutofillId);
6516         }
6517         out.append("}");
6518         return out.toString();
6519     }
6520 
6521     /**
6522      * <p>
6523      * Initializes the fading edges from a given set of styled attributes. This
6524      * method should be called by subclasses that need fading edges and when an
6525      * instance of these subclasses is created programmatically rather than
6526      * being inflated from XML. This method is automatically called when the XML
6527      * is inflated.
6528      * </p>
6529      *
6530      * @param a the styled attributes set to initialize the fading edges from
6531      *
6532      * @removed
6533      */
6534     protected void initializeFadingEdge(TypedArray a) {
6535         // This method probably shouldn't have been included in the SDK to begin with.
6536         // It relies on 'a' having been initialized using an attribute filter array that is
6537         // not publicly available to the SDK. The old method has been renamed
6538         // to initializeFadingEdgeInternal and hidden for framework use only;
6539         // this one initializes using defaults to make it safe to call for apps.
6540 
6541         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
6542 
6543         initializeFadingEdgeInternal(arr);
6544 
6545         arr.recycle();
6546     }
6547 
6548     /**
6549      * <p>
6550      * Initializes the fading edges from a given set of styled attributes. This
6551      * method should be called by subclasses that need fading edges and when an
6552      * instance of these subclasses is created programmatically rather than
6553      * being inflated from XML. This method is automatically called when the XML
6554      * is inflated.
6555      * </p>
6556      *
6557      * @param a the styled attributes set to initialize the fading edges from
6558      * @hide This is the real method; the public one is shimmed to be safe to call from apps.
6559      */
6560     protected void initializeFadingEdgeInternal(TypedArray a) {
6561         initScrollCache();
6562 
6563         mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
6564                 R.styleable.View_fadingEdgeLength,
6565                 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
6566     }
6567 
6568     /**
6569      * Returns the size of the vertical faded edges used to indicate that more
6570      * content in this view is visible.
6571      *
6572      * @return The size in pixels of the vertical faded edge or 0 if vertical
6573      *         faded edges are not enabled for this view.
6574      * @attr ref android.R.styleable#View_fadingEdgeLength
6575      */
6576     public int getVerticalFadingEdgeLength() {
6577         if (isVerticalFadingEdgeEnabled()) {
6578             ScrollabilityCache cache = mScrollCache;
6579             if (cache != null) {
6580                 return cache.fadingEdgeLength;
6581             }
6582         }
6583         return 0;
6584     }
6585 
6586     /**
6587      * Set the size of the faded edge used to indicate that more content in this
6588      * view is available.  Will not change whether the fading edge is enabled; use
6589      * {@link #setVerticalFadingEdgeEnabled(boolean)} or
6590      * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
6591      * for the vertical or horizontal fading edges.
6592      *
6593      * @param length The size in pixels of the faded edge used to indicate that more
6594      *        content in this view is visible.
6595      */
6596     public void setFadingEdgeLength(int length) {
6597         initScrollCache();
6598         mScrollCache.fadingEdgeLength = length;
6599     }
6600 
6601     /**
6602      * Returns the size of the horizontal faded edges used to indicate that more
6603      * content in this view is visible.
6604      *
6605      * @return The size in pixels of the horizontal faded edge or 0 if horizontal
6606      *         faded edges are not enabled for this view.
6607      * @attr ref android.R.styleable#View_fadingEdgeLength
6608      */
6609     public int getHorizontalFadingEdgeLength() {
6610         if (isHorizontalFadingEdgeEnabled()) {
6611             ScrollabilityCache cache = mScrollCache;
6612             if (cache != null) {
6613                 return cache.fadingEdgeLength;
6614             }
6615         }
6616         return 0;
6617     }
6618 
6619     /**
6620      * Returns the width of the vertical scrollbar.
6621      *
6622      * @return The width in pixels of the vertical scrollbar or 0 if there
6623      *         is no vertical scrollbar.
6624      */
6625     public int getVerticalScrollbarWidth() {
6626         ScrollabilityCache cache = mScrollCache;
6627         if (cache != null) {
6628             ScrollBarDrawable scrollBar = cache.scrollBar;
6629             if (scrollBar != null) {
6630                 int size = scrollBar.getSize(true);
6631                 if (size <= 0) {
6632                     size = cache.scrollBarSize;
6633                 }
6634                 return size;
6635             }
6636             return 0;
6637         }
6638         return 0;
6639     }
6640 
6641     /**
6642      * Returns the height of the horizontal scrollbar.
6643      *
6644      * @return The height in pixels of the horizontal scrollbar or 0 if
6645      *         there is no horizontal scrollbar.
6646      */
6647     protected int getHorizontalScrollbarHeight() {
6648         ScrollabilityCache cache = mScrollCache;
6649         if (cache != null) {
6650             ScrollBarDrawable scrollBar = cache.scrollBar;
6651             if (scrollBar != null) {
6652                 int size = scrollBar.getSize(false);
6653                 if (size <= 0) {
6654                     size = cache.scrollBarSize;
6655                 }
6656                 return size;
6657             }
6658             return 0;
6659         }
6660         return 0;
6661     }
6662 
6663     /**
6664      * <p>
6665      * Initializes the scrollbars from a given set of styled attributes. This
6666      * method should be called by subclasses that need scrollbars and when an
6667      * instance of these subclasses is created programmatically rather than
6668      * being inflated from XML. This method is automatically called when the XML
6669      * is inflated.
6670      * </p>
6671      *
6672      * @param a the styled attributes set to initialize the scrollbars from
6673      *
6674      * @removed
6675      */
6676     protected void initializeScrollbars(TypedArray a) {
6677         // It's not safe to use this method from apps. The parameter 'a' must have been obtained
6678         // using the View filter array which is not available to the SDK. As such, internal
6679         // framework usage now uses initializeScrollbarsInternal and we grab a default
6680         // TypedArray with the right filter instead here.
6681         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
6682 
6683         initializeScrollbarsInternal(arr);
6684 
6685         // We ignored the method parameter. Recycle the one we actually did use.
6686         arr.recycle();
6687     }
6688 
6689     private void initializeScrollBarDrawable() {
6690         initScrollCache();
6691 
6692         if (mScrollCache.scrollBar == null) {
6693             mScrollCache.scrollBar = new ScrollBarDrawable();
6694             mScrollCache.scrollBar.setState(getDrawableState());
6695             mScrollCache.scrollBar.setCallback(this);
6696         }
6697     }
6698 
6699     /**
6700      * <p>
6701      * Initializes the scrollbars from a given set of styled attributes. This
6702      * method should be called by subclasses that need scrollbars and when an
6703      * instance of these subclasses is created programmatically rather than
6704      * being inflated from XML. This method is automatically called when the XML
6705      * is inflated.
6706      * </p>
6707      *
6708      * @param a the styled attributes set to initialize the scrollbars from
6709      * @hide
6710      */
6711     @UnsupportedAppUsage
6712     protected void initializeScrollbarsInternal(TypedArray a) {
6713         initScrollCache();
6714 
6715         final ScrollabilityCache scrollabilityCache = mScrollCache;
6716 
6717         if (scrollabilityCache.scrollBar == null) {
6718             scrollabilityCache.scrollBar = new ScrollBarDrawable();
6719             scrollabilityCache.scrollBar.setState(getDrawableState());
6720             scrollabilityCache.scrollBar.setCallback(this);
6721         }
6722 
6723         final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
6724 
6725         if (!fadeScrollbars) {
6726             scrollabilityCache.state = ScrollabilityCache.ON;
6727         }
6728         scrollabilityCache.fadeScrollBars = fadeScrollbars;
6729 
6730 
6731         scrollabilityCache.scrollBarFadeDuration = a.getInt(
6732                 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
6733                         .getScrollBarFadeDuration());
6734         scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
6735                 R.styleable.View_scrollbarDefaultDelayBeforeFade,
6736                 ViewConfiguration.getScrollDefaultDelay());
6737 
6738 
6739         scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
6740                 com.android.internal.R.styleable.View_scrollbarSize,
6741                 ViewConfiguration.get(mContext).getScaledScrollBarSize());
6742 
6743         Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
6744         scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
6745 
6746         Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
6747         if (thumb != null) {
6748             scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
6749         }
6750 
6751         boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
6752                 false);
6753         if (alwaysDraw) {
6754             scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
6755         }
6756 
6757         track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
6758         scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
6759 
6760         thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
6761         if (thumb != null) {
6762             scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
6763         }
6764 
6765         alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
6766                 false);
6767         if (alwaysDraw) {
6768             scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
6769         }
6770 
6771         // Apply layout direction to the new Drawables if needed
6772         final int layoutDirection = getLayoutDirection();
6773         if (track != null) {
6774             track.setLayoutDirection(layoutDirection);
6775         }
6776         if (thumb != null) {
6777             thumb.setLayoutDirection(layoutDirection);
6778         }
6779 
6780         // Re-apply user/background padding so that scrollbar(s) get added
6781         resolvePadding();
6782     }
6783 
6784     /**
6785      * Defines the vertical scrollbar thumb drawable
6786      * @attr ref android.R.styleable#View_scrollbarThumbVertical
6787      *
6788      * @see #awakenScrollBars(int)
6789      * @see #isVerticalScrollBarEnabled()
6790      * @see #setVerticalScrollBarEnabled(boolean)
6791      */
6792     public void setVerticalScrollbarThumbDrawable(@Nullable Drawable drawable) {
6793         initializeScrollBarDrawable();
6794         mScrollCache.scrollBar.setVerticalThumbDrawable(drawable);
6795     }
6796 
6797     /**
6798      * Defines the vertical scrollbar track drawable
6799      * @attr ref android.R.styleable#View_scrollbarTrackVertical
6800      *
6801      * @see #awakenScrollBars(int)
6802      * @see #isVerticalScrollBarEnabled()
6803      * @see #setVerticalScrollBarEnabled(boolean)
6804      */
6805     public void setVerticalScrollbarTrackDrawable(@Nullable Drawable drawable) {
6806         initializeScrollBarDrawable();
6807         mScrollCache.scrollBar.setVerticalTrackDrawable(drawable);
6808     }
6809 
6810     /**
6811      * Defines the horizontal thumb drawable
6812      * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
6813      *
6814      * @see #awakenScrollBars(int)
6815      * @see #isHorizontalScrollBarEnabled()
6816      * @see #setHorizontalScrollBarEnabled(boolean)
6817      */
6818     public void setHorizontalScrollbarThumbDrawable(@Nullable Drawable drawable) {
6819         initializeScrollBarDrawable();
6820         mScrollCache.scrollBar.setHorizontalThumbDrawable(drawable);
6821     }
6822 
6823     /**
6824      * Defines the horizontal track drawable
6825      * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
6826      *
6827      * @see #awakenScrollBars(int)
6828      * @see #isHorizontalScrollBarEnabled()
6829      * @see #setHorizontalScrollBarEnabled(boolean)
6830      */
6831     public void setHorizontalScrollbarTrackDrawable(@Nullable Drawable drawable) {
6832         initializeScrollBarDrawable();
6833         mScrollCache.scrollBar.setHorizontalTrackDrawable(drawable);
6834     }
6835 
6836     /**
6837      * Returns the currently configured Drawable for the thumb of the vertical scroll bar if it
6838      * exists, null otherwise.
6839      *
6840      * @see #awakenScrollBars(int)
6841      * @see #isVerticalScrollBarEnabled()
6842      * @see #setVerticalScrollBarEnabled(boolean)
6843      */
6844     public @Nullable Drawable getVerticalScrollbarThumbDrawable() {
6845         return mScrollCache != null ? mScrollCache.scrollBar.getVerticalThumbDrawable() : null;
6846     }
6847 
6848     /**
6849      * Returns the currently configured Drawable for the track of the vertical scroll bar if it
6850      * exists, null otherwise.
6851      *
6852      * @see #awakenScrollBars(int)
6853      * @see #isVerticalScrollBarEnabled()
6854      * @see #setVerticalScrollBarEnabled(boolean)
6855      */
6856     public @Nullable Drawable getVerticalScrollbarTrackDrawable() {
6857         return mScrollCache != null ? mScrollCache.scrollBar.getVerticalTrackDrawable() : null;
6858     }
6859 
6860     /**
6861      * Returns the currently configured Drawable for the thumb of the horizontal scroll bar if it
6862      * exists, null otherwise.
6863      *
6864      * @see #awakenScrollBars(int)
6865      * @see #isHorizontalScrollBarEnabled()
6866      * @see #setHorizontalScrollBarEnabled(boolean)
6867      */
6868     public @Nullable Drawable getHorizontalScrollbarThumbDrawable() {
6869         return mScrollCache != null ? mScrollCache.scrollBar.getHorizontalThumbDrawable() : null;
6870     }
6871 
6872     /**
6873      * Returns the currently configured Drawable for the track of the horizontal scroll bar if it
6874      * exists, null otherwise.
6875      *
6876      * @see #awakenScrollBars(int)
6877      * @see #isHorizontalScrollBarEnabled()
6878      * @see #setHorizontalScrollBarEnabled(boolean)
6879      */
6880     public @Nullable Drawable getHorizontalScrollbarTrackDrawable() {
6881         return mScrollCache != null ? mScrollCache.scrollBar.getHorizontalTrackDrawable() : null;
6882     }
6883 
6884     private void initializeScrollIndicatorsInternal() {
6885         // Some day maybe we'll break this into top/left/start/etc. and let the
6886         // client control it. Until then, you can have any scroll indicator you
6887         // want as long as it's a 1dp foreground-colored rectangle.
6888         if (mScrollIndicatorDrawable == null) {
6889             mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
6890         }
6891     }
6892 
6893     /**
6894      * <p>
6895      * Initalizes the scrollability cache if necessary.
6896      * </p>
6897      */
6898     private void initScrollCache() {
6899         if (mScrollCache == null) {
6900             mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
6901         }
6902     }
6903 
6904     @UnsupportedAppUsage
6905     private ScrollabilityCache getScrollCache() {
6906         initScrollCache();
6907         return mScrollCache;
6908     }
6909 
6910     /**
6911      * Set the position of the vertical scroll bar. Should be one of
6912      * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
6913      * {@link #SCROLLBAR_POSITION_RIGHT}.
6914      *
6915      * @param position Where the vertical scroll bar should be positioned.
6916      */
6917     public void setVerticalScrollbarPosition(int position) {
6918         if (mVerticalScrollbarPosition != position) {
6919             mVerticalScrollbarPosition = position;
6920             computeOpaqueFlags();
6921             resolvePadding();
6922         }
6923     }
6924 
6925     /**
6926      * @return The position where the vertical scroll bar will show, if applicable.
6927      * @see #setVerticalScrollbarPosition(int)
6928      */
6929     public int getVerticalScrollbarPosition() {
6930         return mVerticalScrollbarPosition;
6931     }
6932 
6933     boolean isOnScrollbar(float x, float y) {
6934         if (mScrollCache == null) {
6935             return false;
6936         }
6937         x += getScrollX();
6938         y += getScrollY();
6939         final boolean canScrollVertically =
6940                 computeVerticalScrollRange() > computeVerticalScrollExtent();
6941         if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden() && canScrollVertically) {
6942             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
6943             getVerticalScrollBarBounds(null, touchBounds);
6944             if (touchBounds.contains((int) x, (int) y)) {
6945                 return true;
6946             }
6947         }
6948         final boolean canScrollHorizontally =
6949                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
6950         if (isHorizontalScrollBarEnabled() && canScrollHorizontally) {
6951             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
6952             getHorizontalScrollBarBounds(null, touchBounds);
6953             if (touchBounds.contains((int) x, (int) y)) {
6954                 return true;
6955             }
6956         }
6957         return false;
6958     }
6959 
6960     @UnsupportedAppUsage
6961     boolean isOnScrollbarThumb(float x, float y) {
6962         return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
6963     }
6964 
6965     private boolean isOnVerticalScrollbarThumb(float x, float y) {
6966         if (mScrollCache == null || !isVerticalScrollBarEnabled() || isVerticalScrollBarHidden()) {
6967             return false;
6968         }
6969         final int range = computeVerticalScrollRange();
6970         final int extent = computeVerticalScrollExtent();
6971         if (range > extent) {
6972             x += getScrollX();
6973             y += getScrollY();
6974             final Rect bounds = mScrollCache.mScrollBarBounds;
6975             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
6976             getVerticalScrollBarBounds(bounds, touchBounds);
6977             final int offset = computeVerticalScrollOffset();
6978             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
6979                     extent, range);
6980             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
6981                     extent, range, offset);
6982             final int thumbTop = bounds.top + thumbOffset;
6983             final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
6984             if (x >= touchBounds.left && x <= touchBounds.right
6985                     && y >= thumbTop - adjust && y <= thumbTop + thumbLength + adjust) {
6986                 return true;
6987             }
6988         }
6989         return false;
6990     }
6991 
6992     private boolean isOnHorizontalScrollbarThumb(float x, float y) {
6993         if (mScrollCache == null || !isHorizontalScrollBarEnabled()) {
6994             return false;
6995         }
6996         final int range = computeHorizontalScrollRange();
6997         final int extent = computeHorizontalScrollExtent();
6998         if (range > extent) {
6999             x += getScrollX();
7000             y += getScrollY();
7001             final Rect bounds = mScrollCache.mScrollBarBounds;
7002             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
7003             getHorizontalScrollBarBounds(bounds, touchBounds);
7004             final int offset = computeHorizontalScrollOffset();
7005 
7006             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
7007                     extent, range);
7008             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
7009                     extent, range, offset);
7010             final int thumbLeft = bounds.left + thumbOffset;
7011             final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
7012             if (x >= thumbLeft - adjust && x <= thumbLeft + thumbLength + adjust
7013                     && y >= touchBounds.top && y <= touchBounds.bottom) {
7014                 return true;
7015             }
7016         }
7017         return false;
7018     }
7019 
7020     @UnsupportedAppUsage
7021     boolean isDraggingScrollBar() {
7022         return mScrollCache != null
7023                 && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
7024     }
7025 
7026     /**
7027      * Sets the state of all scroll indicators.
7028      * <p>
7029      * See {@link #setScrollIndicators(int, int)} for usage information.
7030      *
7031      * @param indicators a bitmask of indicators that should be enabled, or
7032      *                   {@code 0} to disable all indicators
7033      * @see #setScrollIndicators(int, int)
7034      * @see #getScrollIndicators()
7035      * @attr ref android.R.styleable#View_scrollIndicators
7036      */
7037     public void setScrollIndicators(@ScrollIndicators int indicators) {
7038         setScrollIndicators(indicators,
7039                 SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
7040     }
7041 
7042     /**
7043      * Sets the state of the scroll indicators specified by the mask. To change
7044      * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
7045      * <p>
7046      * When a scroll indicator is enabled, it will be displayed if the view
7047      * can scroll in the direction of the indicator.
7048      * <p>
7049      * Multiple indicator types may be enabled or disabled by passing the
7050      * logical OR of the desired types. If multiple types are specified, they
7051      * will all be set to the same enabled state.
7052      * <p>
7053      * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
7054      *
7055      * @param indicators the indicator direction, or the logical OR of multiple
7056      *             indicator directions. One or more of:
7057      *             <ul>
7058      *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
7059      *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
7060      *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
7061      *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
7062      *               <li>{@link #SCROLL_INDICATOR_START}</li>
7063      *               <li>{@link #SCROLL_INDICATOR_END}</li>
7064      *             </ul>
7065      * @see #setScrollIndicators(int)
7066      * @see #getScrollIndicators()
7067      * @attr ref android.R.styleable#View_scrollIndicators
7068      */
7069     public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
7070         // Shift and sanitize mask.
7071         mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
7072         mask &= SCROLL_INDICATORS_PFLAG3_MASK;
7073 
7074         // Shift and mask indicators.
7075         indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
7076         indicators &= mask;
7077 
7078         // Merge with non-masked flags.
7079         final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
7080 
7081         if (mPrivateFlags3 != updatedFlags) {
7082             mPrivateFlags3 = updatedFlags;
7083 
7084             if (indicators != 0) {
7085                 initializeScrollIndicatorsInternal();
7086             }
7087             invalidate();
7088         }
7089     }
7090 
7091     /**
7092      * Returns a bitmask representing the enabled scroll indicators.
7093      * <p>
7094      * For example, if the top and left scroll indicators are enabled and all
7095      * other indicators are disabled, the return value will be
7096      * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
7097      * <p>
7098      * To check whether the bottom scroll indicator is enabled, use the value
7099      * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
7100      *
7101      * @return a bitmask representing the enabled scroll indicators
7102      */
7103     @InspectableProperty(flagMapping = {
7104             @FlagEntry(target = SCROLL_INDICATORS_NONE, mask = 0xffff_ffff, name = "none"),
7105             @FlagEntry(target = SCROLL_INDICATOR_TOP, name = "top"),
7106             @FlagEntry(target = SCROLL_INDICATOR_BOTTOM, name = "bottom"),
7107             @FlagEntry(target = SCROLL_INDICATOR_LEFT, name = "left"),
7108             @FlagEntry(target = SCROLL_INDICATOR_RIGHT, name = "right"),
7109             @FlagEntry(target = SCROLL_INDICATOR_START, name = "start"),
7110             @FlagEntry(target = SCROLL_INDICATOR_END, name = "end")
7111     })
7112     @ScrollIndicators
7113     public int getScrollIndicators() {
7114         return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
7115                 >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
7116     }
7117 
7118     @UnsupportedAppUsage
7119     ListenerInfo getListenerInfo() {
7120         if (mListenerInfo != null) {
7121             return mListenerInfo;
7122         }
7123         mListenerInfo = new ListenerInfo();
7124         return mListenerInfo;
7125     }
7126 
7127     /**
7128      * Register a callback to be invoked when the scroll X or Y positions of
7129      * this view change.
7130      * <p>
7131      * <b>Note:</b> Some views handle scrolling independently from View and may
7132      * have their own separate listeners for scroll-type events. For example,
7133      * {@link android.widget.ListView ListView} allows clients to register an
7134      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
7135      * to listen for changes in list scroll position.
7136      *
7137      * @param l The listener to notify when the scroll X or Y position changes.
7138      * @see android.view.View#getScrollX()
7139      * @see android.view.View#getScrollY()
7140      */
7141     public void setOnScrollChangeListener(OnScrollChangeListener l) {
7142         getListenerInfo().mOnScrollChangeListener = l;
7143     }
7144 
7145     /**
7146      * Register a callback to be invoked when focus of this view changed.
7147      *
7148      * @param l The callback that will run.
7149      */
7150     public void setOnFocusChangeListener(OnFocusChangeListener l) {
7151         getListenerInfo().mOnFocusChangeListener = l;
7152     }
7153 
7154     /**
7155      * Add a listener that will be called when the bounds of the view change due to
7156      * layout processing.
7157      *
7158      * @param listener The listener that will be called when layout bounds change.
7159      */
7160     public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
7161         ListenerInfo li = getListenerInfo();
7162         if (li.mOnLayoutChangeListeners == null) {
7163             li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
7164         }
7165         if (!li.mOnLayoutChangeListeners.contains(listener)) {
7166             li.mOnLayoutChangeListeners.add(listener);
7167         }
7168     }
7169 
7170     /**
7171      * Remove a listener for layout changes.
7172      *
7173      * @param listener The listener for layout bounds change.
7174      */
7175     public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
7176         ListenerInfo li = mListenerInfo;
7177         if (li == null || li.mOnLayoutChangeListeners == null) {
7178             return;
7179         }
7180         li.mOnLayoutChangeListeners.remove(listener);
7181     }
7182 
7183     /**
7184      * Add a listener for attach state changes.
7185      *
7186      * This listener will be called whenever this view is attached or detached
7187      * from a window. Remove the listener using
7188      * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
7189      *
7190      * @param listener Listener to attach
7191      * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
7192      */
7193     public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
7194         ListenerInfo li = getListenerInfo();
7195         if (li.mOnAttachStateChangeListeners == null) {
7196             li.mOnAttachStateChangeListeners
7197                     = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
7198         }
7199         li.mOnAttachStateChangeListeners.add(listener);
7200     }
7201 
7202     /**
7203      * Remove a listener for attach state changes. The listener will receive no further
7204      * notification of window attach/detach events.
7205      *
7206      * @param listener Listener to remove
7207      * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
7208      */
7209     public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
7210         ListenerInfo li = mListenerInfo;
7211         if (li == null || li.mOnAttachStateChangeListeners == null) {
7212             return;
7213         }
7214         li.mOnAttachStateChangeListeners.remove(listener);
7215     }
7216 
7217     /**
7218      * Returns the focus-change callback registered for this view.
7219      *
7220      * @return The callback, or null if one is not registered.
7221      */
7222     public OnFocusChangeListener getOnFocusChangeListener() {
7223         ListenerInfo li = mListenerInfo;
7224         return li != null ? li.mOnFocusChangeListener : null;
7225     }
7226 
7227     /**
7228      * Register a callback to be invoked when this view is clicked. If this view is not
7229      * clickable, it becomes clickable.
7230      *
7231      * @param l The callback that will run
7232      *
7233      * @see #setClickable(boolean)
7234      */
7235     public void setOnClickListener(@Nullable OnClickListener l) {
7236         if (!isClickable()) {
7237             setClickable(true);
7238         }
7239         getListenerInfo().mOnClickListener = l;
7240     }
7241 
7242     /**
7243      * Return whether this view has an attached OnClickListener.  Returns
7244      * true if there is a listener, false if there is none.
7245      */
7246     public boolean hasOnClickListeners() {
7247         ListenerInfo li = mListenerInfo;
7248         return (li != null && li.mOnClickListener != null);
7249     }
7250 
7251     /**
7252      * Register a callback to be invoked when this view is clicked and held. If this view is not
7253      * long clickable, it becomes long clickable.
7254      *
7255      * @param l The callback that will run
7256      *
7257      * @see #setLongClickable(boolean)
7258      */
7259     public void setOnLongClickListener(@Nullable OnLongClickListener l) {
7260         if (!isLongClickable()) {
7261             setLongClickable(true);
7262         }
7263         getListenerInfo().mOnLongClickListener = l;
7264     }
7265 
7266     /**
7267      * Return whether this view has an attached OnLongClickListener.  Returns
7268      * true if there is a listener, false if there is none.
7269      */
7270     public boolean hasOnLongClickListeners() {
7271         ListenerInfo li = mListenerInfo;
7272         return (li != null && li.mOnLongClickListener != null);
7273     }
7274 
7275     /**
7276      * @return the registered {@link OnLongClickListener} if there is one, {@code null} otherwise.
7277      * @hide
7278      */
7279     @Nullable
7280     public OnLongClickListener getOnLongClickListener() {
7281         ListenerInfo li = mListenerInfo;
7282         return (li != null) ? li.mOnLongClickListener : null;
7283     }
7284 
7285     /**
7286      * Register a callback to be invoked when this view is context clicked. If the view is not
7287      * context clickable, it becomes context clickable.
7288      *
7289      * @param l The callback that will run
7290      * @see #setContextClickable(boolean)
7291      */
7292     public void setOnContextClickListener(@Nullable OnContextClickListener l) {
7293         if (!isContextClickable()) {
7294             setContextClickable(true);
7295         }
7296         getListenerInfo().mOnContextClickListener = l;
7297     }
7298 
7299     /**
7300      * Register a callback to be invoked when the context menu for this view is
7301      * being built. If this view is not long clickable, it becomes long clickable.
7302      *
7303      * @param l The callback that will run
7304      *
7305      */
7306     public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
7307         if (!isLongClickable()) {
7308             setLongClickable(true);
7309         }
7310         getListenerInfo().mOnCreateContextMenuListener = l;
7311     }
7312 
7313     /**
7314      * Set an observer to collect stats for each frame rendered for this view.
7315      *
7316      * @hide
7317      */
7318     public void addFrameMetricsListener(Window window,
7319             Window.OnFrameMetricsAvailableListener listener,
7320             Handler handler) {
7321         if (mAttachInfo != null) {
7322             if (mAttachInfo.mThreadedRenderer != null) {
7323                 if (mFrameMetricsObservers == null) {
7324                     mFrameMetricsObservers = new ArrayList<>();
7325                 }
7326 
7327                 FrameMetricsObserver fmo = new FrameMetricsObserver(window, handler, listener);
7328                 mFrameMetricsObservers.add(fmo);
7329                 mAttachInfo.mThreadedRenderer.addObserver(fmo.getRendererObserver());
7330             } else {
7331                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
7332             }
7333         } else {
7334             if (mFrameMetricsObservers == null) {
7335                 mFrameMetricsObservers = new ArrayList<>();
7336             }
7337 
7338             FrameMetricsObserver fmo = new FrameMetricsObserver(window, handler, listener);
7339             mFrameMetricsObservers.add(fmo);
7340         }
7341     }
7342 
7343     /**
7344      * Remove observer configured to collect frame stats for this view.
7345      *
7346      * @hide
7347      */
7348     public void removeFrameMetricsListener(
7349             Window.OnFrameMetricsAvailableListener listener) {
7350         ThreadedRenderer renderer = getThreadedRenderer();
7351         FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
7352         if (fmo == null) {
7353             throw new IllegalArgumentException(
7354                     "attempt to remove OnFrameMetricsAvailableListener that was never added");
7355         }
7356 
7357         if (mFrameMetricsObservers != null) {
7358             mFrameMetricsObservers.remove(fmo);
7359             if (renderer != null) {
7360                 renderer.removeObserver(fmo.getRendererObserver());
7361             }
7362         }
7363     }
7364 
7365     private void registerPendingFrameMetricsObservers() {
7366         if (mFrameMetricsObservers != null) {
7367             ThreadedRenderer renderer = getThreadedRenderer();
7368             if (renderer != null) {
7369                 for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
7370                     renderer.addObserver(fmo.getRendererObserver());
7371                 }
7372             } else {
7373                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
7374             }
7375         }
7376     }
7377 
7378     private FrameMetricsObserver findFrameMetricsObserver(
7379             Window.OnFrameMetricsAvailableListener listener) {
7380         if (mFrameMetricsObservers != null) {
7381             for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
7382                 FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
7383                 if (observer.mListener == listener) {
7384                     return observer;
7385                 }
7386             }
7387         }
7388 
7389         return null;
7390     }
7391 
7392     /** @hide */
7393     public void setNotifyAutofillManagerOnClick(boolean notify) {
7394         if (notify) {
7395             mPrivateFlags |= PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
7396         } else {
7397             mPrivateFlags &= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
7398         }
7399     }
7400 
7401     private void notifyAutofillManagerOnClick() {
7402         if ((mPrivateFlags & PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK) != 0) {
7403             try {
7404                 getAutofillManager().notifyViewClicked(this);
7405             } finally {
7406                 // Set it to already called so it's not called twice when called by
7407                 // performClickInternal()
7408                 mPrivateFlags &= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
7409             }
7410         }
7411     }
7412 
7413     /**
7414      * Entry point for {@link #performClick()} - other methods on View should call it instead of
7415      * {@code performClick()} directly to make sure the autofill manager is notified when
7416      * necessary (as subclasses could extend {@code performClick()} without calling the parent's
7417      * method).
7418      */
7419     private boolean performClickInternal() {
7420         // Must notify autofill manager before performing the click actions to avoid scenarios where
7421         // the app has a click listener that changes the state of views the autofill service might
7422         // be interested on.
7423         notifyAutofillManagerOnClick();
7424 
7425         return performClick();
7426     }
7427 
7428     /**
7429      * Call this view's OnClickListener, if it is defined.  Performs all normal
7430      * actions associated with clicking: reporting accessibility event, playing
7431      * a sound, etc.
7432      *
7433      * @return True there was an assigned OnClickListener that was called, false
7434      *         otherwise is returned.
7435      */
7436     // NOTE: other methods on View should not call this method directly, but performClickInternal()
7437     // instead, to guarantee that the autofill manager is notified when necessary (as subclasses
7438     // could extend this method without calling super.performClick()).
7439     public boolean performClick() {
7440         // We still need to call this method to handle the cases where performClick() was called
7441         // externally, instead of through performClickInternal()
7442         notifyAutofillManagerOnClick();
7443 
7444         final boolean result;
7445         final ListenerInfo li = mListenerInfo;
7446         if (li != null && li.mOnClickListener != null) {
7447             playSoundEffect(SoundEffectConstants.CLICK);
7448             li.mOnClickListener.onClick(this);
7449             result = true;
7450         } else {
7451             result = false;
7452         }
7453 
7454         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
7455 
7456         notifyEnterOrExitForAutoFillIfNeeded(true);
7457 
7458         return result;
7459     }
7460 
7461     /**
7462      * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
7463      * this only calls the listener, and does not do any associated clicking
7464      * actions like reporting an accessibility event.
7465      *
7466      * @return True there was an assigned OnClickListener that was called, false
7467      *         otherwise is returned.
7468      */
7469     public boolean callOnClick() {
7470         ListenerInfo li = mListenerInfo;
7471         if (li != null && li.mOnClickListener != null) {
7472             li.mOnClickListener.onClick(this);
7473             return true;
7474         }
7475         return false;
7476     }
7477 
7478     /**
7479      * Calls this view's OnLongClickListener, if it is defined. Invokes the
7480      * context menu if the OnLongClickListener did not consume the event.
7481      *
7482      * @return {@code true} if one of the above receivers consumed the event,
7483      *         {@code false} otherwise
7484      */
7485     public boolean performLongClick() {
7486         return performLongClickInternal(mLongClickX, mLongClickY);
7487     }
7488 
7489     /**
7490      * Calls this view's OnLongClickListener, if it is defined. Invokes the
7491      * context menu if the OnLongClickListener did not consume the event,
7492      * anchoring it to an (x,y) coordinate.
7493      *
7494      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
7495      *          to disable anchoring
7496      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
7497      *          to disable anchoring
7498      * @return {@code true} if one of the above receivers consumed the event,
7499      *         {@code false} otherwise
7500      */
7501     public boolean performLongClick(float x, float y) {
7502         mLongClickX = x;
7503         mLongClickY = y;
7504         final boolean handled = performLongClick();
7505         mLongClickX = Float.NaN;
7506         mLongClickY = Float.NaN;
7507         return handled;
7508     }
7509 
7510     /**
7511      * Calls this view's OnLongClickListener, if it is defined. Invokes the
7512      * context menu if the OnLongClickListener did not consume the event,
7513      * optionally anchoring it to an (x,y) coordinate.
7514      *
7515      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
7516      *          to disable anchoring
7517      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
7518      *          to disable anchoring
7519      * @return {@code true} if one of the above receivers consumed the event,
7520      *         {@code false} otherwise
7521      */
7522     private boolean performLongClickInternal(float x, float y) {
7523         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
7524 
7525         boolean handled = false;
7526         final ListenerInfo li = mListenerInfo;
7527         if (li != null && li.mOnLongClickListener != null) {
7528             handled = li.mOnLongClickListener.onLongClick(View.this);
7529         }
7530         if (!handled) {
7531             final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
7532             handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
7533         }
7534         if ((mViewFlags & TOOLTIP) == TOOLTIP) {
7535             if (!handled) {
7536                 handled = showLongClickTooltip((int) x, (int) y);
7537             }
7538         }
7539         if (handled) {
7540             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
7541         }
7542         return handled;
7543     }
7544 
7545     /**
7546      * Call this view's OnContextClickListener, if it is defined.
7547      *
7548      * @param x the x coordinate of the context click
7549      * @param y the y coordinate of the context click
7550      * @return True if there was an assigned OnContextClickListener that consumed the event, false
7551      *         otherwise.
7552      */
7553     public boolean performContextClick(float x, float y) {
7554         return performContextClick();
7555     }
7556 
7557     /**
7558      * Call this view's OnContextClickListener, if it is defined.
7559      *
7560      * @return True if there was an assigned OnContextClickListener that consumed the event, false
7561      *         otherwise.
7562      */
7563     public boolean performContextClick() {
7564         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
7565 
7566         boolean handled = false;
7567         ListenerInfo li = mListenerInfo;
7568         if (li != null && li.mOnContextClickListener != null) {
7569             handled = li.mOnContextClickListener.onContextClick(View.this);
7570         }
7571         if (handled) {
7572             performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
7573         }
7574         return handled;
7575     }
7576 
7577     /**
7578      * Performs button-related actions during a touch down event.
7579      *
7580      * @param event The event.
7581      * @return True if the down was consumed.
7582      *
7583      * @hide
7584      */
7585     protected boolean performButtonActionOnTouchDown(MotionEvent event) {
7586         if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
7587             (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
7588             showContextMenu(event.getX(), event.getY());
7589             mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
7590             return true;
7591         }
7592         return false;
7593     }
7594 
7595     /**
7596      * Shows the context menu for this view.
7597      *
7598      * @return {@code true} if the context menu was shown, {@code false}
7599      *         otherwise
7600      * @see #showContextMenu(float, float)
7601      */
7602     public boolean showContextMenu() {
7603         return getParent().showContextMenuForChild(this);
7604     }
7605 
7606     /**
7607      * Shows the context menu for this view anchored to the specified
7608      * view-relative coordinate.
7609      *
7610      * @param x the X coordinate in pixels relative to the view to which the
7611      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
7612      * @param y the Y coordinate in pixels relative to the view to which the
7613      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
7614      * @return {@code true} if the context menu was shown, {@code false}
7615      *         otherwise
7616      */
7617     public boolean showContextMenu(float x, float y) {
7618         return getParent().showContextMenuForChild(this, x, y);
7619     }
7620 
7621     /**
7622      * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
7623      *
7624      * @param callback Callback that will control the lifecycle of the action mode
7625      * @return The new action mode if it is started, null otherwise
7626      *
7627      * @see ActionMode
7628      * @see #startActionMode(android.view.ActionMode.Callback, int)
7629      */
7630     public ActionMode startActionMode(ActionMode.Callback callback) {
7631         return startActionMode(callback, ActionMode.TYPE_PRIMARY);
7632     }
7633 
7634     /**
7635      * Start an action mode with the given type.
7636      *
7637      * @param callback Callback that will control the lifecycle of the action mode
7638      * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
7639      * @return The new action mode if it is started, null otherwise
7640      *
7641      * @see ActionMode
7642      */
7643     public ActionMode startActionMode(ActionMode.Callback callback, int type) {
7644         ViewParent parent = getParent();
7645         if (parent == null) return null;
7646         try {
7647             return parent.startActionModeForChild(this, callback, type);
7648         } catch (AbstractMethodError ame) {
7649             // Older implementations of custom views might not implement this.
7650             return parent.startActionModeForChild(this, callback);
7651         }
7652     }
7653 
7654     /**
7655      * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
7656      * Context, creating a unique View identifier to retrieve the result.
7657      *
7658      * @param intent The Intent to be started.
7659      * @param requestCode The request code to use.
7660      * @hide
7661      */
7662     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
7663     public void startActivityForResult(Intent intent, int requestCode) {
7664         mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
7665         getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
7666     }
7667 
7668     /**
7669      * If this View corresponds to the calling who, dispatches the activity result.
7670      * @param who The identifier for the targeted View to receive the result.
7671      * @param requestCode The integer request code originally supplied to
7672      *                    startActivityForResult(), allowing you to identify who this
7673      *                    result came from.
7674      * @param resultCode The integer result code returned by the child activity
7675      *                   through its setResult().
7676      * @param data An Intent, which can return result data to the caller
7677      *               (various data can be attached to Intent "extras").
7678      * @return {@code true} if the activity result was dispatched.
7679      * @hide
7680      */
7681     public boolean dispatchActivityResult(
7682             String who, int requestCode, int resultCode, Intent data) {
7683         if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
7684             onActivityResult(requestCode, resultCode, data);
7685             mStartActivityRequestWho = null;
7686             return true;
7687         }
7688         return false;
7689     }
7690 
7691     /**
7692      * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
7693      *
7694      * @param requestCode The integer request code originally supplied to
7695      *                    startActivityForResult(), allowing you to identify who this
7696      *                    result came from.
7697      * @param resultCode The integer result code returned by the child activity
7698      *                   through its setResult().
7699      * @param data An Intent, which can return result data to the caller
7700      *               (various data can be attached to Intent "extras").
7701      * @hide
7702      */
7703     public void onActivityResult(int requestCode, int resultCode, Intent data) {
7704         // Do nothing.
7705     }
7706 
7707     /**
7708      * Register a callback to be invoked when a hardware key is pressed in this view.
7709      * Key presses in software input methods will generally not trigger the methods of
7710      * this listener.
7711      * @param l the key listener to attach to this view
7712      */
7713     public void setOnKeyListener(OnKeyListener l) {
7714         getListenerInfo().mOnKeyListener = l;
7715     }
7716 
7717     /**
7718      * Register a callback to be invoked when a touch event is sent to this view.
7719      * @param l the touch listener to attach to this view
7720      */
7721     public void setOnTouchListener(OnTouchListener l) {
7722         getListenerInfo().mOnTouchListener = l;
7723     }
7724 
7725     /**
7726      * Register a callback to be invoked when a generic motion event is sent to this view.
7727      * @param l the generic motion listener to attach to this view
7728      */
7729     public void setOnGenericMotionListener(OnGenericMotionListener l) {
7730         getListenerInfo().mOnGenericMotionListener = l;
7731     }
7732 
7733     /**
7734      * Register a callback to be invoked when a hover event is sent to this view.
7735      * @param l the hover listener to attach to this view
7736      */
7737     public void setOnHoverListener(OnHoverListener l) {
7738         getListenerInfo().mOnHoverListener = l;
7739     }
7740 
7741     /**
7742      * Register a drag event listener callback object for this View. The parameter is
7743      * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
7744      * View, the system calls the
7745      * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
7746      * @param l An implementation of {@link android.view.View.OnDragListener}.
7747      */
7748     public void setOnDragListener(OnDragListener l) {
7749         getListenerInfo().mOnDragListener = l;
7750     }
7751 
7752     /**
7753      * Give this view focus. This will cause
7754      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
7755      *
7756      * Note: this does not check whether this {@link View} should get focus, it just
7757      * gives it focus no matter what.  It should only be called internally by framework
7758      * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
7759      *
7760      * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
7761      *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
7762      *        focus moved when requestFocus() is called. It may not always
7763      *        apply, in which case use the default View.FOCUS_DOWN.
7764      * @param previouslyFocusedRect The rectangle of the view that had focus
7765      *        prior in this View's coordinate system.
7766      */
7767     void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
7768         if (DBG) {
7769             System.out.println(this + " requestFocus()");
7770         }
7771 
7772         if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
7773             mPrivateFlags |= PFLAG_FOCUSED;
7774 
7775             View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
7776 
7777             if (mParent != null) {
7778                 mParent.requestChildFocus(this, this);
7779                 updateFocusedInCluster(oldFocus, direction);
7780             }
7781 
7782             if (mAttachInfo != null) {
7783                 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
7784             }
7785 
7786             onFocusChanged(true, direction, previouslyFocusedRect);
7787             refreshDrawableState();
7788         }
7789     }
7790 
7791     /**
7792      * Sets this view's preference for reveal behavior when it gains focus.
7793      *
7794      * <p>When set to true, this is a signal to ancestor views in the hierarchy that
7795      * this view would prefer to be brought fully into view when it gains focus.
7796      * For example, a text field that a user is meant to type into. Other views such
7797      * as scrolling containers may prefer to opt-out of this behavior.</p>
7798      *
7799      * <p>The default value for views is true, though subclasses may change this
7800      * based on their preferred behavior.</p>
7801      *
7802      * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
7803      *
7804      * @see #getRevealOnFocusHint()
7805      */
7806     public final void setRevealOnFocusHint(boolean revealOnFocus) {
7807         if (revealOnFocus) {
7808             mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
7809         } else {
7810             mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
7811         }
7812     }
7813 
7814     /**
7815      * Returns this view's preference for reveal behavior when it gains focus.
7816      *
7817      * <p>When this method returns true for a child view requesting focus, ancestor
7818      * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
7819      * should make a best effort to make the newly focused child fully visible to the user.
7820      * When it returns false, ancestor views should preferably not disrupt scroll positioning or
7821      * other properties affecting visibility to the user as part of the focus change.</p>
7822      *
7823      * @return true if this view would prefer to become fully visible when it gains focus,
7824      *         false if it would prefer not to disrupt scroll positioning
7825      *
7826      * @see #setRevealOnFocusHint(boolean)
7827      */
7828     public final boolean getRevealOnFocusHint() {
7829         return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
7830     }
7831 
7832     /**
7833      * Populates <code>outRect</code> with the hotspot bounds. By default,
7834      * the hotspot bounds are identical to the screen bounds.
7835      *
7836      * @param outRect rect to populate with hotspot bounds
7837      * @hide Only for internal use by views and widgets.
7838      */
7839     public void getHotspotBounds(Rect outRect) {
7840         final Drawable background = getBackground();
7841         if (background != null) {
7842             background.getHotspotBounds(outRect);
7843         } else {
7844             getBoundsOnScreen(outRect);
7845         }
7846     }
7847 
7848     /**
7849      * Request that a rectangle of this view be visible on the screen,
7850      * scrolling if necessary just enough.
7851      *
7852      * <p>A View should call this if it maintains some notion of which part
7853      * of its content is interesting.  For example, a text editing view
7854      * should call this when its cursor moves.
7855      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
7856      * It should not be affected by which part of the View is currently visible or its scroll
7857      * position.
7858      *
7859      * @param rectangle The rectangle in the View's content coordinate space
7860      * @return Whether any parent scrolled.
7861      */
7862     public boolean requestRectangleOnScreen(Rect rectangle) {
7863         return requestRectangleOnScreen(rectangle, false);
7864     }
7865 
7866     /**
7867      * Request that a rectangle of this view be visible on the screen,
7868      * scrolling if necessary just enough.
7869      *
7870      * <p>A View should call this if it maintains some notion of which part
7871      * of its content is interesting.  For example, a text editing view
7872      * should call this when its cursor moves.
7873      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
7874      * It should not be affected by which part of the View is currently visible or its scroll
7875      * position.
7876      * <p>When <code>immediate</code> is set to true, scrolling will not be
7877      * animated.
7878      *
7879      * @param rectangle The rectangle in the View's content coordinate space
7880      * @param immediate True to forbid animated scrolling, false otherwise
7881      * @return Whether any parent scrolled.
7882      */
7883     public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
7884         if (mParent == null) {
7885             return false;
7886         }
7887 
7888         View child = this;
7889 
7890         RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
7891         position.set(rectangle);
7892 
7893         ViewParent parent = mParent;
7894         boolean scrolled = false;
7895         while (parent != null) {
7896             rectangle.set((int) position.left, (int) position.top,
7897                     (int) position.right, (int) position.bottom);
7898 
7899             scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
7900 
7901             if (!(parent instanceof View)) {
7902                 break;
7903             }
7904 
7905             // move it from child's content coordinate space to parent's content coordinate space
7906             position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
7907 
7908             child = (View) parent;
7909             parent = child.getParent();
7910         }
7911 
7912         return scrolled;
7913     }
7914 
7915     /**
7916      * Called when this view wants to give up focus. If focus is cleared
7917      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
7918      * <p>
7919      * <strong>Note:</strong> When not in touch-mode, the framework will try to give focus
7920      * to the first focusable View from the top after focus is cleared. Hence, if this
7921      * View is the first from the top that can take focus, then all callbacks
7922      * related to clearing focus will be invoked after which the framework will
7923      * give focus to this view.
7924      * </p>
7925      */
7926     public void clearFocus() {
7927         if (DBG) {
7928             System.out.println(this + " clearFocus()");
7929         }
7930 
7931         final boolean refocus = sAlwaysAssignFocus || !isInTouchMode();
7932         clearFocusInternal(null, true, refocus);
7933     }
7934 
7935     /**
7936      * Clears focus from the view, optionally propagating the change up through
7937      * the parent hierarchy and requesting that the root view place new focus.
7938      *
7939      * @param propagate whether to propagate the change up through the parent
7940      *            hierarchy
7941      * @param refocus when propagate is true, specifies whether to request the
7942      *            root view place new focus
7943      */
7944     void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
7945         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
7946             mPrivateFlags &= ~PFLAG_FOCUSED;
7947             clearParentsWantFocus();
7948 
7949             if (propagate && mParent != null) {
7950                 mParent.clearChildFocus(this);
7951             }
7952 
7953             onFocusChanged(false, 0, null);
7954             refreshDrawableState();
7955 
7956             if (propagate && (!refocus || !rootViewRequestFocus())) {
7957                 notifyGlobalFocusCleared(this);
7958             }
7959         }
7960     }
7961 
7962     void notifyGlobalFocusCleared(View oldFocus) {
7963         if (oldFocus != null && mAttachInfo != null) {
7964             mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
7965         }
7966     }
7967 
7968     boolean rootViewRequestFocus() {
7969         final View root = getRootView();
7970         return root != null && root.requestFocus();
7971     }
7972 
7973     /**
7974      * Called internally by the view system when a new view is getting focus.
7975      * This is what clears the old focus.
7976      * <p>
7977      * <b>NOTE:</b> The parent view's focused child must be updated manually
7978      * after calling this method. Otherwise, the view hierarchy may be left in
7979      * an inconstent state.
7980      */
7981     void unFocus(View focused) {
7982         if (DBG) {
7983             System.out.println(this + " unFocus()");
7984         }
7985 
7986         clearFocusInternal(focused, false, false);
7987     }
7988 
7989     /**
7990      * Returns true if this view has focus itself, or is the ancestor of the
7991      * view that has focus.
7992      *
7993      * @return True if this view has or contains focus, false otherwise.
7994      */
7995     @ViewDebug.ExportedProperty(category = "focus")
7996     public boolean hasFocus() {
7997         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
7998     }
7999 
8000     /**
8001      * Returns true if this view is focusable or if it contains a reachable View
8002      * for which {@link #hasFocusable()} returns {@code true}. A "reachable hasFocusable()"
8003      * is a view whose parents do not block descendants focus.
8004      * Only {@link #VISIBLE} views are considered focusable.
8005      *
8006      * <p>As of {@link Build.VERSION_CODES#O} views that are determined to be focusable
8007      * through {@link #FOCUSABLE_AUTO} will also cause this method to return {@code true}.
8008      * Apps that declare a {@link android.content.pm.ApplicationInfo#targetSdkVersion} of
8009      * earlier than {@link Build.VERSION_CODES#O} will continue to see this method return
8010      * {@code false} for views not explicitly marked as focusable.
8011      * Use {@link #hasExplicitFocusable()} if you require the pre-{@link Build.VERSION_CODES#O}
8012      * behavior.</p>
8013      *
8014      * @return {@code true} if the view is focusable or if the view contains a focusable
8015      *         view, {@code false} otherwise
8016      *
8017      * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
8018      * @see ViewGroup#getTouchscreenBlocksFocus()
8019      * @see #hasExplicitFocusable()
8020      */
8021     public boolean hasFocusable() {
8022         return hasFocusable(!sHasFocusableExcludeAutoFocusable, false);
8023     }
8024 
8025     /**
8026      * Returns true if this view is focusable or if it contains a reachable View
8027      * for which {@link #hasExplicitFocusable()} returns {@code true}.
8028      * A "reachable hasExplicitFocusable()" is a view whose parents do not block descendants focus.
8029      * Only {@link #VISIBLE} views for which {@link #getFocusable()} would return
8030      * {@link #FOCUSABLE} are considered focusable.
8031      *
8032      * <p>This method preserves the pre-{@link Build.VERSION_CODES#O} behavior of
8033      * {@link #hasFocusable()} in that only views explicitly set focusable will cause
8034      * this method to return true. A view set to {@link #FOCUSABLE_AUTO} that resolves
8035      * to focusable will not.</p>
8036      *
8037      * @return {@code true} if the view is focusable or if the view contains a focusable
8038      *         view, {@code false} otherwise
8039      *
8040      * @see #hasFocusable()
8041      */
8042     public boolean hasExplicitFocusable() {
8043         return hasFocusable(false, true);
8044     }
8045 
8046     boolean hasFocusable(boolean allowAutoFocus, boolean dispatchExplicit) {
8047         if (!isFocusableInTouchMode()) {
8048             for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
8049                 final ViewGroup g = (ViewGroup) p;
8050                 if (g.shouldBlockFocusForTouchscreen()) {
8051                     return false;
8052                 }
8053             }
8054         }
8055 
8056         // Invisible, gone, or disabled views are never focusable.
8057         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE
8058                 || (mViewFlags & ENABLED_MASK) != ENABLED) {
8059             return false;
8060         }
8061 
8062         // Only use effective focusable value when allowed.
8063         if ((allowAutoFocus || getFocusable() != FOCUSABLE_AUTO) && isFocusable()) {
8064             return true;
8065         }
8066 
8067         return false;
8068     }
8069 
8070     /**
8071      * Called by the view system when the focus state of this view changes.
8072      * When the focus change event is caused by directional navigation, direction
8073      * and previouslyFocusedRect provide insight into where the focus is coming from.
8074      * When overriding, be sure to call up through to the super class so that
8075      * the standard focus handling will occur.
8076      *
8077      * @param gainFocus True if the View has focus; false otherwise.
8078      * @param direction The direction focus has moved when requestFocus()
8079      *                  is called to give this view focus. Values are
8080      *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
8081      *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
8082      *                  It may not always apply, in which case use the default.
8083      * @param previouslyFocusedRect The rectangle, in this view's coordinate
8084      *        system, of the previously focused view.  If applicable, this will be
8085      *        passed in as finer grained information about where the focus is coming
8086      *        from (in addition to direction).  Will be <code>null</code> otherwise.
8087      */
8088     @CallSuper
8089     protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
8090             @Nullable Rect previouslyFocusedRect) {
8091         if (gainFocus) {
8092             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
8093         } else {
8094             notifyViewAccessibilityStateChangedIfNeeded(
8095                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8096         }
8097 
8098         // Here we check whether we still need the default focus highlight, and switch it on/off.
8099         switchDefaultFocusHighlight();
8100 
8101         if (!gainFocus) {
8102             if (isPressed()) {
8103                 setPressed(false);
8104             }
8105             if (hasWindowFocus()) {
8106                 notifyFocusChangeToImeFocusController(false /* hasFocus */);
8107             }
8108             onFocusLost();
8109         } else if (hasWindowFocus()) {
8110             notifyFocusChangeToImeFocusController(true /* hasFocus */);
8111         }
8112 
8113         invalidate(true);
8114         ListenerInfo li = mListenerInfo;
8115         if (li != null && li.mOnFocusChangeListener != null) {
8116             li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
8117         }
8118 
8119         if (mAttachInfo != null) {
8120             mAttachInfo.mKeyDispatchState.reset(this);
8121         }
8122 
8123         if (mParent != null) {
8124             mParent.onDescendantUnbufferedRequested();
8125         }
8126 
8127         notifyEnterOrExitForAutoFillIfNeeded(gainFocus);
8128     }
8129 
8130     /**
8131      * Notify {@link ImeFocusController} about the focus change of the {@link View}.
8132      *
8133      * @param hasFocus {@code true} when the {@link View} is being focused.
8134      */
8135     private void notifyFocusChangeToImeFocusController(boolean hasFocus) {
8136         if (mAttachInfo == null) {
8137             return;
8138         }
8139         mAttachInfo.mViewRootImpl.getImeFocusController().onViewFocusChanged(this, hasFocus);
8140     }
8141 
8142     /** @hide */
8143     public void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {
8144         if (canNotifyAutofillEnterExitEvent()) {
8145             AutofillManager afm = getAutofillManager();
8146             if (afm != null) {
8147                 if (enter && isFocused()) {
8148                     // We have not been laid out yet, hence cannot evaluate
8149                     // whether this view is visible to the user, we will do
8150                     // the evaluation once layout is complete.
8151                     if (!isLaidOut()) {
8152                         mPrivateFlags3 |= PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
8153                     } else if (isVisibleToUser()) {
8154                         // TODO This is a potential problem that View gets focus before it's visible
8155                         // to User. Ideally View should handle the event when isVisibleToUser()
8156                         // becomes true where it should issue notifyViewEntered().
8157                         afm.notifyViewEntered(this);
8158                     }
8159                 } else if (!enter && !isFocused()) {
8160                     afm.notifyViewExited(this);
8161                 }
8162             }
8163         }
8164     }
8165 
8166     /**
8167      * Visually distinct portion of a window with window-like semantics are considered panes for
8168      * accessibility purposes. One example is the content view of a fragment that is replaced.
8169      * In order for accessibility services to understand a pane's window-like behavior, panes
8170      * should have descriptive titles. Views with pane titles produce {@link AccessibilityEvent}s
8171      * when they appear, disappear, or change title.
8172      *
8173      * @param accessibilityPaneTitle The pane's title. Setting to {@code null} indicates that this
8174      *                               View is not a pane.
8175      *
8176      * {@see AccessibilityNodeInfo#setPaneTitle(CharSequence)}
8177      *
8178      * @attr ref android.R.styleable#View_accessibilityPaneTitle
8179      */
8180     public void setAccessibilityPaneTitle(@Nullable CharSequence accessibilityPaneTitle) {
8181         if (!TextUtils.equals(accessibilityPaneTitle, mAccessibilityPaneTitle)) {
8182             mAccessibilityPaneTitle = accessibilityPaneTitle;
8183             notifyViewAccessibilityStateChangedIfNeeded(
8184                     AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_TITLE);
8185         }
8186     }
8187 
8188     /**
8189      * Get the title of the pane for purposes of accessibility.
8190      *
8191      * @return The current pane title.
8192      *
8193      * {@see #setAccessibilityPaneTitle}.
8194      *
8195      * @attr ref android.R.styleable#View_accessibilityPaneTitle
8196      */
8197     @InspectableProperty
8198     @Nullable
8199     public CharSequence getAccessibilityPaneTitle() {
8200         return mAccessibilityPaneTitle;
8201     }
8202 
8203     private boolean isAccessibilityPane() {
8204         return mAccessibilityPaneTitle != null;
8205     }
8206 
8207     /**
8208      * Sends an accessibility event of the given type. If accessibility is
8209      * not enabled this method has no effect. The default implementation calls
8210      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
8211      * to populate information about the event source (this View), then calls
8212      * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
8213      * populate the text content of the event source including its descendants,
8214      * and last calls
8215      * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
8216      * on its parent to request sending of the event to interested parties.
8217      * <p>
8218      * If an {@link AccessibilityDelegate} has been specified via calling
8219      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8220      * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
8221      * responsible for handling this call.
8222      * </p>
8223      *
8224      * @param eventType The type of the event to send, as defined by several types from
8225      * {@link android.view.accessibility.AccessibilityEvent}, such as
8226      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
8227      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
8228      *
8229      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
8230      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
8231      * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
8232      * @see AccessibilityDelegate
8233      */
8234     public void sendAccessibilityEvent(int eventType) {
8235         if (mAccessibilityDelegate != null) {
8236             mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
8237         } else {
8238             sendAccessibilityEventInternal(eventType);
8239         }
8240     }
8241 
8242     /**
8243      * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
8244      * {@link AccessibilityEvent} to suggest that an accessibility service announce the
8245      * specified text to its users.
8246      * <p>
8247      * Note: The event generated with this API carries no semantic meaning, and is appropriate only
8248      * in exceptional situations. Apps can generally achieve correct behavior for accessibility by
8249      * accurately supplying the semantics of their UI.
8250      * They should not need to specify what exactly is announced to users.
8251      *
8252      * @param text The announcement text.
8253      */
8254     public void announceForAccessibility(CharSequence text) {
8255         if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
8256             AccessibilityEvent event = AccessibilityEvent.obtain(
8257                     AccessibilityEvent.TYPE_ANNOUNCEMENT);
8258             onInitializeAccessibilityEvent(event);
8259             event.getText().add(text);
8260             event.setContentDescription(null);
8261             mParent.requestSendAccessibilityEvent(this, event);
8262         }
8263     }
8264 
8265     /**
8266      * @see #sendAccessibilityEvent(int)
8267      *
8268      * Note: Called from the default {@link AccessibilityDelegate}.
8269      *
8270      * @hide
8271      */
8272     public void sendAccessibilityEventInternal(int eventType) {
8273         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
8274             sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
8275         }
8276     }
8277 
8278     /**
8279      * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
8280      * takes as an argument an empty {@link AccessibilityEvent} and does not
8281      * perform a check whether accessibility is enabled.
8282      * <p>
8283      * If an {@link AccessibilityDelegate} has been specified via calling
8284      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8285      * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
8286      * is responsible for handling this call.
8287      * </p>
8288      *
8289      * @param event The event to send.
8290      *
8291      * @see #sendAccessibilityEvent(int)
8292      */
8293     public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
8294         if (mAccessibilityDelegate != null) {
8295             mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
8296         } else {
8297             sendAccessibilityEventUncheckedInternal(event);
8298         }
8299     }
8300 
8301     /**
8302      * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
8303      *
8304      * Note: Called from the default {@link AccessibilityDelegate}.
8305      *
8306      * @hide
8307      */
8308     public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
8309         // Panes disappearing are relevant even if though the view is no longer visible.
8310         boolean isWindowStateChanged =
8311                 (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
8312         boolean isWindowDisappearedEvent = isWindowStateChanged && ((event.getContentChangeTypes()
8313                 & AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED) != 0);
8314         if (!isShown() && !isWindowDisappearedEvent) {
8315             return;
8316         }
8317         onInitializeAccessibilityEvent(event);
8318         // Only a subset of accessibility events populates text content.
8319         if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
8320             dispatchPopulateAccessibilityEvent(event);
8321         }
8322         SendAccessibilityEventThrottle throttle = getThrottleForAccessibilityEvent(event);
8323         if (throttle != null) {
8324             throttle.post(event);
8325         } else {
8326             requestParentSendAccessibilityEvent(event);
8327         }
8328     }
8329 
8330     private void requestParentSendAccessibilityEvent(AccessibilityEvent event) {
8331         ViewParent parent = getParent();
8332         if (parent != null) {
8333             getParent().requestSendAccessibilityEvent(this, event);
8334         }
8335     }
8336 
8337     private SendAccessibilityEventThrottle getThrottleForAccessibilityEvent(
8338             AccessibilityEvent event) {
8339         if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
8340             if (mSendViewScrolledAccessibilityEvent == null) {
8341                 mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
8342             }
8343             return mSendViewScrolledAccessibilityEvent;
8344         }
8345         boolean isStateContentChanged = (event.getContentChangeTypes()
8346                 & AccessibilityEvent.CONTENT_CHANGE_TYPE_STATE_DESCRIPTION) != 0;
8347         if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
8348                 && isStateContentChanged) {
8349             if (mSendStateChangedAccessibilityEvent == null) {
8350                 mSendStateChangedAccessibilityEvent = new SendAccessibilityEventThrottle();
8351             }
8352             return mSendStateChangedAccessibilityEvent;
8353         }
8354         return null;
8355     }
8356 
8357     private void clearAccessibilityThrottles() {
8358         cancel(mSendViewScrolledAccessibilityEvent);
8359         cancel(mSendStateChangedAccessibilityEvent);
8360     }
8361 
8362     /**
8363      * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
8364      * to its children for adding their text content to the event. Note that the
8365      * event text is populated in a separate dispatch path since we add to the
8366      * event not only the text of the source but also the text of all its descendants.
8367      * A typical implementation will call
8368      * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
8369      * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
8370      * on each child. Override this method if custom population of the event text
8371      * content is required.
8372      * <p>
8373      * If an {@link AccessibilityDelegate} has been specified via calling
8374      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8375      * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
8376      * is responsible for handling this call.
8377      * </p>
8378      * <p>
8379      * <em>Note:</em> Accessibility events of certain types are not dispatched for
8380      * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
8381      * </p>
8382      *
8383      * @param event The event.
8384      *
8385      * @return True if the event population was completed.
8386      */
8387     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
8388         if (mAccessibilityDelegate != null) {
8389             return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
8390         } else {
8391             return dispatchPopulateAccessibilityEventInternal(event);
8392         }
8393     }
8394 
8395     /**
8396      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
8397      *
8398      * Note: Called from the default {@link AccessibilityDelegate}.
8399      *
8400      * @hide
8401      */
8402     public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
8403         onPopulateAccessibilityEvent(event);
8404         return false;
8405     }
8406 
8407     /**
8408      * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
8409      * giving a chance to this View to populate the accessibility event with its
8410      * text content. While this method is free to modify event
8411      * attributes other than text content, doing so should normally be performed in
8412      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
8413      * <p>
8414      * Example: Adding formatted date string to an accessibility event in addition
8415      *          to the text added by the super implementation:
8416      * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
8417      *     super.onPopulateAccessibilityEvent(event);
8418      *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
8419      *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
8420      *         mCurrentDate.getTimeInMillis(), flags);
8421      *     event.getText().add(selectedDateUtterance);
8422      * }</pre>
8423      * <p>
8424      * If an {@link AccessibilityDelegate} has been specified via calling
8425      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8426      * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
8427      * is responsible for handling this call.
8428      * </p>
8429      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
8430      * information to the event, in case the default implementation has basic information to add.
8431      * </p>
8432      *
8433      * @param event The accessibility event which to populate.
8434      *
8435      * @see #sendAccessibilityEvent(int)
8436      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
8437      */
8438     @CallSuper
8439     public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
8440         if (mAccessibilityDelegate != null) {
8441             mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
8442         } else {
8443             onPopulateAccessibilityEventInternal(event);
8444         }
8445     }
8446 
8447     /**
8448      * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
8449      *
8450      * Note: Called from the default {@link AccessibilityDelegate}.
8451      *
8452      * @hide
8453      */
8454     public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
8455         if ((event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED)
8456                 && isAccessibilityPane()) {
8457             event.getText().add(getAccessibilityPaneTitle());
8458         }
8459     }
8460 
8461     /**
8462      * Initializes an {@link AccessibilityEvent} with information about
8463      * this View which is the event source. In other words, the source of
8464      * an accessibility event is the view whose state change triggered firing
8465      * the event.
8466      * <p>
8467      * Example: Setting the password property of an event in addition
8468      *          to properties set by the super implementation:
8469      * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
8470      *     super.onInitializeAccessibilityEvent(event);
8471      *     event.setPassword(true);
8472      * }</pre>
8473      * <p>
8474      * If an {@link AccessibilityDelegate} has been specified via calling
8475      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8476      * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
8477      * is responsible for handling this call.
8478      * </p>
8479      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
8480      * information to the event, in case the default implementation has basic information to add.
8481      * </p>
8482      * @param event The event to initialize.
8483      *
8484      * @see #sendAccessibilityEvent(int)
8485      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
8486      */
8487     @CallSuper
8488     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
8489         if (mAccessibilityDelegate != null) {
8490             mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
8491         } else {
8492             onInitializeAccessibilityEventInternal(event);
8493         }
8494     }
8495 
8496     /**
8497      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
8498      *
8499      * Note: Called from the default {@link AccessibilityDelegate}.
8500      *
8501      * @hide
8502      */
8503     @UnsupportedAppUsage
8504     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
8505         event.setSource(this);
8506         event.setClassName(getAccessibilityClassName());
8507         event.setPackageName(getContext().getPackageName());
8508         event.setEnabled(isEnabled());
8509         event.setContentDescription(mContentDescription);
8510         event.setScrollX(getScrollX());
8511         event.setScrollY(getScrollY());
8512 
8513         switch (event.getEventType()) {
8514             case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
8515                 ArrayList<View> focusablesTempList = (mAttachInfo != null)
8516                         ? mAttachInfo.mTempArrayList : new ArrayList<View>();
8517                 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
8518                 event.setItemCount(focusablesTempList.size());
8519                 event.setCurrentItemIndex(focusablesTempList.indexOf(this));
8520                 if (mAttachInfo != null) {
8521                     focusablesTempList.clear();
8522                 }
8523             } break;
8524             case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
8525                 CharSequence text = getIterableTextForAccessibility();
8526                 if (text != null && text.length() > 0) {
8527                     event.setFromIndex(getAccessibilitySelectionStart());
8528                     event.setToIndex(getAccessibilitySelectionEnd());
8529                     event.setItemCount(text.length());
8530                 }
8531             } break;
8532         }
8533     }
8534 
8535     /**
8536      * Returns an {@link AccessibilityNodeInfo} representing this view from the
8537      * point of view of an {@link android.accessibilityservice.AccessibilityService}.
8538      * This method is responsible for obtaining an accessibility node info from a
8539      * pool of reusable instances and calling
8540      * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
8541      * initialize the former.
8542      * <p>
8543      * Note: The client is responsible for recycling the obtained instance by calling
8544      *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
8545      * </p>
8546      *
8547      * @return A populated {@link AccessibilityNodeInfo}.
8548      *
8549      * @see AccessibilityNodeInfo
8550      */
8551     public AccessibilityNodeInfo createAccessibilityNodeInfo() {
8552         if (mAccessibilityDelegate != null) {
8553             return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
8554         } else {
8555             return createAccessibilityNodeInfoInternal();
8556         }
8557     }
8558 
8559     /**
8560      * @see #createAccessibilityNodeInfo()
8561      *
8562      * @hide
8563      */
8564     public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
8565         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
8566         if (provider != null) {
8567             return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
8568         } else {
8569             AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
8570             onInitializeAccessibilityNodeInfo(info);
8571             return info;
8572         }
8573     }
8574 
8575     /**
8576      * Initializes an {@link AccessibilityNodeInfo} with information about this view.
8577      * The base implementation sets:
8578      * <ul>
8579      *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
8580      *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
8581      *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
8582      *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
8583      *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
8584      *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
8585      *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
8586      *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
8587      *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
8588      *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
8589      *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
8590      *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
8591      *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
8592      * </ul>
8593      * <p>
8594      * Subclasses should override this method, call the super implementation,
8595      * and set additional attributes.
8596      * </p>
8597      * <p>
8598      * If an {@link AccessibilityDelegate} has been specified via calling
8599      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8600      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
8601      * is responsible for handling this call.
8602      * </p>
8603      *
8604      * @param info The instance to initialize.
8605      */
8606     @CallSuper
8607     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
8608         if (mAccessibilityDelegate != null) {
8609             mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
8610         } else {
8611             onInitializeAccessibilityNodeInfoInternal(info);
8612         }
8613     }
8614 
8615     /**
8616      * Gets the location of this view in screen coordinates.
8617      *
8618      * @param outRect The output location
8619      * @hide
8620      */
8621     @UnsupportedAppUsage
8622     public void getBoundsOnScreen(Rect outRect) {
8623         getBoundsOnScreen(outRect, false);
8624     }
8625 
8626     /**
8627      * Gets the location of this view in screen coordinates.
8628      *
8629      * @param outRect The output location
8630      * @param clipToParent Whether to clip child bounds to the parent ones.
8631      * @hide
8632      */
8633     @UnsupportedAppUsage
8634     public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
8635         if (mAttachInfo == null) {
8636             return;
8637         }
8638 
8639         RectF position = mAttachInfo.mTmpTransformRect;
8640         position.set(0, 0, mRight - mLeft, mBottom - mTop);
8641         mapRectFromViewToScreenCoords(position, clipToParent);
8642         outRect.set(Math.round(position.left), Math.round(position.top),
8643                 Math.round(position.right), Math.round(position.bottom));
8644     }
8645 
8646     /**
8647      * Map a rectangle from view-relative coordinates to screen-relative coordinates
8648      *
8649      * @param rect The rectangle to be mapped
8650      * @param clipToParent Whether to clip child bounds to the parent ones.
8651      * @hide
8652      */
8653     public void mapRectFromViewToScreenCoords(RectF rect, boolean clipToParent) {
8654         if (!hasIdentityMatrix()) {
8655             getMatrix().mapRect(rect);
8656         }
8657 
8658         rect.offset(mLeft, mTop);
8659 
8660         ViewParent parent = mParent;
8661         while (parent instanceof View) {
8662             View parentView = (View) parent;
8663 
8664             rect.offset(-parentView.mScrollX, -parentView.mScrollY);
8665 
8666             if (clipToParent) {
8667                 rect.left = Math.max(rect.left, 0);
8668                 rect.top = Math.max(rect.top, 0);
8669                 rect.right = Math.min(rect.right, parentView.getWidth());
8670                 rect.bottom = Math.min(rect.bottom, parentView.getHeight());
8671             }
8672 
8673             if (!parentView.hasIdentityMatrix()) {
8674                 parentView.getMatrix().mapRect(rect);
8675             }
8676 
8677             rect.offset(parentView.mLeft, parentView.mTop);
8678 
8679             parent = parentView.mParent;
8680         }
8681 
8682         if (parent instanceof ViewRootImpl) {
8683             ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
8684             rect.offset(0, -viewRootImpl.mCurScrollY);
8685         }
8686 
8687         rect.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
8688     }
8689 
8690     /**
8691      * Return the class name of this object to be used for accessibility purposes.
8692      * Subclasses should only override this if they are implementing something that
8693      * should be seen as a completely new class of view when used by accessibility,
8694      * unrelated to the class it is deriving from.  This is used to fill in
8695      * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
8696      */
8697     public CharSequence getAccessibilityClassName() {
8698         return View.class.getName();
8699     }
8700 
8701     /**
8702      * Called when assist structure is being retrieved from a view as part of
8703      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
8704      * @param structure Fill in with structured view data.  The default implementation
8705      * fills in all data that can be inferred from the view itself.
8706      */
8707     public void onProvideStructure(ViewStructure structure) {
8708         onProvideStructure(structure, VIEW_STRUCTURE_FOR_ASSIST, /* flags= */ 0);
8709     }
8710 
8711     /**
8712      * Populates a {@link ViewStructure} to fullfil an autofill request.
8713      *
8714      * <p>The structure should contain at least the following properties:
8715      * <ul>
8716      *   <li>Autofill id ({@link ViewStructure#setAutofillId(AutofillId, int)}).
8717      *   <li>Autofill type ({@link ViewStructure#setAutofillType(int)}).
8718      *   <li>Autofill value ({@link ViewStructure#setAutofillValue(AutofillValue)}).
8719      *   <li>Whether the data is sensitive ({@link ViewStructure#setDataIsSensitive(boolean)}).
8720      * </ul>
8721      *
8722      * <p>It's also recommended to set the following properties - the more properties the structure
8723      * has, the higher the chances of an {@link android.service.autofill.AutofillService} properly
8724      * using the structure:
8725      *
8726      * <ul>
8727      *   <li>Autofill hints ({@link ViewStructure#setAutofillHints(String[])}).
8728      *   <li>Autofill options ({@link ViewStructure#setAutofillOptions(CharSequence[])}) when the
8729      *       view can only be filled with predefined values (typically used when the autofill type
8730      *       is {@link #AUTOFILL_TYPE_LIST}).
8731      *   <li>Resource id ({@link ViewStructure#setId(int, String, String, String)}).
8732      *   <li>Class name ({@link ViewStructure#setClassName(String)}).
8733      *   <li>Content description ({@link ViewStructure#setContentDescription(CharSequence)}).
8734      *   <li>Visual properties such as visibility ({@link ViewStructure#setVisibility(int)}),
8735      *       dimensions ({@link ViewStructure#setDimens(int, int, int, int, int, int)}), and
8736      *       opacity ({@link ViewStructure#setOpaque(boolean)}).
8737      *   <li>For views representing text fields, text properties such as the text itself
8738      *       ({@link ViewStructure#setText(CharSequence)}), text hints
8739      *       ({@link ViewStructure#setHint(CharSequence)}, input type
8740      *       ({@link ViewStructure#setInputType(int)}),
8741      *   <li>For views representing HTML nodes, its web domain
8742      *       ({@link ViewStructure#setWebDomain(String)}) and HTML properties
8743      *       (({@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}).
8744      * </ul>
8745      *
8746      * <p>The default implementation of this method already sets most of these properties based on
8747      * related {@link View} methods (for example, the autofill id is set using
8748      * {@link #getAutofillId()}, the autofill type set using {@link #getAutofillType()}, etc.),
8749      * and views in the standard Android widgets library also override it to set their
8750      * relevant properties (for example, {@link android.widget.TextView} already sets the text
8751      * properties), so it's recommended to only override this method
8752      * (and call {@code super.onProvideAutofillStructure()}) when:
8753      *
8754      * <ul>
8755      *   <li>The view contents does not include PII (Personally Identifiable Information), so it
8756      *       can call {@link ViewStructure#setDataIsSensitive(boolean)} passing {@code false}.
8757      *   <li>The view can only be autofilled with predefined options, so it can call
8758      *       {@link ViewStructure#setAutofillOptions(CharSequence[])}.
8759      * </ul>
8760      *
8761      * <p><b>Note:</b> The {@code left} and {@code top} values set in
8762      * {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the next
8763      * {@link ViewGroup#isImportantForAutofill()} predecessor view included in the structure.
8764      *
8765      * <p>Views support the Autofill Framework mainly by:
8766      * <ul>
8767      *   <li>Providing the metadata defining what the view means and how it can be autofilled.
8768      *   <li>Notifying the Android System when the view value changed by calling
8769      *       {@link AutofillManager#notifyValueChanged(View)}.
8770      *   <li>Implementing the methods that autofill the view.
8771      * </ul>
8772      * <p>This method is responsible for the former; {@link #autofill(AutofillValue)} is responsible
8773      * for the latter.
8774      *
8775      * @param structure fill in with structured view data for autofill purposes.
8776      * @param flags optional flags.
8777      *
8778      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
8779      */
8780     public void onProvideAutofillStructure(ViewStructure structure, @AutofillFlags int flags) {
8781         onProvideStructure(structure, VIEW_STRUCTURE_FOR_AUTOFILL, flags);
8782     }
8783 
8784     /**
8785      * Populates a {@link ViewStructure} for content capture.
8786      *
8787      * <p>This method is called after a view is that is eligible for content capture
8788      * (for example, if it {@link #isImportantForAutofill()}, an intelligence service is enabled for
8789      * the user, and the activity rendering the view is enabled for content capture) is laid out and
8790      * is visible.
8791      *
8792      * <p>The populated structure is then passed to the service through
8793      * {@link ContentCaptureSession#notifyViewAppeared(ViewStructure)}.
8794      *
8795      * <p><b>Note: </b>views that manage a virtual structure under this view must populate just
8796      * the node representing this view and return right away, then asynchronously report (not
8797      * necessarily in the UI thread) when the children nodes appear, disappear or have their text
8798      * changed by calling
8799      * {@link ContentCaptureSession#notifyViewAppeared(ViewStructure)},
8800      * {@link ContentCaptureSession#notifyViewDisappeared(AutofillId)}, and
8801      * {@link ContentCaptureSession#notifyViewTextChanged(AutofillId, CharSequence)}
8802      * respectively. The structure for the a child must be created using
8803      * {@link ContentCaptureSession#newVirtualViewStructure(AutofillId, long)}, and the
8804      * {@code autofillId} for a child can be obtained either through
8805      * {@code childStructure.getAutofillId()} or
8806      * {@link ContentCaptureSession#newAutofillId(AutofillId, long)}.
8807      *
8808      * <p>When the virtual view hierarchy represents a web page, you should also:
8809      *
8810      * <ul>
8811      *   <li>Call {@link ContentCaptureManager#getContentCaptureConditions()} to infer content
8812      *   capture events should be generate for that URL.
8813      *   <li>Create a new {@link ContentCaptureSession} child for every HTML element that
8814      *   renders a new URL (like an {@code IFRAME}) and use that session to notify events from
8815      *   that subtree.
8816      * </ul>
8817      *
8818      * <p><b>Note: </b>the following methods of the {@code structure} will be ignored:
8819      * <ul>
8820      *   <li>{@link ViewStructure#setChildCount(int)}
8821      *   <li>{@link ViewStructure#addChildCount(int)}
8822      *   <li>{@link ViewStructure#getChildCount()}
8823      *   <li>{@link ViewStructure#newChild(int)}
8824      *   <li>{@link ViewStructure#asyncNewChild(int)}
8825      *   <li>{@link ViewStructure#asyncCommit()}
8826      *   <li>{@link ViewStructure#setWebDomain(String)}
8827      *   <li>{@link ViewStructure#newHtmlInfoBuilder(String)}
8828      *   <li>{@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}
8829      *   <li>{@link ViewStructure#setDataIsSensitive(boolean)}
8830      *   <li>{@link ViewStructure#setAlpha(float)}
8831      *   <li>{@link ViewStructure#setElevation(float)}
8832      *   <li>{@link ViewStructure#setTransformation(Matrix)}
8833      *
8834      * </ul>
8835      */
8836     public void onProvideContentCaptureStructure(@NonNull ViewStructure structure, int flags) {
8837         onProvideStructure(structure, VIEW_STRUCTURE_FOR_CONTENT_CAPTURE, flags);
8838     }
8839 
8840     /** @hide */
8841     protected void onProvideStructure(@NonNull ViewStructure structure,
8842             @ViewStructureType int viewFor, int flags) {
8843         final int id = mID;
8844         if (id != NO_ID && !isViewIdGenerated(id)) {
8845             String pkg, type, entry;
8846             try {
8847                 final Resources res = getResources();
8848                 entry = res.getResourceEntryName(id);
8849                 type = res.getResourceTypeName(id);
8850                 pkg = res.getResourcePackageName(id);
8851             } catch (Resources.NotFoundException e) {
8852                 entry = type = pkg = null;
8853             }
8854             structure.setId(id, pkg, type, entry);
8855         } else {
8856             structure.setId(id, null, null, null);
8857         }
8858 
8859         if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
8860                 || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
8861             final @AutofillType int autofillType = getAutofillType();
8862             // Don't need to fill autofill info if view does not support it.
8863             // For example, only TextViews that are editable support autofill
8864             if (autofillType != AUTOFILL_TYPE_NONE) {
8865                 structure.setAutofillType(autofillType);
8866                 structure.setAutofillHints(getAutofillHints());
8867                 structure.setAutofillValue(getAutofillValue());
8868             }
8869             structure.setImportantForAutofill(getImportantForAutofill());
8870         }
8871 
8872         int ignoredParentLeft = 0;
8873         int ignoredParentTop = 0;
8874         if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
8875                 && (flags & AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) {
8876             View parentGroup = null;
8877 
8878             ViewParent viewParent = getParent();
8879             if (viewParent instanceof View) {
8880                 parentGroup = (View) viewParent;
8881             }
8882 
8883             while (parentGroup != null && !parentGroup.isImportantForAutofill()) {
8884                 ignoredParentLeft += parentGroup.mLeft;
8885                 ignoredParentTop += parentGroup.mTop;
8886 
8887                 viewParent = parentGroup.getParent();
8888                 if (viewParent instanceof View) {
8889                     parentGroup = (View) viewParent;
8890                 } else {
8891                     break;
8892                 }
8893             }
8894         }
8895 
8896         structure.setDimens(ignoredParentLeft + mLeft, ignoredParentTop + mTop, mScrollX, mScrollY,
8897                 mRight - mLeft, mBottom - mTop);
8898         if (viewFor == VIEW_STRUCTURE_FOR_ASSIST) {
8899             if (!hasIdentityMatrix()) {
8900                 structure.setTransformation(getMatrix());
8901             }
8902             structure.setElevation(getZ());
8903         }
8904         structure.setVisibility(getVisibility());
8905         structure.setEnabled(isEnabled());
8906         if (isClickable()) {
8907             structure.setClickable(true);
8908         }
8909         if (isFocusable()) {
8910             structure.setFocusable(true);
8911         }
8912         if (isFocused()) {
8913             structure.setFocused(true);
8914         }
8915         if (isAccessibilityFocused()) {
8916             structure.setAccessibilityFocused(true);
8917         }
8918         if (isSelected()) {
8919             structure.setSelected(true);
8920         }
8921         if (isActivated()) {
8922             structure.setActivated(true);
8923         }
8924         if (isLongClickable()) {
8925             structure.setLongClickable(true);
8926         }
8927         if (this instanceof Checkable) {
8928             structure.setCheckable(true);
8929             if (((Checkable)this).isChecked()) {
8930                 structure.setChecked(true);
8931             }
8932         }
8933         if (isOpaque()) {
8934             structure.setOpaque(true);
8935         }
8936         if (isContextClickable()) {
8937             structure.setContextClickable(true);
8938         }
8939         structure.setClassName(getAccessibilityClassName().toString());
8940         structure.setContentDescription(getContentDescription());
8941     }
8942 
8943     /**
8944      * Called when assist structure is being retrieved from a view as part of
8945      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
8946      * generate additional virtual structure under this view.  The defaullt implementation
8947      * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
8948      * view's virtual accessibility nodes, if any.  You can override this for a more
8949      * optimal implementation providing this data.
8950      */
8951     public void onProvideVirtualStructure(ViewStructure structure) {
8952         onProvideVirtualStructureCompat(structure, false);
8953     }
8954 
8955     /**
8956      * Fallback implementation to populate a ViewStructure from accessibility state.
8957      *
8958      * @param structure The structure to populate.
8959      * @param forAutofill Whether the structure is needed for autofill.
8960      */
8961     private void onProvideVirtualStructureCompat(ViewStructure structure, boolean forAutofill) {
8962         final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
8963         if (provider != null) {
8964             if (forAutofill && Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
8965                 Log.v(AUTOFILL_LOG_TAG, "onProvideVirtualStructureCompat() for " + this);
8966             }
8967             final AccessibilityNodeInfo info = createAccessibilityNodeInfo();
8968             structure.setChildCount(1);
8969             final ViewStructure root = structure.newChild(0);
8970             populateVirtualStructure(root, provider, info, forAutofill);
8971             info.recycle();
8972         }
8973     }
8974 
8975     /**
8976      * Populates a {@link ViewStructure} containing virtual children to fullfil an autofill
8977      * request.
8978      *
8979      * <p>This method should be used when the view manages a virtual structure under this view. For
8980      * example, a view that draws input fields using {@link #draw(Canvas)}.
8981      *
8982      * <p>When implementing this method, subclasses must follow the rules below:
8983      *
8984      * <ul>
8985      *   <li>Add virtual children by calling the {@link ViewStructure#newChild(int)} or
8986      *       {@link ViewStructure#asyncNewChild(int)} methods, where the {@code id} is an unique id
8987      *       identifying the children in the virtual structure.
8988      *   <li>The children hierarchy can have multiple levels if necessary, but ideally it should
8989      *       exclude intermediate levels that are irrelevant for autofill; that would improve the
8990      *       autofill performance.
8991      *   <li>Also implement {@link #autofill(SparseArray)} to autofill the virtual
8992      *       children.
8993      *   <li>Set the autofill properties of the child structure as defined by
8994      *       {@link #onProvideAutofillStructure(ViewStructure, int)}, using
8995      *       {@link ViewStructure#setAutofillId(AutofillId, int)} to set its autofill id.
8996      *   <li>Call {@link android.view.autofill.AutofillManager#notifyViewEntered(View, int, Rect)}
8997      *       and/or {@link android.view.autofill.AutofillManager#notifyViewExited(View, int)}
8998      *       when the focused virtual child changed.
8999      *   <li>Override {@link #isVisibleToUserForAutofill(int)} to allow the platform to query
9000      *       whether a given virtual view is visible to the user in order to support triggering
9001      *       save when all views of interest go away.
9002      *   <li>Call
9003      *    {@link android.view.autofill.AutofillManager#notifyValueChanged(View, int, AutofillValue)}
9004      *       when the value of a virtual child changed.
9005      *   <li>Call {@link
9006      *    android.view.autofill.AutofillManager#notifyViewVisibilityChanged(View, int, boolean)}
9007      *       when the visibility of a virtual child changed.
9008      *   <li>Call
9009      *    {@link android.view.autofill.AutofillManager#notifyViewClicked(View, int)} when a virtual
9010      *       child is clicked.
9011      *   <li>Call {@link AutofillManager#commit()} when the autofill context of the view structure
9012      *       changed and the current context should be committed (for example, when the user tapped
9013      *       a {@code SUBMIT} button in an HTML page).
9014      *   <li>Call {@link AutofillManager#cancel()} when the autofill context of the view structure
9015      *       changed and the current context should be canceled (for example, when the user tapped
9016      *       a {@code CANCEL} button in an HTML page).
9017      *   <li>Provide ways for users to manually request autofill by calling
9018      *       {@link AutofillManager#requestAutofill(View, int, Rect)}.
9019      *   <li>The {@code left} and {@code top} values set in
9020      *       {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the
9021      *       next {@link ViewGroup#isImportantForAutofill()} predecessor view included in the
9022      *       structure.
9023      * </ul>
9024      *
9025      * <p>Views with virtual children support the Autofill Framework mainly by:
9026      * <ul>
9027      *   <li>Providing the metadata defining what the virtual children mean and how they can be
9028      *       autofilled.
9029      *   <li>Implementing the methods that autofill the virtual children.
9030      * </ul>
9031      * <p>This method is responsible for the former; {@link #autofill(SparseArray)} is responsible
9032      * for the latter.
9033      *
9034      * @param structure fill in with virtual children data for autofill purposes.
9035      * @param flags optional flags.
9036      *
9037      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
9038      */
9039     public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
9040         if (mContext.isAutofillCompatibilityEnabled()) {
9041             onProvideVirtualStructureCompat(structure, true);
9042         }
9043     }
9044 
9045     /**
9046      * Automatically fills the content of this view with the {@code value}.
9047      *
9048      * <p>Views support the Autofill Framework mainly by:
9049      * <ul>
9050      *   <li>Providing the metadata defining what the view means and how it can be autofilled.
9051      *   <li>Implementing the methods that autofill the view.
9052      * </ul>
9053      * <p>{@link #onProvideAutofillStructure(ViewStructure, int)} is responsible for the former,
9054      * this method is responsible for latter.
9055      *
9056      * <p>This method does nothing by default, but when overridden it typically:
9057      * <ol>
9058      *   <li>Checks if the provided value matches the expected type (which is defined by
9059      *       {@link #getAutofillType()}).
9060      *   <li>Checks if the view is editable - if it isn't, it should return right away.
9061      *   <li>Call the proper getter method on {@link AutofillValue} to fetch the actual value.
9062      *   <li>Pass the actual value to the equivalent setter in the view.
9063      * </ol>
9064      *
9065      * <p>For example, a text-field view could implement the method this way:
9066      *
9067      * <pre class="prettyprint">
9068      * &#64;Override
9069      * public void autofill(AutofillValue value) {
9070      *   if (!value.isText() || !this.isEditable()) {
9071      *      return;
9072      *   }
9073      *   CharSequence text = value.getTextValue();
9074      *   if (text != null) {
9075      *     this.setText(text);
9076      *   }
9077      * }
9078      * </pre>
9079      *
9080      * <p>If the value is updated asynchronously, the next call to
9081      * {@link AutofillManager#notifyValueChanged(View)} must happen <b>after</b> the value was
9082      * changed to the autofilled value. If not, the view will not be considered autofilled.
9083      *
9084      * <p><b>Note:</b> After this method is called, the value returned by
9085      * {@link #getAutofillValue()} must be equal to the {@code value} passed to it, otherwise the
9086      * view will not be highlighted as autofilled.
9087      *
9088      * @param value value to be autofilled.
9089      */
9090     public void autofill(@SuppressWarnings("unused") AutofillValue value) {
9091     }
9092 
9093     /**
9094      * Automatically fills the content of the virtual children within this view.
9095      *
9096      * <p>Views with virtual children support the Autofill Framework mainly by:
9097      * <ul>
9098      *   <li>Providing the metadata defining what the virtual children mean and how they can be
9099      *       autofilled.
9100      *   <li>Implementing the methods that autofill the virtual children.
9101      * </ul>
9102      * <p>{@link #onProvideAutofillVirtualStructure(ViewStructure, int)} is responsible for the
9103      * former, this method is responsible for the latter - see {@link #autofill(AutofillValue)} and
9104      * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} for more info about autofill.
9105      *
9106      * <p>If a child value is updated asynchronously, the next call to
9107      * {@link AutofillManager#notifyValueChanged(View, int, AutofillValue)} must happen
9108      * <b>after</b> the value was changed to the autofilled value. If not, the child will not be
9109      * considered autofilled.
9110      *
9111      * <p><b>Note:</b> To indicate that a virtual view was autofilled,
9112      * <code>?android:attr/autofilledHighlight</code> should be drawn over it until the data
9113      * changes.
9114      *
9115      * @param values map of values to be autofilled, keyed by virtual child id.
9116      *
9117      * @attr ref android.R.styleable#Theme_autofilledHighlight
9118      */
9119     public void autofill(@NonNull @SuppressWarnings("unused") SparseArray<AutofillValue> values) {
9120         if (!mContext.isAutofillCompatibilityEnabled()) {
9121             return;
9122         }
9123         final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
9124         if (provider == null) {
9125             return;
9126         }
9127         final int valueCount = values.size();
9128         for (int i = 0; i < valueCount; i++) {
9129             final AutofillValue value = values.valueAt(i);
9130             if (value.isText()) {
9131                 final int virtualId = values.keyAt(i);
9132                 final CharSequence text = value.getTextValue();
9133                 final Bundle arguments = new Bundle();
9134                 arguments.putCharSequence(
9135                         AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text);
9136                 provider.performAction(virtualId, AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
9137             }
9138         }
9139     }
9140 
9141     /**
9142      * Gets the unique, logical identifier of this view in the activity, for autofill purposes.
9143      *
9144      * <p>The autofill id is created on demand, unless it is explicitly set by
9145      * {@link #setAutofillId(AutofillId)}.
9146      *
9147      * <p>See {@link #setAutofillId(AutofillId)} for more info.
9148      *
9149      * @return The View's autofill id.
9150      */
9151     public final AutofillId getAutofillId() {
9152         if (mAutofillId == null) {
9153             // The autofill id needs to be unique, but its value doesn't matter,
9154             // so it's better to reuse the accessibility id to save space.
9155             mAutofillId = new AutofillId(getAutofillViewId());
9156         }
9157         return mAutofillId;
9158     }
9159 
9160     /**
9161      * Sets the unique, logical identifier of this view in the activity, for autofill purposes.
9162      *
9163      * <p>The autofill id is created on demand, and this method should only be called when a view is
9164      * reused after {@link #dispatchProvideAutofillStructure(ViewStructure, int)} is called, as
9165      * that method creates a snapshot of the view that is passed along to the autofill service.
9166      *
9167      * <p>This method is typically used when view subtrees are recycled to represent different
9168      * content* &mdash;in this case, the autofill id can be saved before the view content is swapped
9169      * out, and restored later when it's swapped back in. For example:
9170      *
9171      * <pre>
9172      * EditText reusableView = ...;
9173      * ViewGroup parentView = ...;
9174      * AutofillManager afm = ...;
9175      *
9176      * // Swap out the view and change its contents
9177      * AutofillId oldId = reusableView.getAutofillId();
9178      * CharSequence oldText = reusableView.getText();
9179      * parentView.removeView(reusableView);
9180      * AutofillId newId = afm.getNextAutofillId();
9181      * reusableView.setText("New I am");
9182      * reusableView.setAutofillId(newId);
9183      * parentView.addView(reusableView);
9184      *
9185      * // Later, swap the old content back in
9186      * parentView.removeView(reusableView);
9187      * reusableView.setAutofillId(oldId);
9188      * reusableView.setText(oldText);
9189      * parentView.addView(reusableView);
9190      * </pre>
9191      *
9192      * @param id an autofill ID that is unique in the {@link android.app.Activity} hosting the view,
9193      * or {@code null} to reset it. Usually it's an id previously allocated to another view (and
9194      * obtained through {@link #getAutofillId()}), or a new value obtained through
9195      * {@link AutofillManager#getNextAutofillId()}.
9196      *
9197      * @throws IllegalStateException if the view is already {@link #isAttachedToWindow() attached to
9198      * a window}.
9199      *
9200      * @throws IllegalArgumentException if the id is an autofill id associated with a virtual view.
9201      */
9202     public void setAutofillId(@Nullable AutofillId id) {
9203         // TODO(b/37566627): add unit / CTS test for all possible combinations below
9204         if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
9205             Log.v(AUTOFILL_LOG_TAG, "setAutofill(): from " + mAutofillId + " to " + id);
9206         }
9207         if (isAttachedToWindow()) {
9208             throw new IllegalStateException("Cannot set autofill id when view is attached");
9209         }
9210         if (id != null && !id.isNonVirtual()) {
9211             throw new IllegalStateException("Cannot set autofill id assigned to virtual views");
9212         }
9213         if (id == null && (mPrivateFlags3 & PFLAG3_AUTOFILLID_EXPLICITLY_SET) == 0) {
9214             // Ignore reset because it was never explicitly set before.
9215             return;
9216         }
9217         mAutofillId = id;
9218         if (id != null) {
9219             mAutofillViewId = id.getViewId();
9220             mPrivateFlags3 |= PFLAG3_AUTOFILLID_EXPLICITLY_SET;
9221         } else {
9222             mAutofillViewId = NO_ID;
9223             mPrivateFlags3 &= ~PFLAG3_AUTOFILLID_EXPLICITLY_SET;
9224         }
9225     }
9226 
9227     /**
9228      * Describes the autofill type of this view, so an
9229      * {@link android.service.autofill.AutofillService} can create the proper {@link AutofillValue}
9230      * when autofilling the view.
9231      *
9232      * <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it to properly
9233      * support the Autofill Framework.
9234      *
9235      * @return either {@link #AUTOFILL_TYPE_NONE}, {@link #AUTOFILL_TYPE_TEXT},
9236      * {@link #AUTOFILL_TYPE_LIST}, {@link #AUTOFILL_TYPE_DATE}, or {@link #AUTOFILL_TYPE_TOGGLE}.
9237      *
9238      * @see #onProvideAutofillStructure(ViewStructure, int)
9239      * @see #autofill(AutofillValue)
9240      */
9241     public @AutofillType int getAutofillType() {
9242         return AUTOFILL_TYPE_NONE;
9243     }
9244 
9245     /**
9246      * Gets the hints that help an {@link android.service.autofill.AutofillService} determine how
9247      * to autofill the view with the user's data.
9248      *
9249      * <p>See {@link #setAutofillHints(String...)} for more info about these hints.
9250      *
9251      * @return The hints set via the attribute or {@link #setAutofillHints(String...)}, or
9252      * {@code null} if no hints were set.
9253      *
9254      * @attr ref android.R.styleable#View_autofillHints
9255      */
9256     @ViewDebug.ExportedProperty()
9257     @InspectableProperty
9258     @Nullable public String[] getAutofillHints() {
9259         return mAutofillHints;
9260     }
9261 
9262     /**
9263      * @hide
9264      */
9265     @TestApi
9266     public boolean isAutofilled() {
9267         return (mPrivateFlags3 & PFLAG3_IS_AUTOFILLED) != 0;
9268     }
9269 
9270     /**
9271      * @hide
9272      */
9273     public boolean hideAutofillHighlight() {
9274         return (mPrivateFlags4 & PFLAG4_AUTOFILL_HIDE_HIGHLIGHT) != 0;
9275     }
9276 
9277     /**
9278      * Gets the {@link View}'s current autofill value.
9279      *
9280      * <p>By default returns {@code null}, but subclasses should override it and return an
9281      * appropriate value to properly support the Autofill Framework.
9282      *
9283      * @see #onProvideAutofillStructure(ViewStructure, int)
9284      * @see #autofill(AutofillValue)
9285      */
9286     @Nullable
9287     public AutofillValue getAutofillValue() {
9288         return null;
9289     }
9290 
9291     /**
9292      * Gets the mode for determining whether this view is important for autofill.
9293      *
9294      * <p>See {@link #setImportantForAutofill(int)} and {@link #isImportantForAutofill()} for more
9295      * info about this mode.
9296      *
9297      * @return {@link #IMPORTANT_FOR_AUTOFILL_AUTO} by default, or value passed to
9298      * {@link #setImportantForAutofill(int)}.
9299      *
9300      * @attr ref android.R.styleable#View_importantForAutofill
9301      */
9302     @ViewDebug.ExportedProperty(mapping = {
9303             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_AUTO, to = "auto"),
9304             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES, to = "yes"),
9305             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO, to = "no"),
9306             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
9307                 to = "yesExcludeDescendants"),
9308             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
9309                 to = "noExcludeDescendants")})
9310     @InspectableProperty(enumMapping = {
9311             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_AUTO, name = "auto"),
9312             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_YES, name = "yes"),
9313             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_NO, name = "no"),
9314             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
9315                     name = "yesExcludeDescendants"),
9316             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
9317                     name = "noExcludeDescendants"),
9318     })
9319     public @AutofillImportance int getImportantForAutofill() {
9320         return (mPrivateFlags3
9321                 & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK) >> PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
9322     }
9323 
9324     /**
9325      * Sets the mode for determining whether this view is considered important for autofill.
9326      *
9327      * <p>The platform determines the importance for autofill automatically but you
9328      * can use this method to customize the behavior. For example:
9329      *
9330      * <ol>
9331      *   <li>When the view contents is irrelevant for autofill (for example, a text field used in a
9332      *       "Captcha" challenge), it should be {@link #IMPORTANT_FOR_AUTOFILL_NO}.
9333      *   <li>When both the view and its children are irrelevant for autofill (for example, the root
9334      *       view of an activity containing a spreadhseet editor), it should be
9335      *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
9336      *   <li>When the view content is relevant for autofill but its children aren't (for example,
9337      *       a credit card expiration date represented by a custom view that overrides the proper
9338      *       autofill methods and has 2 children representing the month and year), it should
9339      *       be {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}.
9340      * </ol>
9341      *
9342      * <p><b>Note:</b> Setting the mode as {@link #IMPORTANT_FOR_AUTOFILL_NO} or
9343      * {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS} does not guarantee the view (and its
9344      * children) will be always be considered not important; for example, when the user explicitly
9345      * makes an autofill request, all views are considered important. See
9346      * {@link #isImportantForAutofill()} for more details about how the View's importance for
9347      * autofill is used.
9348      *
9349      * @param mode {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, {@link #IMPORTANT_FOR_AUTOFILL_YES},
9350      * {@link #IMPORTANT_FOR_AUTOFILL_NO}, {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS},
9351      * or {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
9352      *
9353      * @attr ref android.R.styleable#View_importantForAutofill
9354      */
9355     public void setImportantForAutofill(@AutofillImportance int mode) {
9356         mPrivateFlags3 &= ~PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
9357         mPrivateFlags3 |= (mode << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT)
9358                 & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
9359     }
9360 
9361     /**
9362      * Hints the Android System whether the {@link android.app.assist.AssistStructure.ViewNode}
9363      * associated with this view is considered important for autofill purposes.
9364      *
9365      * <p>Generally speaking, a view is important for autofill if:
9366      * <ol>
9367      * <li>The view can be autofilled by an {@link android.service.autofill.AutofillService}.
9368      * <li>The view contents can help an {@link android.service.autofill.AutofillService}
9369      *     determine how other views can be autofilled.
9370      * <ol>
9371      *
9372      * <p>For example, view containers should typically return {@code false} for performance reasons
9373      * (since the important info is provided by their children), but if its properties have relevant
9374      * information (for example, a resource id called {@code credentials}, it should return
9375      * {@code true}. On the other hand, views representing labels or editable fields should
9376      * typically return {@code true}, but in some cases they could return {@code false}
9377      * (for example, if they're part of a "Captcha" mechanism).
9378      *
9379      * <p>The value returned by this method depends on the value returned by
9380      * {@link #getImportantForAutofill()}:
9381      *
9382      * <ol>
9383      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_YES} or
9384      *       {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}, then it returns {@code true}
9385      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_NO} or
9386      *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}, then it returns {@code false}
9387      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, then it uses some simple heuristics
9388      *       that can return {@code true} in some cases (like a container with a resource id),
9389      *       but {@code false} in most.
9390      *   <li>otherwise, it returns {@code false}.
9391      * </ol>
9392      *
9393      * <p>When a view is considered important for autofill:
9394      * <ul>
9395      *   <li>The view might automatically trigger an autofill request when focused on.
9396      *   <li>The contents of the view are included in the {@link ViewStructure} used in an autofill
9397      *       request.
9398      * </ul>
9399      *
9400      * <p>On the other hand, when a view is considered not important for autofill:
9401      * <ul>
9402      *   <li>The view never automatically triggers autofill requests, but it can trigger a manual
9403      *       request through {@link AutofillManager#requestAutofill(View)}.
9404      *   <li>The contents of the view are not included in the {@link ViewStructure} used in an
9405      *       autofill request, unless the request has the
9406      *       {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag.
9407      * </ul>
9408      *
9409      * @return whether the view is considered important for autofill.
9410      *
9411      * @see #setImportantForAutofill(int)
9412      * @see #IMPORTANT_FOR_AUTOFILL_AUTO
9413      * @see #IMPORTANT_FOR_AUTOFILL_YES
9414      * @see #IMPORTANT_FOR_AUTOFILL_NO
9415      * @see #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
9416      * @see #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
9417      * @see AutofillManager#requestAutofill(View)
9418      */
9419     public final boolean isImportantForAutofill() {
9420         // Check parent mode to ensure we're not hidden.
9421         ViewParent parent = mParent;
9422         while (parent instanceof View) {
9423             final int parentImportance = ((View) parent).getImportantForAutofill();
9424             if (parentImportance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
9425                     || parentImportance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS) {
9426                 if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
9427                     Log.v(AUTOFILL_LOG_TAG, "View (" +  this + ") is not important for autofill "
9428                             + "because parent " + parent + "'s importance is " + parentImportance);
9429                 }
9430                 return false;
9431             }
9432             parent = parent.getParent();
9433         }
9434 
9435         final int importance = getImportantForAutofill();
9436 
9437         // First, check the explicit states.
9438         if (importance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
9439                 || importance == IMPORTANT_FOR_AUTOFILL_YES) {
9440             return true;
9441         }
9442         if (importance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
9443                 || importance == IMPORTANT_FOR_AUTOFILL_NO) {
9444             if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
9445                 Log.v(AUTOFILL_LOG_TAG, "View (" +  this + ") is not important for autofill "
9446                         + "because its importance is " + importance);
9447             }
9448             return false;
9449         }
9450 
9451         // Then use some heuristics to handle AUTO.
9452         if (importance != IMPORTANT_FOR_AUTOFILL_AUTO) {
9453             Log.w(AUTOFILL_LOG_TAG, "invalid autofill importance (" + importance + " on view "
9454                     + this);
9455             return false;
9456         }
9457 
9458         // Always include views that have an explicit resource id.
9459         final int id = mID;
9460         if (id != NO_ID && !isViewIdGenerated(id)) {
9461             final Resources res = getResources();
9462             String entry = null;
9463             String pkg = null;
9464             try {
9465                 entry = res.getResourceEntryName(id);
9466                 pkg = res.getResourcePackageName(id);
9467             } catch (Resources.NotFoundException e) {
9468                 // ignore
9469             }
9470             if (entry != null && pkg != null && pkg.equals(mContext.getPackageName())) {
9471                 return true;
9472             }
9473         }
9474 
9475         // If the app developer explicitly set hints for it, it's important.
9476         if (getAutofillHints() != null) {
9477             return true;
9478         }
9479 
9480         // Otherwise, assume it's not important...
9481         return false;
9482     }
9483 
9484     /**
9485      * Gets the mode for determining whether this view is important for content capture.
9486      *
9487      * <p>See {@link #setImportantForContentCapture(int)} and
9488      * {@link #isImportantForContentCapture()} for more info about this mode.
9489      *
9490      * @return {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO} by default, or value passed to
9491      * {@link #setImportantForContentCapture(int)}.
9492      *
9493      * @attr ref android.R.styleable#View_importantForContentCapture
9494      */
9495     @ViewDebug.ExportedProperty(mapping = {
9496             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_AUTO, to = "auto"),
9497             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_YES, to = "yes"),
9498             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_NO, to = "no"),
9499             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
9500                 to = "yesExcludeDescendants"),
9501             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS,
9502                 to = "noExcludeDescendants")})
9503     @InspectableProperty(enumMapping = {
9504             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_AUTO, name = "auto"),
9505             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_YES, name = "yes"),
9506             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_NO, name = "no"),
9507             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
9508                     name = "yesExcludeDescendants"),
9509             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS,
9510                     name = "noExcludeDescendants"),
9511     })
9512     public @ContentCaptureImportance int getImportantForContentCapture() {
9513         // NOTE: the important for content capture values were the first flags added and are set in
9514         // the rightmost position, so we don't need to shift them
9515         return mPrivateFlags4 & PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK;
9516     }
9517 
9518     /**
9519      * Sets the mode for determining whether this view is considered important for content capture.
9520      *
9521      * <p>The platform determines the importance for autofill automatically but you
9522      * can use this method to customize the behavior. Typically, a view that provides text should
9523      * be marked as {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES}.
9524      *
9525      * @param mode {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO},
9526      * {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES}, {@link #IMPORTANT_FOR_CONTENT_CAPTURE_NO},
9527      * {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS},
9528      * or {@link #IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS}.
9529      *
9530      * @attr ref android.R.styleable#View_importantForContentCapture
9531      */
9532     public void setImportantForContentCapture(@ContentCaptureImportance int mode) {
9533         // Reset first
9534         mPrivateFlags4 &= ~PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK;
9535         // Then set again
9536         // NOTE: the important for content capture values were the first flags added and are set in
9537         // the rightmost position, so we don't need to shift them
9538         mPrivateFlags4 |= (mode & PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK);
9539     }
9540 
9541     /**
9542      * Hints the Android System whether this view is considered important for content capture, based
9543      * on the value explicitly set by {@link #setImportantForContentCapture(int)} and heuristics
9544      * when it's {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO}.
9545      *
9546      * <p>See {@link ContentCaptureManager} for more info about content capture.
9547      *
9548      * @return whether the view is considered important for content capture.
9549      *
9550      * @see #setImportantForContentCapture(int)
9551      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO
9552      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_YES
9553      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_NO
9554      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
9555      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
9556      */
9557     public final boolean isImportantForContentCapture() {
9558         boolean isImportant;
9559         if ((mPrivateFlags4 & PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED) != 0) {
9560             isImportant = (mPrivateFlags4 & PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE) != 0;
9561             return isImportant;
9562         }
9563 
9564         isImportant = calculateIsImportantForContentCapture();
9565 
9566         mPrivateFlags4 &= ~PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
9567         if (isImportant) {
9568             mPrivateFlags4 |= PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
9569         }
9570         mPrivateFlags4 |= PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED;
9571         return isImportant;
9572     }
9573 
9574     /**
9575      * Calculates whether the flag is important for content capture so it can be used by
9576      * {@link #isImportantForContentCapture()} while the tree is traversed.
9577      */
9578     private boolean calculateIsImportantForContentCapture() {
9579         // Check parent mode to ensure we're important
9580         ViewParent parent = mParent;
9581         while (parent instanceof View) {
9582             final int parentImportance = ((View) parent).getImportantForContentCapture();
9583             if (parentImportance == IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
9584                     || parentImportance == IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS) {
9585                 if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
9586                     Log.v(CONTENT_CAPTURE_LOG_TAG, "View (" +  this + ") is not important for "
9587                             + "content capture because parent " + parent + "'s importance is "
9588                             + parentImportance);
9589                 }
9590                 return false;
9591             }
9592             parent = parent.getParent();
9593         }
9594 
9595         final int importance = getImportantForContentCapture();
9596 
9597         // First, check the explicit states.
9598         if (importance == IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
9599                 || importance == IMPORTANT_FOR_CONTENT_CAPTURE_YES) {
9600             return true;
9601         }
9602         if (importance == IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
9603                 || importance == IMPORTANT_FOR_CONTENT_CAPTURE_NO) {
9604             if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
9605                 Log.v(CONTENT_CAPTURE_LOG_TAG, "View (" +  this + ") is not important for content "
9606                         + "capture because its importance is " + importance);
9607             }
9608             return false;
9609         }
9610 
9611         // Then use some heuristics to handle AUTO.
9612         if (importance != IMPORTANT_FOR_CONTENT_CAPTURE_AUTO) {
9613             Log.w(CONTENT_CAPTURE_LOG_TAG, "invalid content capture importance (" + importance
9614                     + " on view " + this);
9615             return false;
9616         }
9617 
9618         // View group is important if at least one children also is
9619         if (this instanceof ViewGroup) {
9620             final ViewGroup group = (ViewGroup) this;
9621             for (int i = 0; i < group.getChildCount(); i++) {
9622                 final View child = group.getChildAt(i);
9623                 if (child.isImportantForContentCapture()) {
9624                     return true;
9625                 }
9626             }
9627         }
9628 
9629         // If the app developer explicitly set hints or autofill hintsfor it, it's important.
9630         if (getAutofillHints() != null) {
9631             return true;
9632         }
9633 
9634         // Otherwise, assume it's not important...
9635         return false;
9636     }
9637 
9638     /**
9639      * Helper used to notify the {@link ContentCaptureManager} when the view is removed or
9640      * added, based on whether it's laid out and visible, and without knowing if the parent removed
9641      * it from the view hierarchy.
9642      *
9643      * <p>This method is called from many places (visibility changed, view laid out, view attached
9644      * or detached to/from window, etc...) and hence must contain the logic to call the manager, as
9645      * described below:
9646      *
9647      * <ol>
9648      *   <li>It should only be called when content capture is enabled for the view.
9649      *   <li>It must call viewAppeared() before viewDisappeared()
9650      *   <li>viewAppearead() can only be called when the view is visible and laidout
9651      *   <li>It should not call the same event twice.
9652      * </ol>
9653      */
9654     private void notifyAppearedOrDisappearedForContentCaptureIfNeeded(boolean appeared) {
9655         AttachInfo ai = mAttachInfo;
9656         // Skip it while the view is being laided out for the first time
9657         if (ai != null && !ai.mReadyForContentCaptureUpdates) return;
9658 
9659         if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
9660             Trace.traceBegin(Trace.TRACE_TAG_VIEW,
9661                     "notifyContentCapture(" + appeared + ") for " + getClass().getSimpleName());
9662         }
9663         try {
9664             notifyAppearedOrDisappearedForContentCaptureIfNeededNoTrace(appeared);
9665         } finally {
9666             Trace.traceEnd(Trace.TRACE_TAG_VIEW);
9667         }
9668     }
9669 
9670     private void notifyAppearedOrDisappearedForContentCaptureIfNeededNoTrace(boolean appeared) {
9671         AttachInfo ai = mAttachInfo;
9672 
9673         // First check if context has client, so it saves a service lookup when it doesn't
9674         if (mContext.getContentCaptureOptions() == null) return;
9675 
9676         if (appeared) {
9677             if (!isLaidOut() || getVisibility() != VISIBLE
9678                     || (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) != 0) {
9679                 if (DEBUG_CONTENT_CAPTURE) {
9680                     Log.v(CONTENT_CAPTURE_LOG_TAG, "Ignoring 'appeared' on " + this + ": laid="
9681                             + isLaidOut() + ", visibleToUser=" + isVisibleToUser()
9682                             + ", visible=" + (getVisibility() == VISIBLE)
9683                             + ": alreadyNotifiedAppeared=" + ((mPrivateFlags4
9684                             & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) != 0)
9685                             + ", alreadyNotifiedDisappeared=" + ((mPrivateFlags4
9686                             & PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED) != 0));
9687                 }
9688                 return;
9689             }
9690         } else {
9691             if ((mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) == 0
9692                     || (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED) != 0) {
9693                 if (DEBUG_CONTENT_CAPTURE) {
9694                     Log.v(CONTENT_CAPTURE_LOG_TAG, "Ignoring 'disappeared' on " + this + ": laid="
9695                             + isLaidOut() + ", visibleToUser=" + isVisibleToUser()
9696                             + ", visible=" + (getVisibility() == VISIBLE)
9697                             + ": alreadyNotifiedAppeared=" + ((mPrivateFlags4
9698                             & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) != 0)
9699                             + ", alreadyNotifiedDisappeared=" + ((mPrivateFlags4
9700                             & PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED) != 0));
9701                 }
9702                 return;
9703             }
9704         }
9705 
9706         ContentCaptureSession session = getContentCaptureSession();
9707         if (session == null) return;
9708 
9709         // ... and finally at the view level
9710         // NOTE: isImportantForContentCapture() is more expensive than cm.isContentCaptureEnabled()
9711         if (!isImportantForContentCapture()) return;
9712 
9713         if (appeared) {
9714             setNotifiedContentCaptureAppeared();
9715 
9716             if (ai != null) {
9717                 ai.delayNotifyContentCaptureEvent(session, this, appeared);
9718             } else {
9719                 if (DEBUG_CONTENT_CAPTURE) {
9720                     Log.w(CONTENT_CAPTURE_LOG_TAG, "no AttachInfo on appeared for " + this);
9721                 }
9722             }
9723         } else {
9724             mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED;
9725             mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED;
9726 
9727             if (ai != null) {
9728                 ai.delayNotifyContentCaptureEvent(session, this, appeared);
9729             } else {
9730                 if (DEBUG_CONTENT_CAPTURE) {
9731                     Log.v(CONTENT_CAPTURE_LOG_TAG, "no AttachInfo on disappeared for " + this);
9732                 }
9733             }
9734         }
9735     }
9736 
9737     private void setNotifiedContentCaptureAppeared() {
9738         mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED;
9739         mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED;
9740     }
9741 
9742     /** @hide */
9743     protected boolean getNotifiedContentCaptureAppeared() {
9744         return (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) != 0;
9745     }
9746 
9747 
9748     /**
9749      * Sets the (optional) {@link ContentCaptureSession} associated with this view.
9750      *
9751      * <p>This method should be called when you need to associate a {@link ContentCaptureContext} to
9752      * the content capture events associated with this view or its view hierarchy (if it's a
9753      * {@link ViewGroup}).
9754      *
9755      * <p>For example, if your activity is associated with a web domain, first you would need to
9756      * set the context for the main DOM:
9757      *
9758      * <pre>
9759      *   ContentCaptureSession mainSession = rootView.getContentCaptureSession();
9760      *   mainSession.setContentCaptureContext(ContentCaptureContext.forLocusId(Uri.parse(myUrl));
9761      * </pre>
9762      *
9763      * <p>Then if the page had an {@code IFRAME}, you would create a new session for it:
9764      *
9765      * <pre>
9766      *   ContentCaptureSession iframeSession = mainSession.createContentCaptureSession(
9767      *       ContentCaptureContext.forLocusId(Uri.parse(iframeUrl)));
9768      *   iframeView.setContentCaptureSession(iframeSession);
9769      * </pre>
9770      *
9771      * @param contentCaptureSession a session created by
9772      * {@link ContentCaptureSession#createContentCaptureSession(
9773      *        android.view.contentcapture.ContentCaptureContext)}.
9774      */
9775     public void setContentCaptureSession(@Nullable ContentCaptureSession contentCaptureSession) {
9776         mContentCaptureSession = contentCaptureSession;
9777     }
9778 
9779     /**
9780      * Gets the session used to notify content capture events.
9781      *
9782      * @return session explicitly set by {@link #setContentCaptureSession(ContentCaptureSession)},
9783      * inherited by ancestors, default session or {@code null} if content capture is disabled for
9784      * this view.
9785      */
9786     @Nullable
9787     public final ContentCaptureSession getContentCaptureSession() {
9788         if (mContentCaptureSessionCached) {
9789             return mContentCaptureSession;
9790         }
9791 
9792         mContentCaptureSession = getAndCacheContentCaptureSession();
9793         mContentCaptureSessionCached = true;
9794         return mContentCaptureSession;
9795     }
9796 
9797     @Nullable
9798     private ContentCaptureSession getAndCacheContentCaptureSession() {
9799         // First try the session explicitly set by setContentCaptureSession()
9800         if (mContentCaptureSession != null) {
9801             return mContentCaptureSession;
9802         }
9803 
9804         // Then the session explicitly set in an ancestor
9805         ContentCaptureSession session = null;
9806         if (mParent instanceof View) {
9807             session = ((View) mParent).getContentCaptureSession();
9808         }
9809 
9810         // Finally, if no session was explicitly set, use the context's default session.
9811         if (session == null) {
9812             final ContentCaptureManager ccm = mContext
9813                     .getSystemService(ContentCaptureManager.class);
9814             return ccm == null ? null : ccm.getMainContentCaptureSession();
9815         }
9816         return session;
9817     }
9818 
9819     @Nullable
9820     private AutofillManager getAutofillManager() {
9821         return mContext.getSystemService(AutofillManager.class);
9822     }
9823 
9824     private boolean isAutofillable() {
9825         if (getAutofillType() == AUTOFILL_TYPE_NONE) return false;
9826 
9827         if (!isImportantForAutofill()) {
9828             // View is not important for "regular" autofill, so we must check if Augmented Autofill
9829             // is enabled for the activity
9830             final AutofillOptions options = mContext.getAutofillOptions();
9831             if (options == null || !options.isAugmentedAutofillEnabled(mContext)) {
9832                 return false;
9833             }
9834             final AutofillManager afm = getAutofillManager();
9835             if (afm == null) return false;
9836             afm.notifyViewEnteredForAugmentedAutofill(this);
9837         }
9838 
9839         return getAutofillViewId() > LAST_APP_AUTOFILL_ID;
9840     }
9841 
9842     /** @hide */
9843     public boolean canNotifyAutofillEnterExitEvent() {
9844         return isAutofillable() && isAttachedToWindow();
9845     }
9846 
9847     private void populateVirtualStructure(ViewStructure structure,
9848             AccessibilityNodeProvider provider, AccessibilityNodeInfo info,
9849             boolean forAutofill) {
9850         structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
9851                 null, null, info.getViewIdResourceName());
9852         Rect rect = structure.getTempRect();
9853         info.getBoundsInParent(rect);
9854         structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
9855         structure.setVisibility(VISIBLE);
9856         structure.setEnabled(info.isEnabled());
9857         if (info.isClickable()) {
9858             structure.setClickable(true);
9859         }
9860         if (info.isFocusable()) {
9861             structure.setFocusable(true);
9862         }
9863         if (info.isFocused()) {
9864             structure.setFocused(true);
9865         }
9866         if (info.isAccessibilityFocused()) {
9867             structure.setAccessibilityFocused(true);
9868         }
9869         if (info.isSelected()) {
9870             structure.setSelected(true);
9871         }
9872         if (info.isLongClickable()) {
9873             structure.setLongClickable(true);
9874         }
9875         if (info.isCheckable()) {
9876             structure.setCheckable(true);
9877             if (info.isChecked()) {
9878                 structure.setChecked(true);
9879             }
9880         }
9881         if (info.isContextClickable()) {
9882             structure.setContextClickable(true);
9883         }
9884         if (forAutofill) {
9885             structure.setAutofillId(new AutofillId(getAutofillId(),
9886                     AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId())));
9887         }
9888         CharSequence cname = info.getClassName();
9889         structure.setClassName(cname != null ? cname.toString() : null);
9890         structure.setContentDescription(info.getContentDescription());
9891         if (forAutofill) {
9892             final int maxTextLength = info.getMaxTextLength();
9893             if (maxTextLength != -1) {
9894                 structure.setMaxTextLength(maxTextLength);
9895             }
9896             structure.setHint(info.getHintText());
9897         }
9898         CharSequence text = info.getText();
9899         boolean hasText = text != null || info.getError() != null;
9900         if (hasText) {
9901             structure.setText(text, info.getTextSelectionStart(), info.getTextSelectionEnd());
9902         }
9903         if (forAutofill) {
9904             if (info.isEditable()) {
9905                 structure.setDataIsSensitive(true);
9906                 if (hasText) {
9907                     structure.setAutofillType(AUTOFILL_TYPE_TEXT);
9908                     structure.setAutofillValue(AutofillValue.forText(text));
9909                 }
9910                 int inputType = info.getInputType();
9911                 if (inputType == 0 && info.isPassword()) {
9912                     inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD;
9913                 }
9914                 structure.setInputType(inputType);
9915             } else {
9916                 structure.setDataIsSensitive(false);
9917             }
9918         }
9919         final int NCHILDREN = info.getChildCount();
9920         if (NCHILDREN > 0) {
9921             structure.setChildCount(NCHILDREN);
9922             for (int i=0; i<NCHILDREN; i++) {
9923                 if (AccessibilityNodeInfo.getVirtualDescendantId(info.getChildNodeIds().get(i))
9924                         == AccessibilityNodeProvider.HOST_VIEW_ID) {
9925                     Log.e(VIEW_LOG_TAG, "Virtual view pointing to its host. Ignoring");
9926                     continue;
9927                 }
9928                 AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
9929                         AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
9930                 ViewStructure child = structure.newChild(i);
9931                 populateVirtualStructure(child, provider, cinfo, forAutofill);
9932                 cinfo.recycle();
9933             }
9934         }
9935     }
9936 
9937     /**
9938      * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
9939      * implementation calls {@link #onProvideStructure} and
9940      * {@link #onProvideVirtualStructure}.
9941      */
9942     public void dispatchProvideStructure(ViewStructure structure) {
9943         dispatchProvideStructure(structure, VIEW_STRUCTURE_FOR_ASSIST, /* flags= */ 0);
9944     }
9945 
9946     /**
9947      * Dispatches creation of a {@link ViewStructure}s for autofill purposes down the hierarchy,
9948      * when an Assist structure is being created as part of an autofill request.
9949      *
9950      * <p>The default implementation does the following:
9951      * <ul>
9952      *   <li>Sets the {@link AutofillId} in the structure.
9953      *   <li>Calls {@link #onProvideAutofillStructure(ViewStructure, int)}.
9954      *   <li>Calls {@link #onProvideAutofillVirtualStructure(ViewStructure, int)}.
9955      * </ul>
9956      *
9957      * <p>Typically, this method should only be overridden by subclasses that provide a view
9958      * hierarchy (such as {@link ViewGroup}) - other classes should override
9959      * {@link #onProvideAutofillStructure(ViewStructure, int)} or
9960      * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} instead.
9961      *
9962      * <p>When overridden, it must:
9963      *
9964      * <ul>
9965      *   <li>Either call
9966      *       {@code super.dispatchProvideAutofillStructure(structure, flags)} or explicitly
9967      *       set the {@link AutofillId} in the structure (for example, by calling
9968      *       {@code structure.setAutofillId(getAutofillId())}).
9969      *   <li>Decide how to handle the {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag - when
9970      *       set, all views in the structure should be considered important for autofill,
9971      *       regardless of what {@link #isImportantForAutofill()} returns. We encourage you to
9972      *       respect this flag to provide a better user experience - this flag is typically used
9973      *       when an user explicitly requested autofill. If the flag is not set,
9974      *       then only views marked as important for autofill should be included in the
9975      *       structure - skipping non-important views optimizes the overall autofill performance.
9976      * </ul>
9977      *
9978      * @param structure fill in with structured view data for autofill purposes.
9979      * @param flags optional flags.
9980      *
9981      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
9982      */
9983     public void dispatchProvideAutofillStructure(@NonNull ViewStructure structure,
9984             @AutofillFlags int flags) {
9985         dispatchProvideStructure(structure, VIEW_STRUCTURE_FOR_AUTOFILL, flags);
9986     }
9987 
9988     private void dispatchProvideStructure(@NonNull ViewStructure structure,
9989             @ViewStructureType int viewFor, @AutofillFlags int flags) {
9990         if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
9991             structure.setAutofillId(getAutofillId());
9992             onProvideAutofillStructure(structure, flags);
9993             onProvideAutofillVirtualStructure(structure, flags);
9994         } else if (!isAssistBlocked()) {
9995             onProvideStructure(structure);
9996             onProvideVirtualStructure(structure);
9997         } else {
9998             structure.setClassName(getAccessibilityClassName().toString());
9999             structure.setAssistBlocked(true);
10000         }
10001     }
10002 
10003     /**
10004      * Dispatches the initial content capture events for a view structure.
10005      *
10006      * @hide
10007      */
10008     public void dispatchInitialProvideContentCaptureStructure() {
10009         AttachInfo ai = mAttachInfo;
10010         if (ai == null) {
10011             Log.w(CONTENT_CAPTURE_LOG_TAG,
10012                     "dispatchProvideContentCaptureStructure(): no AttachInfo for " + this);
10013             return;
10014         }
10015         ContentCaptureManager ccm = ai.mContentCaptureManager;
10016         if (ccm == null) {
10017             Log.w(CONTENT_CAPTURE_LOG_TAG, "dispatchProvideContentCaptureStructure(): "
10018                     + "no ContentCaptureManager for " + this);
10019             return;
10020         }
10021 
10022         // We must set it before checkign if the view itself is important, because it might
10023         // initially not be (for example, if it's empty), although that might change later (for
10024         // example, if important views are added)
10025         ai.mReadyForContentCaptureUpdates = true;
10026 
10027         if (!isImportantForContentCapture()) {
10028             if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.DEBUG)) {
10029                 Log.d(CONTENT_CAPTURE_LOG_TAG,
10030                         "dispatchProvideContentCaptureStructure(): decorView is not important");
10031             }
10032             return;
10033         }
10034 
10035         ai.mContentCaptureManager = ccm;
10036 
10037         ContentCaptureSession session = getContentCaptureSession();
10038         if (session == null) {
10039             if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.DEBUG)) {
10040                 Log.d(CONTENT_CAPTURE_LOG_TAG,
10041                         "dispatchProvideContentCaptureStructure(): no session for " + this);
10042             }
10043             return;
10044         }
10045 
10046         session.internalNotifyViewTreeEvent(/* started= */ true);
10047         try {
10048             dispatchProvideContentCaptureStructure();
10049         } finally {
10050             session.internalNotifyViewTreeEvent(/* started= */ false);
10051         }
10052     }
10053 
10054     /** @hide */
10055     void dispatchProvideContentCaptureStructure() {
10056         ContentCaptureSession session = getContentCaptureSession();
10057         if (session != null) {
10058             ViewStructure structure = session.newViewStructure(this);
10059             onProvideContentCaptureStructure(structure, /* flags= */ 0);
10060             setNotifiedContentCaptureAppeared();
10061             session.notifyViewAppeared(structure);
10062         }
10063     }
10064 
10065     /**
10066      * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
10067      *
10068      * Note: Called from the default {@link AccessibilityDelegate}.
10069      *
10070      * @hide
10071      */
10072     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
10073         if (mAttachInfo == null) {
10074             return;
10075         }
10076 
10077         Rect bounds = mAttachInfo.mTmpInvalRect;
10078 
10079         getDrawingRect(bounds);
10080         info.setBoundsInParent(bounds);
10081 
10082         getBoundsOnScreen(bounds, true);
10083         info.setBoundsInScreen(bounds);
10084 
10085         ViewParent parent = getParentForAccessibility();
10086         if (parent instanceof View) {
10087             info.setParent((View) parent);
10088         }
10089 
10090         if (mID != View.NO_ID) {
10091             View rootView = getRootView();
10092             if (rootView == null) {
10093                 rootView = this;
10094             }
10095 
10096             View label = rootView.findLabelForView(this, mID);
10097             if (label != null) {
10098                 info.setLabeledBy(label);
10099             }
10100 
10101             if ((mAttachInfo.mAccessibilityFetchFlags
10102                     & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
10103                     && Resources.resourceHasPackage(mID)) {
10104                 try {
10105                     String viewId = getResources().getResourceName(mID);
10106                     info.setViewIdResourceName(viewId);
10107                 } catch (Resources.NotFoundException nfe) {
10108                     /* ignore */
10109                 }
10110             }
10111         }
10112 
10113         if (mLabelForId != View.NO_ID) {
10114             View rootView = getRootView();
10115             if (rootView == null) {
10116                 rootView = this;
10117             }
10118             View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
10119             if (labeled != null) {
10120                 info.setLabelFor(labeled);
10121             }
10122         }
10123 
10124         if (mAccessibilityTraversalBeforeId != View.NO_ID) {
10125             View rootView = getRootView();
10126             if (rootView == null) {
10127                 rootView = this;
10128             }
10129             View next = rootView.findViewInsideOutShouldExist(this,
10130                     mAccessibilityTraversalBeforeId);
10131             if (next != null && next.includeForAccessibility()) {
10132                 info.setTraversalBefore(next);
10133             }
10134         }
10135 
10136         if (mAccessibilityTraversalAfterId != View.NO_ID) {
10137             View rootView = getRootView();
10138             if (rootView == null) {
10139                 rootView = this;
10140             }
10141             View next = rootView.findViewInsideOutShouldExist(this,
10142                     mAccessibilityTraversalAfterId);
10143             if (next != null && next.includeForAccessibility()) {
10144                 info.setTraversalAfter(next);
10145             }
10146         }
10147 
10148         info.setVisibleToUser(isVisibleToUser());
10149 
10150         info.setImportantForAccessibility(isImportantForAccessibility());
10151         info.setPackageName(mContext.getPackageName());
10152         info.setClassName(getAccessibilityClassName());
10153         info.setStateDescription(getStateDescription());
10154         info.setContentDescription(getContentDescription());
10155 
10156         info.setEnabled(isEnabled());
10157         info.setClickable(isClickable());
10158         info.setFocusable(isFocusable());
10159         info.setScreenReaderFocusable(isScreenReaderFocusable());
10160         info.setFocused(isFocused());
10161         info.setAccessibilityFocused(isAccessibilityFocused());
10162         info.setSelected(isSelected());
10163         info.setLongClickable(isLongClickable());
10164         info.setContextClickable(isContextClickable());
10165         info.setLiveRegion(getAccessibilityLiveRegion());
10166         if ((mTooltipInfo != null) && (mTooltipInfo.mTooltipText != null)) {
10167             info.setTooltipText(mTooltipInfo.mTooltipText);
10168             info.addAction((mTooltipInfo.mTooltipPopup == null)
10169                     ? AccessibilityNodeInfo.AccessibilityAction.ACTION_SHOW_TOOLTIP
10170                     : AccessibilityNodeInfo.AccessibilityAction.ACTION_HIDE_TOOLTIP);
10171         }
10172 
10173         // TODO: These make sense only if we are in an AdapterView but all
10174         // views can be selected. Maybe from accessibility perspective
10175         // we should report as selectable view in an AdapterView.
10176         info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
10177         info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
10178 
10179         if (isFocusable()) {
10180             if (isFocused()) {
10181                 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
10182             } else {
10183                 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
10184             }
10185         }
10186 
10187         if (!isAccessibilityFocused()) {
10188             info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
10189         } else {
10190             info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
10191         }
10192 
10193         if (isClickable() && isEnabled()) {
10194             info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
10195         }
10196 
10197         if (isLongClickable() && isEnabled()) {
10198             info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
10199         }
10200 
10201         if (isContextClickable() && isEnabled()) {
10202             info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
10203         }
10204 
10205         CharSequence text = getIterableTextForAccessibility();
10206         if (text != null && text.length() > 0) {
10207             info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
10208 
10209             info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
10210             info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
10211             info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
10212             info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
10213                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
10214                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
10215         }
10216 
10217         info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
10218         populateAccessibilityNodeInfoDrawingOrderInParent(info);
10219         info.setPaneTitle(mAccessibilityPaneTitle);
10220         info.setHeading(isAccessibilityHeading());
10221 
10222         if (mTouchDelegate != null) {
10223             info.setTouchDelegateInfo(mTouchDelegate.getTouchDelegateInfo());
10224         }
10225     }
10226 
10227     /**
10228      * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
10229      * additional data.
10230      * <p>
10231      * This method only needs overloading if the node is marked as having extra data available.
10232      * </p>
10233      *
10234      * @param info The info to which to add the extra data. Never {@code null}.
10235      * @param extraDataKey A key specifying the type of extra data to add to the info. The
10236      *                     extra data should be added to the {@link Bundle} returned by
10237      *                     the info's {@link AccessibilityNodeInfo#getExtras} method. Never
10238      *                     {@code null}.
10239      * @param arguments A {@link Bundle} holding any arguments relevant for this request. May be
10240      *                  {@code null} if the service provided no arguments.
10241      *
10242      * @see AccessibilityNodeInfo#setAvailableExtraData(List)
10243      */
10244     public void addExtraDataToAccessibilityNodeInfo(
10245             @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
10246             @Nullable Bundle arguments) {
10247     }
10248 
10249     /**
10250      * Determine the order in which this view will be drawn relative to its siblings for a11y
10251      *
10252      * @param info The info whose drawing order should be populated
10253      */
10254     private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
10255         /*
10256          * If the view's bounds haven't been set yet, layout has not completed. In that situation,
10257          * drawing order may not be well-defined, and some Views with custom drawing order may
10258          * not be initialized sufficiently to respond properly getChildDrawingOrder.
10259          */
10260         if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
10261             info.setDrawingOrder(0);
10262             return;
10263         }
10264         int drawingOrderInParent = 1;
10265         // Iterate up the hierarchy if parents are not important for a11y
10266         View viewAtDrawingLevel = this;
10267         final ViewParent parent = getParentForAccessibility();
10268         while (viewAtDrawingLevel != parent) {
10269             final ViewParent currentParent = viewAtDrawingLevel.getParent();
10270             if (!(currentParent instanceof ViewGroup)) {
10271                 // Should only happen for the Decor
10272                 drawingOrderInParent = 0;
10273                 break;
10274             } else {
10275                 final ViewGroup parentGroup = (ViewGroup) currentParent;
10276                 final int childCount = parentGroup.getChildCount();
10277                 if (childCount > 1) {
10278                     List<View> preorderedList = parentGroup.buildOrderedChildList();
10279                     if (preorderedList != null) {
10280                         final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
10281                         for (int i = 0; i < childDrawIndex; i++) {
10282                             drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
10283                         }
10284                     } else {
10285                         final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
10286                         final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
10287                         final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
10288                                 .getChildDrawingOrder(childCount, childIndex) : childIndex;
10289                         final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
10290                         if (childDrawIndex != 0) {
10291                             for (int i = 0; i < numChildrenToIterate; i++) {
10292                                 final int otherDrawIndex = (customOrder ?
10293                                         parentGroup.getChildDrawingOrder(childCount, i) : i);
10294                                 if (otherDrawIndex < childDrawIndex) {
10295                                     drawingOrderInParent +=
10296                                             numViewsForAccessibility(parentGroup.getChildAt(i));
10297                                 }
10298                             }
10299                         }
10300                     }
10301                 }
10302             }
10303             viewAtDrawingLevel = (View) currentParent;
10304         }
10305         info.setDrawingOrder(drawingOrderInParent);
10306     }
10307 
10308     private static int numViewsForAccessibility(View view) {
10309         if (view != null) {
10310             if (view.includeForAccessibility()) {
10311                 return 1;
10312             } else if (view instanceof ViewGroup) {
10313                 return ((ViewGroup) view).getNumChildrenForAccessibility();
10314             }
10315         }
10316         return 0;
10317     }
10318 
10319     private View findLabelForView(View view, int labeledId) {
10320         if (mMatchLabelForPredicate == null) {
10321             mMatchLabelForPredicate = new MatchLabelForPredicate();
10322         }
10323         mMatchLabelForPredicate.mLabeledId = labeledId;
10324         return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
10325     }
10326 
10327     /**
10328      * Computes whether this virtual autofill view is visible to the user.
10329      *
10330      * <p><b>Note: </b>By default it returns {@code true}, but views providing a virtual hierarchy
10331      * view must override it.
10332      *
10333      * @return Whether the view is visible on the screen.
10334      */
10335     public boolean isVisibleToUserForAutofill(int virtualId) {
10336         if (mContext.isAutofillCompatibilityEnabled()) {
10337             final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
10338             if (provider != null) {
10339                 final AccessibilityNodeInfo node = provider.createAccessibilityNodeInfo(virtualId);
10340                 if (node != null) {
10341                     return node.isVisibleToUser();
10342                 }
10343                 // if node is null, assume it's not visible anymore
10344             } else {
10345                 Log.w(VIEW_LOG_TAG, "isVisibleToUserForAutofill(" + virtualId + "): no provider");
10346             }
10347             return false;
10348         }
10349         return true;
10350     }
10351 
10352     /**
10353      * Computes whether this view is visible to the user. Such a view is
10354      * attached, visible, all its predecessors are visible, it is not clipped
10355      * entirely by its predecessors, and has an alpha greater than zero.
10356      *
10357      * @return Whether the view is visible on the screen.
10358      *
10359      * @hide
10360      */
10361     @UnsupportedAppUsage
10362     public boolean isVisibleToUser() {
10363         return isVisibleToUser(null);
10364     }
10365 
10366     /**
10367      * Computes whether the given portion of this view is visible to the user.
10368      * Such a view is attached, visible, all its predecessors are visible,
10369      * has an alpha greater than zero, and the specified portion is not
10370      * clipped entirely by its predecessors.
10371      *
10372      * @param boundInView the portion of the view to test; coordinates should be relative; may be
10373      *                    <code>null</code>, and the entire view will be tested in this case.
10374      *                    When <code>true</code> is returned by the function, the actual visible
10375      *                    region will be stored in this parameter; that is, if boundInView is fully
10376      *                    contained within the view, no modification will be made, otherwise regions
10377      *                    outside of the visible area of the view will be clipped.
10378      *
10379      * @return Whether the specified portion of the view is visible on the screen.
10380      *
10381      * @hide
10382      */
10383     @UnsupportedAppUsage
10384     protected boolean isVisibleToUser(Rect boundInView) {
10385         if (mAttachInfo != null) {
10386             // Attached to invisible window means this view is not visible.
10387             if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
10388                 return false;
10389             }
10390             // An invisible predecessor or one with alpha zero means
10391             // that this view is not visible to the user.
10392             Object current = this;
10393             while (current instanceof View) {
10394                 View view = (View) current;
10395                 // We have attach info so this view is attached and there is no
10396                 // need to check whether we reach to ViewRootImpl on the way up.
10397                 if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
10398                         view.getVisibility() != VISIBLE) {
10399                     return false;
10400                 }
10401                 current = view.mParent;
10402             }
10403             // Check if the view is entirely covered by its predecessors.
10404             Rect visibleRect = mAttachInfo.mTmpInvalRect;
10405             Point offset = mAttachInfo.mPoint;
10406             if (!getGlobalVisibleRect(visibleRect, offset)) {
10407                 return false;
10408             }
10409             // Check if the visible portion intersects the rectangle of interest.
10410             if (boundInView != null) {
10411                 visibleRect.offset(-offset.x, -offset.y);
10412                 return boundInView.intersect(visibleRect);
10413             }
10414             return true;
10415         }
10416         return false;
10417     }
10418 
10419     /**
10420      * Returns the delegate for implementing accessibility support via
10421      * composition. For more details see {@link AccessibilityDelegate}.
10422      *
10423      * @return The delegate, or null if none set.
10424      */
10425     public AccessibilityDelegate getAccessibilityDelegate() {
10426         return mAccessibilityDelegate;
10427     }
10428 
10429     /**
10430      * Sets a delegate for implementing accessibility support via composition
10431      * (as opposed to inheritance). For more details, see
10432      * {@link AccessibilityDelegate}.
10433      * <p>
10434      * <strong>Note:</strong> On platform versions prior to
10435      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
10436      * views in the {@code android.widget.*} package are called <i>before</i>
10437      * host methods. This prevents certain properties such as class name from
10438      * being modified by overriding
10439      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
10440      * as any changes will be overwritten by the host class.
10441      * <p>
10442      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
10443      * methods are called <i>after</i> host methods, which all properties to be
10444      * modified without being overwritten by the host class.
10445      *
10446      * @param delegate the object to which accessibility method calls should be
10447      *                 delegated
10448      * @see AccessibilityDelegate
10449      */
10450     public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
10451         mAccessibilityDelegate = delegate;
10452     }
10453 
10454     /**
10455      * Gets the provider for managing a virtual view hierarchy rooted at this View
10456      * and reported to {@link android.accessibilityservice.AccessibilityService}s
10457      * that explore the window content.
10458      * <p>
10459      * If this method returns an instance, this instance is responsible for managing
10460      * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
10461      * View including the one representing the View itself. Similarly the returned
10462      * instance is responsible for performing accessibility actions on any virtual
10463      * view or the root view itself.
10464      * </p>
10465      * <p>
10466      * If an {@link AccessibilityDelegate} has been specified via calling
10467      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
10468      * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
10469      * is responsible for handling this call.
10470      * </p>
10471      *
10472      * @return The provider.
10473      *
10474      * @see AccessibilityNodeProvider
10475      */
10476     public AccessibilityNodeProvider getAccessibilityNodeProvider() {
10477         if (mAccessibilityDelegate != null) {
10478             return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
10479         } else {
10480             return null;
10481         }
10482     }
10483 
10484     /**
10485      * Gets the unique identifier of this view on the screen for accessibility purposes.
10486      *
10487      * @return The view accessibility id.
10488      *
10489      * @hide
10490      */
10491     @UnsupportedAppUsage
10492     public int getAccessibilityViewId() {
10493         if (mAccessibilityViewId == NO_ID) {
10494             mAccessibilityViewId = sNextAccessibilityViewId++;
10495         }
10496         return mAccessibilityViewId;
10497     }
10498 
10499     /**
10500      * Gets the unique identifier of this view on the screen for autofill purposes.
10501      *
10502      * @return The view autofill id.
10503      *
10504      * @hide
10505      */
10506     public int getAutofillViewId() {
10507         if (mAutofillViewId == NO_ID) {
10508             mAutofillViewId = mContext.getNextAutofillId();
10509         }
10510         return mAutofillViewId;
10511     }
10512 
10513     /**
10514      * Gets the unique identifier of the window in which this View resides.
10515      *
10516      * @return The window accessibility id.
10517      *
10518      * @hide
10519      */
10520     public int getAccessibilityWindowId() {
10521         return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
10522                 : AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
10523     }
10524 
10525     /**
10526      * Returns the {@link View}'s state description.
10527      * <p>
10528      * <strong>Note:</strong> Do not override this method, as it will have no
10529      * effect on the state description presented to accessibility services.
10530      * You must call {@link #setStateDescription(CharSequence)} to modify the
10531      * state description.
10532      *
10533      * @return the state description
10534      * @see #setStateDescription(CharSequence)
10535      */
10536     @ViewDebug.ExportedProperty(category = "accessibility")
10537     public final @Nullable CharSequence getStateDescription() {
10538         return mStateDescription;
10539     }
10540 
10541     /**
10542      * Returns the {@link View}'s content description.
10543      * <p>
10544      * <strong>Note:</strong> Do not override this method, as it will have no
10545      * effect on the content description presented to accessibility services.
10546      * You must call {@link #setContentDescription(CharSequence)} to modify the
10547      * content description.
10548      *
10549      * @return the content description
10550      * @see #setContentDescription(CharSequence)
10551      * @attr ref android.R.styleable#View_contentDescription
10552      */
10553     @ViewDebug.ExportedProperty(category = "accessibility")
10554     @InspectableProperty
10555     public CharSequence getContentDescription() {
10556         return mContentDescription;
10557     }
10558 
10559     /**
10560      * Sets the {@link View}'s state description.
10561      * <p>
10562      * A state description briefly describes the states of the view and is primarily used
10563      * for accessibility support to determine how the states of a view should be presented to
10564      * the user. It is a supplement to the boolean states (for example, checked/unchecked) and
10565      * it is used for customized state description (for example, "wifi, connected, three bars").
10566      * State description changes frequently while content description should change less often.
10567      * State description should be localized. For android widgets which have default state
10568      * descriptions, app developers can call this method to override the state descriptions.
10569      * Setting state description to null restores the default behavior.
10570      *
10571      * @param stateDescription The state description.
10572      * @see #getStateDescription()
10573      */
10574     @RemotableViewMethod
10575     public void setStateDescription(@Nullable CharSequence stateDescription) {
10576         if (mStateDescription == null) {
10577             if (stateDescription == null) {
10578                 return;
10579             }
10580         } else if (mStateDescription.equals(stateDescription)) {
10581             return;
10582         }
10583         mStateDescription = stateDescription;
10584         if (!TextUtils.isEmpty(stateDescription)
10585                 && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
10586             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
10587         }
10588         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
10589             AccessibilityEvent event = AccessibilityEvent.obtain();
10590             event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
10591             event.setContentChangeTypes(AccessibilityEvent.CONTENT_CHANGE_TYPE_STATE_DESCRIPTION);
10592             sendAccessibilityEventUnchecked(event);
10593         }
10594     }
10595 
10596     /**
10597      * Sets the {@link View}'s content description.
10598      * <p>
10599      * A content description briefly describes the view and is primarily used
10600      * for accessibility support to determine how a view should be presented to
10601      * the user. In the case of a view with no textual representation, such as
10602      * {@link android.widget.ImageButton}, a useful content description
10603      * explains what the view does. For example, an image button with a phone
10604      * icon that is used to place a call may use "Call" as its content
10605      * description. An image of a floppy disk that is used to save a file may
10606      * use "Save".
10607      *
10608      * @param contentDescription The content description.
10609      * @see #getContentDescription()
10610      * @attr ref android.R.styleable#View_contentDescription
10611      */
10612     @RemotableViewMethod
10613     public void setContentDescription(CharSequence contentDescription) {
10614         if (mContentDescription == null) {
10615             if (contentDescription == null) {
10616                 return;
10617             }
10618         } else if (mContentDescription.equals(contentDescription)) {
10619             return;
10620         }
10621         mContentDescription = contentDescription;
10622         final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
10623         if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
10624             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
10625             notifySubtreeAccessibilityStateChangedIfNeeded();
10626         } else {
10627             notifyViewAccessibilityStateChangedIfNeeded(
10628                     AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
10629         }
10630     }
10631 
10632     /**
10633      * Sets the id of a view before which this one is visited in accessibility traversal.
10634      * A screen-reader must visit the content of this view before the content of the one
10635      * it precedes. For example, if view B is set to be before view A, then a screen-reader
10636      * will traverse the entire content of B before traversing the entire content of A,
10637      * regardles of what traversal strategy it is using.
10638      * <p>
10639      * Views that do not have specified before/after relationships are traversed in order
10640      * determined by the screen-reader.
10641      * </p>
10642      * <p>
10643      * Setting that this view is before a view that is not important for accessibility
10644      * or if this view is not important for accessibility will have no effect as the
10645      * screen-reader is not aware of unimportant views.
10646      * </p>
10647      *
10648      * @param beforeId The id of a view this one precedes in accessibility traversal.
10649      *
10650      * @attr ref android.R.styleable#View_accessibilityTraversalBefore
10651      *
10652      * @see #setImportantForAccessibility(int)
10653      */
10654     @RemotableViewMethod
10655     public void setAccessibilityTraversalBefore(@IdRes int beforeId) {
10656         if (mAccessibilityTraversalBeforeId == beforeId) {
10657             return;
10658         }
10659         mAccessibilityTraversalBeforeId = beforeId;
10660         notifyViewAccessibilityStateChangedIfNeeded(
10661                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10662     }
10663 
10664     /**
10665      * Gets the id of a view before which this one is visited in accessibility traversal.
10666      *
10667      * @return The id of a view this one precedes in accessibility traversal if
10668      *         specified, otherwise {@link #NO_ID}.
10669      *
10670      * @see #setAccessibilityTraversalBefore(int)
10671      */
10672     @IdRes
10673     @InspectableProperty
10674     public int getAccessibilityTraversalBefore() {
10675         return mAccessibilityTraversalBeforeId;
10676     }
10677 
10678     /**
10679      * Sets the id of a view after which this one is visited in accessibility traversal.
10680      * A screen-reader must visit the content of the other view before the content of this
10681      * one. For example, if view B is set to be after view A, then a screen-reader
10682      * will traverse the entire content of A before traversing the entire content of B,
10683      * regardles of what traversal strategy it is using.
10684      * <p>
10685      * Views that do not have specified before/after relationships are traversed in order
10686      * determined by the screen-reader.
10687      * </p>
10688      * <p>
10689      * Setting that this view is after a view that is not important for accessibility
10690      * or if this view is not important for accessibility will have no effect as the
10691      * screen-reader is not aware of unimportant views.
10692      * </p>
10693      *
10694      * @param afterId The id of a view this one succedees in accessibility traversal.
10695      *
10696      * @attr ref android.R.styleable#View_accessibilityTraversalAfter
10697      *
10698      * @see #setImportantForAccessibility(int)
10699      */
10700     @RemotableViewMethod
10701     public void setAccessibilityTraversalAfter(@IdRes int afterId) {
10702         if (mAccessibilityTraversalAfterId == afterId) {
10703             return;
10704         }
10705         mAccessibilityTraversalAfterId = afterId;
10706         notifyViewAccessibilityStateChangedIfNeeded(
10707                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10708     }
10709 
10710     /**
10711      * Gets the id of a view after which this one is visited in accessibility traversal.
10712      *
10713      * @return The id of a view this one succeedes in accessibility traversal if
10714      *         specified, otherwise {@link #NO_ID}.
10715      *
10716      * @see #setAccessibilityTraversalAfter(int)
10717      */
10718     @IdRes
10719     @InspectableProperty
10720     public int getAccessibilityTraversalAfter() {
10721         return mAccessibilityTraversalAfterId;
10722     }
10723 
10724     /**
10725      * Gets the id of a view for which this view serves as a label for
10726      * accessibility purposes.
10727      *
10728      * @return The labeled view id.
10729      */
10730     @IdRes
10731     @ViewDebug.ExportedProperty(category = "accessibility")
10732     @InspectableProperty
10733     public int getLabelFor() {
10734         return mLabelForId;
10735     }
10736 
10737     /**
10738      * Sets the id of a view for which this view serves as a label for
10739      * accessibility purposes.
10740      *
10741      * @param id The labeled view id.
10742      */
10743     @RemotableViewMethod
10744     public void setLabelFor(@IdRes int id) {
10745         if (mLabelForId == id) {
10746             return;
10747         }
10748         mLabelForId = id;
10749         if (mLabelForId != View.NO_ID
10750                 && mID == View.NO_ID) {
10751             mID = generateViewId();
10752         }
10753         notifyViewAccessibilityStateChangedIfNeeded(
10754                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10755     }
10756 
10757     /**
10758      * Invoked whenever this view loses focus, either by losing window focus or by losing
10759      * focus within its window. This method can be used to clear any state tied to the
10760      * focus. For instance, if a button is held pressed with the trackball and the window
10761      * loses focus, this method can be used to cancel the press.
10762      *
10763      * Subclasses of View overriding this method should always call super.onFocusLost().
10764      *
10765      * @see #onFocusChanged(boolean, int, android.graphics.Rect)
10766      * @see #onWindowFocusChanged(boolean)
10767      *
10768      * @hide pending API council approval
10769      */
10770     @CallSuper
10771     @UnsupportedAppUsage
10772     protected void onFocusLost() {
10773         resetPressedState();
10774     }
10775 
10776     private void resetPressedState() {
10777         if ((mViewFlags & ENABLED_MASK) == DISABLED) {
10778             return;
10779         }
10780 
10781         if (isPressed()) {
10782             setPressed(false);
10783 
10784             if (!mHasPerformedLongPress) {
10785                 removeLongPressCallback();
10786             }
10787         }
10788     }
10789 
10790     /**
10791      * Returns true if this view has focus
10792      *
10793      * @return True if this view has focus, false otherwise.
10794      */
10795     @ViewDebug.ExportedProperty(category = "focus")
10796     @InspectableProperty(hasAttributeId = false)
10797     public boolean isFocused() {
10798         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
10799     }
10800 
10801     /**
10802      * Find the view in the hierarchy rooted at this view that currently has
10803      * focus.
10804      *
10805      * @return The view that currently has focus, or null if no focused view can
10806      *         be found.
10807      */
10808     public View findFocus() {
10809         return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
10810     }
10811 
10812     /**
10813      * Indicates whether this view is one of the set of scrollable containers in
10814      * its window.
10815      *
10816      * @return whether this view is one of the set of scrollable containers in
10817      * its window
10818      *
10819      * @attr ref android.R.styleable#View_isScrollContainer
10820      */
10821     @InspectableProperty(name = "isScrollContainer")
10822     public boolean isScrollContainer() {
10823         return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
10824     }
10825 
10826     /**
10827      * Change whether this view is one of the set of scrollable containers in
10828      * its window.  This will be used to determine whether the window can
10829      * resize or must pan when a soft input area is open -- scrollable
10830      * containers allow the window to use resize mode since the container
10831      * will appropriately shrink.
10832      *
10833      * @attr ref android.R.styleable#View_isScrollContainer
10834      */
10835     public void setScrollContainer(boolean isScrollContainer) {
10836         if (isScrollContainer) {
10837             if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
10838                 mAttachInfo.mScrollContainers.add(this);
10839                 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
10840             }
10841             mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
10842         } else {
10843             if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
10844                 mAttachInfo.mScrollContainers.remove(this);
10845             }
10846             mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
10847         }
10848     }
10849 
10850     /**
10851      * Returns the quality of the drawing cache.
10852      *
10853      * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
10854      *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
10855      *
10856      * @see #setDrawingCacheQuality(int)
10857      * @see #setDrawingCacheEnabled(boolean)
10858      * @see #isDrawingCacheEnabled()
10859      *
10860      * @attr ref android.R.styleable#View_drawingCacheQuality
10861      *
10862      * @deprecated The view drawing cache was largely made obsolete with the introduction of
10863      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
10864      * layers are largely unnecessary and can easily result in a net loss in performance due to the
10865      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
10866      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
10867      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
10868      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
10869      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
10870      * software-rendered usages are discouraged and have compatibility issues with hardware-only
10871      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
10872      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
10873      * reports or unit testing the {@link PixelCopy} API is recommended.
10874      */
10875     @Deprecated
10876     @DrawingCacheQuality
10877     @InspectableProperty(enumMapping = {
10878             @EnumEntry(value = DRAWING_CACHE_QUALITY_LOW, name = "low"),
10879             @EnumEntry(value = DRAWING_CACHE_QUALITY_HIGH, name = "high"),
10880             @EnumEntry(value = DRAWING_CACHE_QUALITY_AUTO, name = "auto")
10881     })
10882     public int getDrawingCacheQuality() {
10883         return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
10884     }
10885 
10886     /**
10887      * Set the drawing cache quality of this view. This value is used only when the
10888      * drawing cache is enabled
10889      *
10890      * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
10891      *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
10892      *
10893      * @see #getDrawingCacheQuality()
10894      * @see #setDrawingCacheEnabled(boolean)
10895      * @see #isDrawingCacheEnabled()
10896      *
10897      * @attr ref android.R.styleable#View_drawingCacheQuality
10898      *
10899      * @deprecated The view drawing cache was largely made obsolete with the introduction of
10900      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
10901      * layers are largely unnecessary and can easily result in a net loss in performance due to the
10902      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
10903      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
10904      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
10905      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
10906      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
10907      * software-rendered usages are discouraged and have compatibility issues with hardware-only
10908      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
10909      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
10910      * reports or unit testing the {@link PixelCopy} API is recommended.
10911      */
10912     @Deprecated
10913     public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
10914         setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
10915     }
10916 
10917     /**
10918      * Returns whether the screen should remain on, corresponding to the current
10919      * value of {@link #KEEP_SCREEN_ON}.
10920      *
10921      * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
10922      *
10923      * @see #setKeepScreenOn(boolean)
10924      *
10925      * @attr ref android.R.styleable#View_keepScreenOn
10926      */
10927     @InspectableProperty
10928     public boolean getKeepScreenOn() {
10929         return (mViewFlags & KEEP_SCREEN_ON) != 0;
10930     }
10931 
10932     /**
10933      * Controls whether the screen should remain on, modifying the
10934      * value of {@link #KEEP_SCREEN_ON}.
10935      *
10936      * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
10937      *
10938      * @see #getKeepScreenOn()
10939      *
10940      * @attr ref android.R.styleable#View_keepScreenOn
10941      */
10942     public void setKeepScreenOn(boolean keepScreenOn) {
10943         setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
10944     }
10945 
10946     /**
10947      * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
10948      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
10949      *
10950      * @attr ref android.R.styleable#View_nextFocusLeft
10951      */
10952     @IdRes
10953     @InspectableProperty(name = "nextFocusLeft")
10954     public int getNextFocusLeftId() {
10955         return mNextFocusLeftId;
10956     }
10957 
10958     /**
10959      * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
10960      * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
10961      * decide automatically.
10962      *
10963      * @attr ref android.R.styleable#View_nextFocusLeft
10964      */
10965     public void setNextFocusLeftId(@IdRes int nextFocusLeftId) {
10966         mNextFocusLeftId = nextFocusLeftId;
10967     }
10968 
10969     /**
10970      * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
10971      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
10972      *
10973      * @attr ref android.R.styleable#View_nextFocusRight
10974      */
10975     @IdRes
10976     @InspectableProperty(name = "nextFocusRight")
10977     public int getNextFocusRightId() {
10978         return mNextFocusRightId;
10979     }
10980 
10981     /**
10982      * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
10983      * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
10984      * decide automatically.
10985      *
10986      * @attr ref android.R.styleable#View_nextFocusRight
10987      */
10988     public void setNextFocusRightId(@IdRes int nextFocusRightId) {
10989         mNextFocusRightId = nextFocusRightId;
10990     }
10991 
10992     /**
10993      * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
10994      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
10995      *
10996      * @attr ref android.R.styleable#View_nextFocusUp
10997      */
10998     @IdRes
10999     @InspectableProperty(name = "nextFocusUp")
11000     public int getNextFocusUpId() {
11001         return mNextFocusUpId;
11002     }
11003 
11004     /**
11005      * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
11006      * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
11007      * decide automatically.
11008      *
11009      * @attr ref android.R.styleable#View_nextFocusUp
11010      */
11011     public void setNextFocusUpId(@IdRes int nextFocusUpId) {
11012         mNextFocusUpId = nextFocusUpId;
11013     }
11014 
11015     /**
11016      * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
11017      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
11018      *
11019      * @attr ref android.R.styleable#View_nextFocusDown
11020      */
11021     @IdRes
11022     @InspectableProperty(name = "nextFocusDown")
11023     public int getNextFocusDownId() {
11024         return mNextFocusDownId;
11025     }
11026 
11027     /**
11028      * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
11029      * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
11030      * decide automatically.
11031      *
11032      * @attr ref android.R.styleable#View_nextFocusDown
11033      */
11034     public void setNextFocusDownId(@IdRes int nextFocusDownId) {
11035         mNextFocusDownId = nextFocusDownId;
11036     }
11037 
11038     /**
11039      * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
11040      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
11041      *
11042      * @attr ref android.R.styleable#View_nextFocusForward
11043      */
11044     @IdRes
11045     @InspectableProperty(name = "nextFocusForward")
11046     public int getNextFocusForwardId() {
11047         return mNextFocusForwardId;
11048     }
11049 
11050     /**
11051      * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
11052      * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
11053      * decide automatically.
11054      *
11055      * @attr ref android.R.styleable#View_nextFocusForward
11056      */
11057     public void setNextFocusForwardId(@IdRes int nextFocusForwardId) {
11058         mNextFocusForwardId = nextFocusForwardId;
11059     }
11060 
11061     /**
11062      * Gets the id of the root of the next keyboard navigation cluster.
11063      * @return The next keyboard navigation cluster ID, or {@link #NO_ID} if the framework should
11064      * decide automatically.
11065      *
11066      * @attr ref android.R.styleable#View_nextClusterForward
11067      */
11068     @IdRes
11069     @InspectableProperty(name = "nextClusterForward")
11070     public int getNextClusterForwardId() {
11071         return mNextClusterForwardId;
11072     }
11073 
11074     /**
11075      * Sets the id of the view to use as the root of the next keyboard navigation cluster.
11076      * @param nextClusterForwardId The next cluster ID, or {@link #NO_ID} if the framework should
11077      * decide automatically.
11078      *
11079      * @attr ref android.R.styleable#View_nextClusterForward
11080      */
11081     public void setNextClusterForwardId(@IdRes int nextClusterForwardId) {
11082         mNextClusterForwardId = nextClusterForwardId;
11083     }
11084 
11085     /**
11086      * Returns the visibility of this view and all of its ancestors
11087      *
11088      * @return True if this view and all of its ancestors are {@link #VISIBLE}
11089      */
11090     public boolean isShown() {
11091         View current = this;
11092         //noinspection ConstantConditions
11093         do {
11094             if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
11095                 return false;
11096             }
11097             ViewParent parent = current.mParent;
11098             if (parent == null) {
11099                 return false; // We are not attached to the view root
11100             }
11101             if (!(parent instanceof View)) {
11102                 return true;
11103             }
11104             current = (View) parent;
11105         } while (current != null);
11106 
11107         return false;
11108     }
11109 
11110     /**
11111      * Called by the view hierarchy when the content insets for a window have
11112      * changed, to allow it to adjust its content to fit within those windows.
11113      * The content insets tell you the space that the status bar, input method,
11114      * and other system windows infringe on the application's window.
11115      *
11116      * <p>You do not normally need to deal with this function, since the default
11117      * window decoration given to applications takes care of applying it to the
11118      * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
11119      * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
11120      * and your content can be placed under those system elements.  You can then
11121      * use this method within your view hierarchy if you have parts of your UI
11122      * which you would like to ensure are not being covered.
11123      *
11124      * <p>The default implementation of this method simply applies the content
11125      * insets to the view's padding, consuming that content (modifying the
11126      * insets to be 0), and returning true.  This behavior is off by default, but can
11127      * be enabled through {@link #setFitsSystemWindows(boolean)}.
11128      *
11129      * <p>This function's traversal down the hierarchy is depth-first.  The same content
11130      * insets object is propagated down the hierarchy, so any changes made to it will
11131      * be seen by all following views (including potentially ones above in
11132      * the hierarchy since this is a depth-first traversal).  The first view
11133      * that returns true will abort the entire traversal.
11134      *
11135      * <p>The default implementation works well for a situation where it is
11136      * used with a container that covers the entire window, allowing it to
11137      * apply the appropriate insets to its content on all edges.  If you need
11138      * a more complicated layout (such as two different views fitting system
11139      * windows, one on the top of the window, and one on the bottom),
11140      * you can override the method and handle the insets however you would like.
11141      * Note that the insets provided by the framework are always relative to the
11142      * far edges of the window, not accounting for the location of the called view
11143      * within that window.  (In fact when this method is called you do not yet know
11144      * where the layout will place the view, as it is done before layout happens.)
11145      *
11146      * <p>Note: unlike many View methods, there is no dispatch phase to this
11147      * call.  If you are overriding it in a ViewGroup and want to allow the
11148      * call to continue to your children, you must be sure to call the super
11149      * implementation.
11150      *
11151      * <p>Here is a sample layout that makes use of fitting system windows
11152      * to have controls for a video view placed inside of the window decorations
11153      * that it hides and shows.  This can be used with code like the second
11154      * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
11155      *
11156      * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
11157      *
11158      * @param insets Current content insets of the window.  Prior to
11159      * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
11160      * the insets or else you and Android will be unhappy.
11161      *
11162      * @return {@code true} if this view applied the insets and it should not
11163      * continue propagating further down the hierarchy, {@code false} otherwise.
11164      * @see #getFitsSystemWindows()
11165      * @see #setFitsSystemWindows(boolean)
11166      * @see #setSystemUiVisibility(int)
11167      *
11168      * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
11169      * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
11170      * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
11171      * to implement handling their own insets.
11172      */
11173     @Deprecated
11174     protected boolean fitSystemWindows(Rect insets) {
11175         if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
11176             if (insets == null) {
11177                 // Null insets by definition have already been consumed.
11178                 // This call cannot apply insets since there are none to apply,
11179                 // so return false.
11180                 return false;
11181             }
11182             // If we're not in the process of dispatching the newer apply insets call,
11183             // that means we're not in the compatibility path. Dispatch into the newer
11184             // apply insets path and take things from there.
11185             try {
11186                 mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
11187                 return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
11188             } finally {
11189                 mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
11190             }
11191         } else {
11192             // We're being called from the newer apply insets path.
11193             // Perform the standard fallback behavior.
11194             return fitSystemWindowsInt(insets);
11195         }
11196     }
11197 
11198     private boolean fitSystemWindowsInt(Rect insets) {
11199         if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
11200             Rect localInsets = sThreadLocal.get();
11201             boolean res = computeFitSystemWindows(insets, localInsets);
11202             applyInsets(localInsets);
11203             return res;
11204         }
11205         return false;
11206     }
11207 
11208     private void applyInsets(Rect insets) {
11209         mUserPaddingStart = UNDEFINED_PADDING;
11210         mUserPaddingEnd = UNDEFINED_PADDING;
11211         mUserPaddingLeftInitial = insets.left;
11212         mUserPaddingRightInitial = insets.right;
11213         internalSetPadding(insets.left, insets.top, insets.right, insets.bottom);
11214     }
11215 
11216     /**
11217      * Called when the view should apply {@link WindowInsets} according to its internal policy.
11218      *
11219      * <p>This method should be overridden by views that wish to apply a policy different from or
11220      * in addition to the default behavior. Clients that wish to force a view subtree
11221      * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
11222      *
11223      * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
11224      * it will be called during dispatch instead of this method. The listener may optionally
11225      * call this method from its own implementation if it wishes to apply the view's default
11226      * insets policy in addition to its own.</p>
11227      *
11228      * <p>Implementations of this method should either return the insets parameter unchanged
11229      * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
11230      * that this view applied itself. This allows new inset types added in future platform
11231      * versions to pass through existing implementations unchanged without being erroneously
11232      * consumed.</p>
11233      *
11234      * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
11235      * property is set then the view will consume the system window insets and apply them
11236      * as padding for the view.</p>
11237      *
11238      * @param insets Insets to apply
11239      * @return The supplied insets with any applied insets consumed
11240      */
11241     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
11242         if ((mPrivateFlags4 & PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS) != 0
11243                 && (mViewFlags & FITS_SYSTEM_WINDOWS) != 0) {
11244             return onApplyFrameworkOptionalFitSystemWindows(insets);
11245         }
11246         if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
11247             // We weren't called from within a direct call to fitSystemWindows,
11248             // call into it as a fallback in case we're in a class that overrides it
11249             // and has logic to perform.
11250             if (fitSystemWindows(insets.getSystemWindowInsetsAsRect())) {
11251                 return insets.consumeSystemWindowInsets();
11252             }
11253         } else {
11254             // We were called from within a direct call to fitSystemWindows.
11255             if (fitSystemWindowsInt(insets.getSystemWindowInsetsAsRect())) {
11256                 return insets.consumeSystemWindowInsets();
11257             }
11258         }
11259         return insets;
11260     }
11261 
11262     private WindowInsets onApplyFrameworkOptionalFitSystemWindows(WindowInsets insets) {
11263         Rect localInsets = sThreadLocal.get();
11264         WindowInsets result = computeSystemWindowInsets(insets, localInsets);
11265         applyInsets(localInsets);
11266         return result;
11267     }
11268 
11269     /**
11270      * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
11271      * window insets to this view. The listener's
11272      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
11273      * method will be called instead of the view's
11274      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
11275      *
11276      * @param listener Listener to set
11277      *
11278      * @see #onApplyWindowInsets(WindowInsets)
11279      */
11280     public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
11281         getListenerInfo().mOnApplyWindowInsetsListener = listener;
11282     }
11283 
11284     /**
11285      * Request to apply the given window insets to this view or another view in its subtree.
11286      *
11287      * <p>This method should be called by clients wishing to apply insets corresponding to areas
11288      * obscured by window decorations or overlays. This can include the status and navigation bars,
11289      * action bars, input methods and more. New inset categories may be added in the future.
11290      * The method returns the insets provided minus any that were applied by this view or its
11291      * children.</p>
11292      *
11293      * <p>Clients wishing to provide custom behavior should override the
11294      * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
11295      * {@link OnApplyWindowInsetsListener} via the
11296      * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
11297      * method.</p>
11298      *
11299      * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
11300      * </p>
11301      *
11302      * @param insets Insets to apply
11303      * @return The provided insets minus the insets that were consumed
11304      */
11305     public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
11306         try {
11307             mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
11308             if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
11309                 return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
11310             } else {
11311                 return onApplyWindowInsets(insets);
11312             }
11313         } finally {
11314             mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
11315         }
11316     }
11317 
11318     /**
11319      * Sets a {@link WindowInsetsAnimation.Callback} to be notified about animations of windows that
11320      * cause insets.
11321      * <p>
11322      * The callback's {@link WindowInsetsAnimation.Callback#getDispatchMode()
11323      * dispatch mode} will affect whether animation callbacks are dispatched to the children of
11324      * this view.
11325      * </p>
11326      * @param callback The callback to set.
11327      */
11328     public void setWindowInsetsAnimationCallback(
11329             @Nullable WindowInsetsAnimation.Callback callback) {
11330         getListenerInfo().mWindowInsetsAnimationCallback = callback;
11331     }
11332 
11333     /**
11334      * @return {@code true} if any {@link WindowInsetsAnimation.Callback} is registered on the view
11335      *         or view tree of the sub-hierarchy {@code false} otherwise.
11336      * @hide
11337      */
11338     public boolean hasWindowInsetsAnimationCallback() {
11339         return getListenerInfo().mWindowInsetsAnimationCallback != null;
11340     }
11341 
11342     /**
11343      * Dispatches {@link WindowInsetsAnimation.Callback#onPrepare(WindowInsetsAnimation)}
11344      * when Window Insets animation is being prepared.
11345      * @param animation current animation
11346      *
11347      * @see WindowInsetsAnimation.Callback#onPrepare(WindowInsetsAnimation)
11348      */
11349     public void dispatchWindowInsetsAnimationPrepare(
11350             @NonNull WindowInsetsAnimation animation) {
11351         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
11352             mListenerInfo.mWindowInsetsAnimationCallback.onPrepare(animation);
11353         }
11354     }
11355 
11356     /**
11357      * Dispatches {@link WindowInsetsAnimation.Callback#onStart(WindowInsetsAnimation, Bounds)}
11358      * when Window Insets animation is started.
11359      * @param animation current animation
11360      * @param bounds the upper and lower {@link Bounds} that provides range of
11361      *  {@link WindowInsetsAnimation}.
11362      * @return the upper and lower {@link Bounds}.
11363      */
11364     @NonNull
11365     public Bounds dispatchWindowInsetsAnimationStart(
11366             @NonNull WindowInsetsAnimation animation, @NonNull Bounds bounds) {
11367         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
11368             return mListenerInfo.mWindowInsetsAnimationCallback.onStart(animation, bounds);
11369         }
11370         return bounds;
11371     }
11372 
11373     /**
11374      * Dispatches {@link WindowInsetsAnimation.Callback#onProgress(WindowInsets, List)}
11375      * when Window Insets animation makes progress.
11376      * @param insets The current {@link WindowInsets}.
11377      * @param runningAnimations The currently running {@link WindowInsetsAnimation}s.
11378      * @return current {@link WindowInsets}.
11379      */
11380     @NonNull
11381     public WindowInsets dispatchWindowInsetsAnimationProgress(@NonNull WindowInsets insets,
11382             @NonNull List<WindowInsetsAnimation> runningAnimations) {
11383         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
11384             return mListenerInfo.mWindowInsetsAnimationCallback.onProgress(insets,
11385                     runningAnimations);
11386         } else {
11387             return insets;
11388         }
11389     }
11390 
11391     /**
11392      * Dispatches {@link WindowInsetsAnimation.Callback#onEnd(WindowInsetsAnimation)}
11393      * when Window Insets animation ends.
11394      * @param animation The current ongoing {@link WindowInsetsAnimation}.
11395      */
11396     public void dispatchWindowInsetsAnimationEnd(@NonNull WindowInsetsAnimation animation) {
11397         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
11398             mListenerInfo.mWindowInsetsAnimationCallback.onEnd(animation);
11399         }
11400     }
11401 
11402     /**
11403      * Sets a list of areas within this view's post-layout coordinate space where the system
11404      * should not intercept touch or other pointing device gestures. <em>This method should
11405      * be called by {@link #onLayout(boolean, int, int, int, int)} or {@link #onDraw(Canvas)}.</em>
11406      *
11407      * <p>Use this to tell the system which specific sub-areas of a view need to receive gesture
11408      * input in order to function correctly in the presence of global system gestures that may
11409      * conflict. For example, if the system wishes to capture swipe-in-from-screen-edge gestures
11410      * to provide system-level navigation functionality, a view such as a navigation drawer
11411      * container can mark the left (or starting) edge of itself as requiring gesture capture
11412      * priority using this API. The system may then choose to relax its own gesture recognition
11413      * to allow the app to consume the user's gesture. It is not necessary for an app to register
11414      * exclusion rects for broadly spanning regions such as the entirety of a
11415      * <code>ScrollView</code> or for simple press and release click targets such as
11416      * <code>Button</code>. Mark an exclusion rect when interacting with a view requires
11417      * a precision touch gesture in a small area in either the X or Y dimension, such as
11418      * an edge swipe or dragging a <code>SeekBar</code> thumb.</p>
11419      *
11420      * <p>Do not modify the provided list after this method is called.</p>
11421      *
11422      * <p>Note: the system will put a limit of <code>200dp</code> on the vertical extent of the
11423      * exclusions it takes into account. The limit does not apply while the navigation
11424      * bar is {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY stickily} hidden, nor to the
11425      * {@link android.inputmethodservice.InputMethodService input method} and
11426      * {@link Intent#CATEGORY_HOME home activity}.
11427      * </p>
11428      *
11429      * @param rects A list of precision gesture regions that this view needs to function correctly
11430      */
11431     public void setSystemGestureExclusionRects(@NonNull List<Rect> rects) {
11432         if (rects.isEmpty() && mListenerInfo == null) return;
11433 
11434         final ListenerInfo info = getListenerInfo();
11435         if (rects.isEmpty()) {
11436             info.mSystemGestureExclusionRects = null;
11437             if (info.mPositionUpdateListener != null) {
11438                 mRenderNode.removePositionUpdateListener(info.mPositionUpdateListener);
11439             }
11440         } else {
11441             info.mSystemGestureExclusionRects = rects;
11442             if (info.mPositionUpdateListener == null) {
11443                 info.mPositionUpdateListener = new RenderNode.PositionUpdateListener() {
11444                     @Override
11445                     public void positionChanged(long n, int l, int t, int r, int b) {
11446                         postUpdateSystemGestureExclusionRects();
11447                     }
11448 
11449                     @Override
11450                     public void positionLost(long frameNumber) {
11451                         postUpdateSystemGestureExclusionRects();
11452                     }
11453                 };
11454                 mRenderNode.addPositionUpdateListener(info.mPositionUpdateListener);
11455             }
11456         }
11457         postUpdateSystemGestureExclusionRects();
11458     }
11459 
11460     /**
11461      * WARNING: this can be called by a hwui worker thread, not just the UI thread!
11462      */
11463     void postUpdateSystemGestureExclusionRects() {
11464         // Potentially racey from a background thread. It's ok if it's not perfect.
11465         final Handler h = getHandler();
11466         if (h != null) {
11467             h.postAtFrontOfQueue(this::updateSystemGestureExclusionRects);
11468         }
11469     }
11470 
11471     void updateSystemGestureExclusionRects() {
11472         final AttachInfo ai = mAttachInfo;
11473         if (ai != null) {
11474             ai.mViewRootImpl.updateSystemGestureExclusionRectsForView(this);
11475         }
11476     }
11477 
11478     /**
11479      * Retrieve the list of areas within this view's post-layout coordinate space where the system
11480      * should not intercept touch or other pointing device gestures.
11481      *
11482      * <p>Do not modify the returned list.</p>
11483      *
11484      * @return the list set by {@link #setSystemGestureExclusionRects(List)}
11485      */
11486     @NonNull
11487     public List<Rect> getSystemGestureExclusionRects() {
11488         final ListenerInfo info = mListenerInfo;
11489         if (info != null) {
11490             final List<Rect> list = info.mSystemGestureExclusionRects;
11491             if (list != null) {
11492                 return list;
11493             }
11494         }
11495         return Collections.emptyList();
11496     }
11497 
11498     /**
11499      * Compute the view's coordinate within the surface.
11500      *
11501      * <p>Computes the coordinates of this view in its surface. The argument
11502      * must be an array of two integers. After the method returns, the array
11503      * contains the x and y location in that order.</p>
11504      *
11505      * @param location an array of two integers in which to hold the coordinates
11506      */
11507     public void getLocationInSurface(@NonNull @Size(2) int[] location) {
11508         getLocationInWindow(location);
11509         if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
11510             location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
11511             location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
11512         }
11513     }
11514 
11515     /**
11516      * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
11517      * only available if the view is attached.
11518      *
11519      * @return WindowInsets from the top of the view hierarchy or null if View is detached
11520      */
11521     public WindowInsets getRootWindowInsets() {
11522         if (mAttachInfo != null) {
11523             return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
11524         }
11525         return null;
11526     }
11527 
11528     /**
11529      * Retrieves the single {@link WindowInsetsController} of the window this view is attached to.
11530      *
11531      * @return The {@link WindowInsetsController} or {@code null} if the view is neither attached to
11532      *         a window nor a view tree with a decor.
11533      * @see Window#getInsetsController()
11534      */
11535     public @Nullable WindowInsetsController getWindowInsetsController() {
11536         if (mAttachInfo != null) {
11537             return mAttachInfo.mViewRootImpl.getInsetsController();
11538         }
11539         ViewParent parent = getParent();
11540         if (parent instanceof View) {
11541             return ((View) parent).getWindowInsetsController();
11542         } else if (parent instanceof ViewRootImpl) {
11543             // Between WindowManager.addView() and the first traversal AttachInfo isn't set yet.
11544             return ((ViewRootImpl) parent).getInsetsController();
11545         }
11546         return null;
11547     }
11548 
11549     /**
11550      * @hide Compute the insets that should be consumed by this view and the ones
11551      * that should propagate to those under it.
11552      *
11553      * Note: This is used by appcompat's ActionBarOverlayLayout through reflection.
11554      *
11555      * @param inoutInsets the insets given to this view
11556      * @param outLocalInsets the insets that should be applied to this view
11557      * @deprecated use {@link #computeSystemWindowInsets}
11558      * @return
11559      */
11560     @Deprecated
11561     @UnsupportedAppUsage
11562     protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
11563         WindowInsets innerInsets = computeSystemWindowInsets(new WindowInsets(inoutInsets),
11564                 outLocalInsets);
11565         inoutInsets.set(innerInsets.getSystemWindowInsetsAsRect());
11566         return innerInsets.isSystemWindowInsetsConsumed();
11567     }
11568 
11569     /**
11570      * Compute insets that should be consumed by this view and the ones that should propagate
11571      * to those under it.
11572      *
11573      * @param in Insets currently being processed by this View, likely received as a parameter
11574      *           to {@link #onApplyWindowInsets(WindowInsets)}.
11575      * @param outLocalInsets A Rect that will receive the insets that should be consumed
11576      *                       by this view
11577      * @return Insets that should be passed along to views under this one
11578      */
11579     public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
11580         boolean isOptionalFitSystemWindows = (mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) != 0
11581                 || (mPrivateFlags4 & PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS) != 0;
11582         if (isOptionalFitSystemWindows && mAttachInfo != null) {
11583             OnContentApplyWindowInsetsListener listener =
11584                     mAttachInfo.mContentOnApplyWindowInsetsListener;
11585             if (listener == null) {
11586                 // The application wants to take care of fitting system window for
11587                 // the content.
11588                 outLocalInsets.setEmpty();
11589                 return in;
11590             }
11591             Pair<Insets, WindowInsets> result = listener.onContentApplyWindowInsets(this, in);
11592             outLocalInsets.set(result.first.toRect());
11593             return result.second;
11594         } else {
11595             outLocalInsets.set(in.getSystemWindowInsetsAsRect());
11596             return in.consumeSystemWindowInsets().inset(outLocalInsets);
11597         }
11598     }
11599 
11600     /**
11601      * Sets whether or not this view should account for system screen decorations
11602      * such as the status bar and inset its content; that is, controlling whether
11603      * the default implementation of {@link #fitSystemWindows(Rect)} will be
11604      * executed.  See that method for more details.
11605      *
11606      * <p>Note that if you are providing your own implementation of
11607      * {@link #fitSystemWindows(Rect)}, then there is no need to set this
11608      * flag to true -- your implementation will be overriding the default
11609      * implementation that checks this flag.
11610      *
11611      * @param fitSystemWindows If true, then the default implementation of
11612      * {@link #fitSystemWindows(Rect)} will be executed.
11613      *
11614      * @attr ref android.R.styleable#View_fitsSystemWindows
11615      * @see #getFitsSystemWindows()
11616      * @see #fitSystemWindows(Rect)
11617      * @see #setSystemUiVisibility(int)
11618      */
11619     public void setFitsSystemWindows(boolean fitSystemWindows) {
11620         setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
11621     }
11622 
11623     /**
11624      * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
11625      * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
11626      * will be executed.
11627      *
11628      * @return {@code true} if the default implementation of
11629      * {@link #fitSystemWindows(Rect)} will be executed.
11630      *
11631      * @attr ref android.R.styleable#View_fitsSystemWindows
11632      * @see #setFitsSystemWindows(boolean)
11633      * @see #fitSystemWindows(Rect)
11634      * @see #setSystemUiVisibility(int)
11635      */
11636     @ViewDebug.ExportedProperty
11637     @InspectableProperty
11638     public boolean getFitsSystemWindows() {
11639         return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
11640     }
11641 
11642     /** @hide */
11643     @UnsupportedAppUsage
11644     public boolean fitsSystemWindows() {
11645         return getFitsSystemWindows();
11646     }
11647 
11648     /**
11649      * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
11650      * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
11651      */
11652     @Deprecated
11653     public void requestFitSystemWindows() {
11654         if (mParent != null) {
11655             mParent.requestFitSystemWindows();
11656         }
11657     }
11658 
11659     /**
11660      * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
11661      */
11662     public void requestApplyInsets() {
11663         requestFitSystemWindows();
11664     }
11665 
11666     /**
11667      * @see #OPTIONAL_FITS_SYSTEM_WINDOWS
11668      * @hide
11669      */
11670     @UnsupportedAppUsage
11671     public void makeOptionalFitsSystemWindows() {
11672         setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
11673     }
11674 
11675     /**
11676      * @see #PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS
11677      * @hide
11678      */
11679     public void makeFrameworkOptionalFitsSystemWindows() {
11680         mPrivateFlags4 |= PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS;
11681     }
11682 
11683     /**
11684      * @hide
11685      */
11686     public boolean isFrameworkOptionalFitsSystemWindows() {
11687         return (mPrivateFlags4 & PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS) != 0;
11688     }
11689 
11690     /**
11691      * Returns the visibility status for this view.
11692      *
11693      * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
11694      * @attr ref android.R.styleable#View_visibility
11695      */
11696     @ViewDebug.ExportedProperty(mapping = {
11697         @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
11698         @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
11699         @ViewDebug.IntToString(from = GONE,      to = "GONE")
11700     })
11701     @InspectableProperty(enumMapping = {
11702             @EnumEntry(value = VISIBLE, name = "visible"),
11703             @EnumEntry(value = INVISIBLE, name = "invisible"),
11704             @EnumEntry(value = GONE, name = "gone")
11705     })
11706     @Visibility
11707     public int getVisibility() {
11708         return mViewFlags & VISIBILITY_MASK;
11709     }
11710 
11711     /**
11712      * Set the visibility state of this view.
11713      *
11714      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
11715      * @attr ref android.R.styleable#View_visibility
11716      */
11717     @RemotableViewMethod
11718     public void setVisibility(@Visibility int visibility) {
11719         setFlags(visibility, VISIBILITY_MASK);
11720     }
11721 
11722     /**
11723      * Returns the enabled status for this view. The interpretation of the
11724      * enabled state varies by subclass.
11725      *
11726      * @return True if this view is enabled, false otherwise.
11727      */
11728     @ViewDebug.ExportedProperty
11729     @InspectableProperty
11730     public boolean isEnabled() {
11731         return (mViewFlags & ENABLED_MASK) == ENABLED;
11732     }
11733 
11734     /**
11735      * Set the enabled state of this view. The interpretation of the enabled
11736      * state varies by subclass.
11737      *
11738      * @param enabled True if this view is enabled, false otherwise.
11739      */
11740     @RemotableViewMethod
11741     public void setEnabled(boolean enabled) {
11742         if (enabled == isEnabled()) return;
11743 
11744         setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
11745 
11746         /*
11747          * The View most likely has to change its appearance, so refresh
11748          * the drawable state.
11749          */
11750         refreshDrawableState();
11751 
11752         // Invalidate too, since the default behavior for views is to be
11753         // be drawn at 50% alpha rather than to change the drawable.
11754         invalidate(true);
11755 
11756         if (!enabled) {
11757             cancelPendingInputEvents();
11758         }
11759     }
11760 
11761     /**
11762      * Set whether this view can receive the focus.
11763      * <p>
11764      * Setting this to false will also ensure that this view is not focusable
11765      * in touch mode.
11766      *
11767      * @param focusable If true, this view can receive the focus.
11768      *
11769      * @see #setFocusableInTouchMode(boolean)
11770      * @see #setFocusable(int)
11771      * @attr ref android.R.styleable#View_focusable
11772      */
11773     public void setFocusable(boolean focusable) {
11774         setFocusable(focusable ? FOCUSABLE : NOT_FOCUSABLE);
11775     }
11776 
11777     /**
11778      * Sets whether this view can receive focus.
11779      * <p>
11780      * Setting this to {@link #FOCUSABLE_AUTO} tells the framework to determine focusability
11781      * automatically based on the view's interactivity. This is the default.
11782      * <p>
11783      * Setting this to NOT_FOCUSABLE will ensure that this view is also not focusable
11784      * in touch mode.
11785      *
11786      * @param focusable One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE},
11787      *                  or {@link #FOCUSABLE_AUTO}.
11788      * @see #setFocusableInTouchMode(boolean)
11789      * @attr ref android.R.styleable#View_focusable
11790      */
11791     public void setFocusable(@Focusable int focusable) {
11792         if ((focusable & (FOCUSABLE_AUTO | FOCUSABLE)) == 0) {
11793             setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
11794         }
11795         setFlags(focusable, FOCUSABLE_MASK);
11796     }
11797 
11798     /**
11799      * Set whether this view can receive focus while in touch mode.
11800      *
11801      * Setting this to true will also ensure that this view is focusable.
11802      *
11803      * @param focusableInTouchMode If true, this view can receive the focus while
11804      *   in touch mode.
11805      *
11806      * @see #setFocusable(boolean)
11807      * @attr ref android.R.styleable#View_focusableInTouchMode
11808      */
11809     public void setFocusableInTouchMode(boolean focusableInTouchMode) {
11810         // Focusable in touch mode should always be set before the focusable flag
11811         // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
11812         // which, in touch mode, will not successfully request focus on this view
11813         // because the focusable in touch mode flag is not set
11814         setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
11815 
11816         // Clear FOCUSABLE_AUTO if set.
11817         if (focusableInTouchMode) {
11818             // Clears FOCUSABLE_AUTO if set.
11819             setFlags(FOCUSABLE, FOCUSABLE_MASK);
11820         }
11821     }
11822 
11823     /**
11824      * Sets the hints that help an {@link android.service.autofill.AutofillService} determine how
11825      * to autofill the view with the user's data.
11826      *
11827      * <p>Typically, there is only one way to autofill a view, but there could be more than one.
11828      * For example, if the application accepts either an username or email address to identify
11829      * an user.
11830      *
11831      * <p>These hints are not validated by the Android System, but passed "as is" to the service.
11832      * Hence, they can have any value, but it's recommended to use the {@code AUTOFILL_HINT_}
11833      * constants such as:
11834      * {@link #AUTOFILL_HINT_USERNAME}, {@link #AUTOFILL_HINT_PASSWORD},
11835      * {@link #AUTOFILL_HINT_EMAIL_ADDRESS},
11836      * {@link #AUTOFILL_HINT_NAME},
11837      * {@link #AUTOFILL_HINT_PHONE},
11838      * {@link #AUTOFILL_HINT_POSTAL_ADDRESS}, {@link #AUTOFILL_HINT_POSTAL_CODE},
11839      * {@link #AUTOFILL_HINT_CREDIT_CARD_NUMBER}, {@link #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE},
11840      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE},
11841      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
11842      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH} or
11843      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}.
11844      *
11845      * @param autofillHints The autofill hints to set. If the array is emtpy, {@code null} is set.
11846      * @attr ref android.R.styleable#View_autofillHints
11847      */
11848     public void setAutofillHints(@Nullable String... autofillHints) {
11849         if (autofillHints == null || autofillHints.length == 0) {
11850             mAutofillHints = null;
11851         } else {
11852             mAutofillHints = autofillHints;
11853         }
11854     }
11855 
11856     /**
11857      * @hide
11858      */
11859     @TestApi
11860     public void setAutofilled(boolean isAutofilled, boolean hideHighlight) {
11861         boolean wasChanged = isAutofilled != isAutofilled();
11862 
11863         if (wasChanged) {
11864             if (isAutofilled) {
11865                 mPrivateFlags3 |= PFLAG3_IS_AUTOFILLED;
11866             } else {
11867                 mPrivateFlags3 &= ~PFLAG3_IS_AUTOFILLED;
11868             }
11869 
11870             if (hideHighlight) {
11871                 mPrivateFlags4 |= PFLAG4_AUTOFILL_HIDE_HIGHLIGHT;
11872             } else {
11873                 mPrivateFlags4 &= ~PFLAG4_AUTOFILL_HIDE_HIGHLIGHT;
11874             }
11875 
11876             invalidate();
11877         }
11878     }
11879 
11880     /**
11881      * Set whether this view should have sound effects enabled for events such as
11882      * clicking and touching.
11883      *
11884      * <p>You may wish to disable sound effects for a view if you already play sounds,
11885      * for instance, a dial key that plays dtmf tones.
11886      *
11887      * @param soundEffectsEnabled whether sound effects are enabled for this view.
11888      * @see #isSoundEffectsEnabled()
11889      * @see #playSoundEffect(int)
11890      * @attr ref android.R.styleable#View_soundEffectsEnabled
11891      */
11892     public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
11893         setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
11894     }
11895 
11896     /**
11897      * @return whether this view should have sound effects enabled for events such as
11898      *     clicking and touching.
11899      *
11900      * @see #setSoundEffectsEnabled(boolean)
11901      * @see #playSoundEffect(int)
11902      * @attr ref android.R.styleable#View_soundEffectsEnabled
11903      */
11904     @ViewDebug.ExportedProperty
11905     @InspectableProperty
11906     public boolean isSoundEffectsEnabled() {
11907         return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
11908     }
11909 
11910     /**
11911      * Set whether this view should have haptic feedback for events such as
11912      * long presses.
11913      *
11914      * <p>You may wish to disable haptic feedback if your view already controls
11915      * its own haptic feedback.
11916      *
11917      * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
11918      * @see #isHapticFeedbackEnabled()
11919      * @see #performHapticFeedback(int)
11920      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
11921      */
11922     public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
11923         setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
11924     }
11925 
11926     /**
11927      * @return whether this view should have haptic feedback enabled for events
11928      * long presses.
11929      *
11930      * @see #setHapticFeedbackEnabled(boolean)
11931      * @see #performHapticFeedback(int)
11932      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
11933      */
11934     @ViewDebug.ExportedProperty
11935     @InspectableProperty
11936     public boolean isHapticFeedbackEnabled() {
11937         return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
11938     }
11939 
11940     /**
11941      * Returns the layout direction for this view.
11942      *
11943      * @return One of {@link #LAYOUT_DIRECTION_LTR},
11944      *   {@link #LAYOUT_DIRECTION_RTL},
11945      *   {@link #LAYOUT_DIRECTION_INHERIT} or
11946      *   {@link #LAYOUT_DIRECTION_LOCALE}.
11947      *
11948      * @attr ref android.R.styleable#View_layoutDirection
11949      *
11950      * @hide
11951      */
11952     @ViewDebug.ExportedProperty(category = "layout", mapping = {
11953         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
11954         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
11955         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
11956         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
11957     })
11958     @InspectableProperty(hasAttributeId = false, enumMapping = {
11959             @EnumEntry(value = LAYOUT_DIRECTION_LTR, name = "ltr"),
11960             @EnumEntry(value = LAYOUT_DIRECTION_RTL, name = "rtl"),
11961             @EnumEntry(value = LAYOUT_DIRECTION_INHERIT, name = "inherit"),
11962             @EnumEntry(value = LAYOUT_DIRECTION_LOCALE, name = "locale")
11963     })
11964     @LayoutDir
11965     public int getRawLayoutDirection() {
11966         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
11967     }
11968 
11969     /**
11970      * Set the layout direction for this view. This will propagate a reset of layout direction
11971      * resolution to the view's children and resolve layout direction for this view.
11972      *
11973      * @param layoutDirection the layout direction to set. Should be one of:
11974      *
11975      * {@link #LAYOUT_DIRECTION_LTR},
11976      * {@link #LAYOUT_DIRECTION_RTL},
11977      * {@link #LAYOUT_DIRECTION_INHERIT},
11978      * {@link #LAYOUT_DIRECTION_LOCALE}.
11979      *
11980      * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
11981      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
11982      * will return the default {@link #LAYOUT_DIRECTION_LTR}.
11983      *
11984      * @attr ref android.R.styleable#View_layoutDirection
11985      */
11986     @RemotableViewMethod
11987     public void setLayoutDirection(@LayoutDir int layoutDirection) {
11988         if (getRawLayoutDirection() != layoutDirection) {
11989             // Reset the current layout direction and the resolved one
11990             mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
11991             resetRtlProperties();
11992             // Set the new layout direction (filtered)
11993             mPrivateFlags2 |=
11994                     ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
11995             // We need to resolve all RTL properties as they all depend on layout direction
11996             resolveRtlPropertiesIfNeeded();
11997             requestLayout();
11998             invalidate(true);
11999         }
12000     }
12001 
12002     /**
12003      * Returns the resolved layout direction for this view.
12004      *
12005      * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
12006      * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
12007      *
12008      * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
12009      * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
12010      *
12011      * @attr ref android.R.styleable#View_layoutDirection
12012      */
12013     @ViewDebug.ExportedProperty(category = "layout", mapping = {
12014         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
12015         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
12016     })
12017     @InspectableProperty(enumMapping = {
12018             @EnumEntry(value = LAYOUT_DIRECTION_LTR, name = "ltr"),
12019             @EnumEntry(value = LAYOUT_DIRECTION_RTL, name = "rtl")
12020     })
12021     @ResolvedLayoutDir
12022     public int getLayoutDirection() {
12023         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
12024         if (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
12025             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
12026             return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
12027         }
12028         return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
12029                 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
12030     }
12031 
12032     /**
12033      * Indicates whether or not this view's layout is right-to-left. This is resolved from
12034      * layout attribute and/or the inherited value from the parent
12035      *
12036      * @return true if the layout is right-to-left.
12037      *
12038      * @hide
12039      */
12040     @ViewDebug.ExportedProperty(category = "layout")
12041     @UnsupportedAppUsage
12042     public boolean isLayoutRtl() {
12043         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
12044     }
12045 
12046     /**
12047      * Indicates whether the view is currently tracking transient state that the
12048      * app should not need to concern itself with saving and restoring, but that
12049      * the framework should take special note to preserve when possible.
12050      *
12051      * <p>A view with transient state cannot be trivially rebound from an external
12052      * data source, such as an adapter binding item views in a list. This may be
12053      * because the view is performing an animation, tracking user selection
12054      * of content, or similar.</p>
12055      *
12056      * @return true if the view has transient state
12057      */
12058     @ViewDebug.ExportedProperty(category = "layout")
12059     public boolean hasTransientState() {
12060         return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
12061     }
12062 
12063     /**
12064      * Set whether this view is currently tracking transient state that the
12065      * framework should attempt to preserve when possible. This flag is reference counted,
12066      * so every call to setHasTransientState(true) should be paired with a later call
12067      * to setHasTransientState(false).
12068      *
12069      * <p>A view with transient state cannot be trivially rebound from an external
12070      * data source, such as an adapter binding item views in a list. This may be
12071      * because the view is performing an animation, tracking user selection
12072      * of content, or similar.</p>
12073      *
12074      * @param hasTransientState true if this view has transient state
12075      */
12076     public void setHasTransientState(boolean hasTransientState) {
12077         final boolean oldHasTransientState = hasTransientState();
12078         mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
12079                 mTransientStateCount - 1;
12080         if (mTransientStateCount < 0) {
12081             mTransientStateCount = 0;
12082             Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
12083                     "unmatched pair of setHasTransientState calls");
12084         } else if ((hasTransientState && mTransientStateCount == 1) ||
12085                 (!hasTransientState && mTransientStateCount == 0)) {
12086             // update flag if we've just incremented up from 0 or decremented down to 0
12087             mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
12088                     (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
12089             final boolean newHasTransientState = hasTransientState();
12090             if (mParent != null && newHasTransientState != oldHasTransientState) {
12091                 try {
12092                     mParent.childHasTransientStateChanged(this, newHasTransientState);
12093                 } catch (AbstractMethodError e) {
12094                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
12095                             " does not fully implement ViewParent", e);
12096                 }
12097             }
12098         }
12099     }
12100 
12101     /**
12102      * Returns true if this view is currently attached to a window.
12103      */
12104     public boolean isAttachedToWindow() {
12105         return mAttachInfo != null;
12106     }
12107 
12108     /**
12109      * Returns true if this view has been through at least one layout since it
12110      * was last attached to or detached from a window.
12111      */
12112     public boolean isLaidOut() {
12113         return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
12114     }
12115 
12116     /**
12117      * @return {@code true} if laid-out and not about to do another layout.
12118      */
12119     boolean isLayoutValid() {
12120         return isLaidOut() && ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == 0);
12121     }
12122 
12123     /**
12124      * If this view doesn't do any drawing on its own, set this flag to
12125      * allow further optimizations. By default, this flag is not set on
12126      * View, but could be set on some View subclasses such as ViewGroup.
12127      *
12128      * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
12129      * you should clear this flag.
12130      *
12131      * @param willNotDraw whether or not this View draw on its own
12132      */
12133     public void setWillNotDraw(boolean willNotDraw) {
12134         setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
12135     }
12136 
12137     /**
12138      * Returns whether or not this View draws on its own.
12139      *
12140      * @return true if this view has nothing to draw, false otherwise
12141      */
12142     @ViewDebug.ExportedProperty(category = "drawing")
12143     public boolean willNotDraw() {
12144         return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
12145     }
12146 
12147     /**
12148      * When a View's drawing cache is enabled, drawing is redirected to an
12149      * offscreen bitmap. Some views, like an ImageView, must be able to
12150      * bypass this mechanism if they already draw a single bitmap, to avoid
12151      * unnecessary usage of the memory.
12152      *
12153      * @param willNotCacheDrawing true if this view does not cache its
12154      *        drawing, false otherwise
12155      *
12156      * @deprecated The view drawing cache was largely made obsolete with the introduction of
12157      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
12158      * layers are largely unnecessary and can easily result in a net loss in performance due to the
12159      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
12160      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
12161      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
12162      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
12163      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
12164      * software-rendered usages are discouraged and have compatibility issues with hardware-only
12165      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
12166      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
12167      * reports or unit testing the {@link PixelCopy} API is recommended.
12168      */
12169     @Deprecated
12170     public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
12171         setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
12172     }
12173 
12174     /**
12175      * Returns whether or not this View can cache its drawing or not.
12176      *
12177      * @return true if this view does not cache its drawing, false otherwise
12178      *
12179      * @deprecated The view drawing cache was largely made obsolete with the introduction of
12180      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
12181      * layers are largely unnecessary and can easily result in a net loss in performance due to the
12182      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
12183      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
12184      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
12185      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
12186      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
12187      * software-rendered usages are discouraged and have compatibility issues with hardware-only
12188      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
12189      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
12190      * reports or unit testing the {@link PixelCopy} API is recommended.
12191      */
12192     @ViewDebug.ExportedProperty(category = "drawing")
12193     @Deprecated
12194     public boolean willNotCacheDrawing() {
12195         return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
12196     }
12197 
12198     /**
12199      * Indicates whether this view reacts to click events or not.
12200      *
12201      * @return true if the view is clickable, false otherwise
12202      *
12203      * @see #setClickable(boolean)
12204      * @attr ref android.R.styleable#View_clickable
12205      */
12206     @ViewDebug.ExportedProperty
12207     @InspectableProperty
12208     public boolean isClickable() {
12209         return (mViewFlags & CLICKABLE) == CLICKABLE;
12210     }
12211 
12212     /**
12213      * Enables or disables click events for this view. When a view
12214      * is clickable it will change its state to "pressed" on every click.
12215      * Subclasses should set the view clickable to visually react to
12216      * user's clicks.
12217      *
12218      * @param clickable true to make the view clickable, false otherwise
12219      *
12220      * @see #isClickable()
12221      * @attr ref android.R.styleable#View_clickable
12222      */
12223     public void setClickable(boolean clickable) {
12224         setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
12225     }
12226 
12227     /**
12228      * Indicates whether this view reacts to long click events or not.
12229      *
12230      * @return true if the view is long clickable, false otherwise
12231      *
12232      * @see #setLongClickable(boolean)
12233      * @attr ref android.R.styleable#View_longClickable
12234      */
12235     @InspectableProperty
12236     public boolean isLongClickable() {
12237         return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
12238     }
12239 
12240     /**
12241      * Enables or disables long click events for this view. When a view is long
12242      * clickable it reacts to the user holding down the button for a longer
12243      * duration than a tap. This event can either launch the listener or a
12244      * context menu.
12245      *
12246      * @param longClickable true to make the view long clickable, false otherwise
12247      * @see #isLongClickable()
12248      * @attr ref android.R.styleable#View_longClickable
12249      */
12250     public void setLongClickable(boolean longClickable) {
12251         setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
12252     }
12253 
12254     /**
12255      * Indicates whether this view reacts to context clicks or not.
12256      *
12257      * @return true if the view is context clickable, false otherwise
12258      * @see #setContextClickable(boolean)
12259      * @attr ref android.R.styleable#View_contextClickable
12260      */
12261     @InspectableProperty
12262     public boolean isContextClickable() {
12263         return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
12264     }
12265 
12266     /**
12267      * Enables or disables context clicking for this view. This event can launch the listener.
12268      *
12269      * @param contextClickable true to make the view react to a context click, false otherwise
12270      * @see #isContextClickable()
12271      * @attr ref android.R.styleable#View_contextClickable
12272      */
12273     public void setContextClickable(boolean contextClickable) {
12274         setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
12275     }
12276 
12277     /**
12278      * Sets the pressed state for this view and provides a touch coordinate for
12279      * animation hinting.
12280      *
12281      * @param pressed Pass true to set the View's internal state to "pressed",
12282      *            or false to reverts the View's internal state from a
12283      *            previously set "pressed" state.
12284      * @param x The x coordinate of the touch that caused the press
12285      * @param y The y coordinate of the touch that caused the press
12286      */
12287     private void setPressed(boolean pressed, float x, float y) {
12288         if (pressed) {
12289             drawableHotspotChanged(x, y);
12290         }
12291 
12292         setPressed(pressed);
12293     }
12294 
12295     /**
12296      * Sets the pressed state for this view.
12297      *
12298      * @see #isClickable()
12299      * @see #setClickable(boolean)
12300      *
12301      * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
12302      *        the View's internal state from a previously set "pressed" state.
12303      */
12304     public void setPressed(boolean pressed) {
12305         final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
12306 
12307         if (pressed) {
12308             mPrivateFlags |= PFLAG_PRESSED;
12309         } else {
12310             mPrivateFlags &= ~PFLAG_PRESSED;
12311         }
12312 
12313         if (needsRefresh) {
12314             refreshDrawableState();
12315         }
12316         dispatchSetPressed(pressed);
12317     }
12318 
12319     /**
12320      * Dispatch setPressed to all of this View's children.
12321      *
12322      * @see #setPressed(boolean)
12323      *
12324      * @param pressed The new pressed state
12325      */
12326     protected void dispatchSetPressed(boolean pressed) {
12327     }
12328 
12329     /**
12330      * Indicates whether the view is currently in pressed state. Unless
12331      * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
12332      * the pressed state.
12333      *
12334      * @see #setPressed(boolean)
12335      * @see #isClickable()
12336      * @see #setClickable(boolean)
12337      *
12338      * @return true if the view is currently pressed, false otherwise
12339      */
12340     @ViewDebug.ExportedProperty
12341     @InspectableProperty(hasAttributeId = false)
12342     public boolean isPressed() {
12343         return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
12344     }
12345 
12346     /**
12347      * @hide
12348      * Indicates whether this view will participate in data collection through
12349      * {@link ViewStructure}.  If true, it will not provide any data
12350      * for itself or its children.  If false, the normal data collection will be allowed.
12351      *
12352      * @return Returns false if assist data collection is not blocked, else true.
12353      *
12354      * @see #setAssistBlocked(boolean)
12355      * @attr ref android.R.styleable#View_assistBlocked
12356      */
12357     public boolean isAssistBlocked() {
12358         return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
12359     }
12360 
12361     /**
12362      * @hide
12363      * Controls whether assist data collection from this view and its children is enabled
12364      * (that is, whether {@link #onProvideStructure} and
12365      * {@link #onProvideVirtualStructure} will be called).  The default value is false,
12366      * allowing normal assist collection.  Setting this to false will disable assist collection.
12367      *
12368      * @param enabled Set to true to <em>disable</em> assist data collection, or false
12369      * (the default) to allow it.
12370      *
12371      * @see #isAssistBlocked()
12372      * @see #onProvideStructure
12373      * @see #onProvideVirtualStructure
12374      * @attr ref android.R.styleable#View_assistBlocked
12375      */
12376     @UnsupportedAppUsage
12377     public void setAssistBlocked(boolean enabled) {
12378         if (enabled) {
12379             mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
12380         } else {
12381             mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
12382         }
12383     }
12384 
12385     /**
12386      * Indicates whether this view will save its state (that is,
12387      * whether its {@link #onSaveInstanceState} method will be called).
12388      *
12389      * @return Returns true if the view state saving is enabled, else false.
12390      *
12391      * @see #setSaveEnabled(boolean)
12392      * @attr ref android.R.styleable#View_saveEnabled
12393      */
12394     @InspectableProperty
12395     public boolean isSaveEnabled() {
12396         return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
12397     }
12398 
12399     /**
12400      * Controls whether the saving of this view's state is
12401      * enabled (that is, whether its {@link #onSaveInstanceState} method
12402      * will be called).  Note that even if freezing is enabled, the
12403      * view still must have an id assigned to it (via {@link #setId(int)})
12404      * for its state to be saved.  This flag can only disable the
12405      * saving of this view; any child views may still have their state saved.
12406      *
12407      * @param enabled Set to false to <em>disable</em> state saving, or true
12408      * (the default) to allow it.
12409      *
12410      * @see #isSaveEnabled()
12411      * @see #setId(int)
12412      * @see #onSaveInstanceState()
12413      * @attr ref android.R.styleable#View_saveEnabled
12414      */
12415     public void setSaveEnabled(boolean enabled) {
12416         setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
12417     }
12418 
12419     /**
12420      * Gets whether the framework should discard touches when the view's
12421      * window is obscured by another visible window.
12422      * Refer to the {@link View} security documentation for more details.
12423      *
12424      * @return True if touch filtering is enabled.
12425      *
12426      * @see #setFilterTouchesWhenObscured(boolean)
12427      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
12428      */
12429     @ViewDebug.ExportedProperty
12430     @InspectableProperty
12431     public boolean getFilterTouchesWhenObscured() {
12432         return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
12433     }
12434 
12435     /**
12436      * Sets whether the framework should discard touches when the view's
12437      * window is obscured by another visible window.
12438      * Refer to the {@link View} security documentation for more details.
12439      *
12440      * @param enabled True if touch filtering should be enabled.
12441      *
12442      * @see #getFilterTouchesWhenObscured
12443      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
12444      */
12445     public void setFilterTouchesWhenObscured(boolean enabled) {
12446         setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
12447                 FILTER_TOUCHES_WHEN_OBSCURED);
12448     }
12449 
12450     /**
12451      * Indicates whether the entire hierarchy under this view will save its
12452      * state when a state saving traversal occurs from its parent.  The default
12453      * is true; if false, these views will not be saved unless
12454      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
12455      *
12456      * @return Returns true if the view state saving from parent is enabled, else false.
12457      *
12458      * @see #setSaveFromParentEnabled(boolean)
12459      */
12460     public boolean isSaveFromParentEnabled() {
12461         return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
12462     }
12463 
12464     /**
12465      * Controls whether the entire hierarchy under this view will save its
12466      * state when a state saving traversal occurs from its parent.  The default
12467      * is true; if false, these views will not be saved unless
12468      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
12469      *
12470      * @param enabled Set to false to <em>disable</em> state saving, or true
12471      * (the default) to allow it.
12472      *
12473      * @see #isSaveFromParentEnabled()
12474      * @see #setId(int)
12475      * @see #onSaveInstanceState()
12476      */
12477     public void setSaveFromParentEnabled(boolean enabled) {
12478         setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
12479     }
12480 
12481 
12482     /**
12483      * Returns whether this View is currently able to take focus.
12484      *
12485      * @return True if this view can take focus, or false otherwise.
12486      */
12487     @ViewDebug.ExportedProperty(category = "focus")
12488     public final boolean isFocusable() {
12489         return FOCUSABLE == (mViewFlags & FOCUSABLE);
12490     }
12491 
12492     /**
12493      * Returns the focusable setting for this view.
12494      *
12495      * @return One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE}, or {@link #FOCUSABLE_AUTO}.
12496      * @attr ref android.R.styleable#View_focusable
12497      */
12498     @ViewDebug.ExportedProperty(mapping = {
12499             @ViewDebug.IntToString(from = NOT_FOCUSABLE, to = "NOT_FOCUSABLE"),
12500             @ViewDebug.IntToString(from = FOCUSABLE, to = "FOCUSABLE"),
12501             @ViewDebug.IntToString(from = FOCUSABLE_AUTO, to = "FOCUSABLE_AUTO")
12502             }, category = "focus")
12503     @InspectableProperty(enumMapping = {
12504             @EnumEntry(value = NOT_FOCUSABLE, name = "false"),
12505             @EnumEntry(value = FOCUSABLE, name = "true"),
12506             @EnumEntry(value = FOCUSABLE_AUTO, name = "auto")
12507     })
12508     @Focusable
12509     public int getFocusable() {
12510         return (mViewFlags & FOCUSABLE_AUTO) > 0 ? FOCUSABLE_AUTO : mViewFlags & FOCUSABLE;
12511     }
12512 
12513     /**
12514      * When a view is focusable, it may not want to take focus when in touch mode.
12515      * For example, a button would like focus when the user is navigating via a D-pad
12516      * so that the user can click on it, but once the user starts touching the screen,
12517      * the button shouldn't take focus
12518      * @return Whether the view is focusable in touch mode.
12519      * @attr ref android.R.styleable#View_focusableInTouchMode
12520      */
12521     @ViewDebug.ExportedProperty(category = "focus")
12522     @InspectableProperty
12523     public final boolean isFocusableInTouchMode() {
12524         return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
12525     }
12526 
12527     /**
12528      * Returns whether the view should be treated as a focusable unit by screen reader
12529      * accessibility tools.
12530      * @see #setScreenReaderFocusable(boolean)
12531      *
12532      * @return Whether the view should be treated as a focusable unit by screen reader.
12533      *
12534      * @attr ref android.R.styleable#View_screenReaderFocusable
12535      */
12536     @InspectableProperty
12537     public boolean isScreenReaderFocusable() {
12538         return (mPrivateFlags3 & PFLAG3_SCREEN_READER_FOCUSABLE) != 0;
12539     }
12540 
12541     /**
12542      * Sets whether this View should be a focusable element for screen readers
12543      * and include non-focusable Views from its subtree when providing feedback.
12544      * <p>
12545      * Note: this is similar to using <a href="#attr_android:focusable">{@code android:focusable},
12546      * but does not impact input focus behavior.
12547      *
12548      * @param screenReaderFocusable Whether the view should be treated as a unit by screen reader
12549      *                              accessibility tools.
12550      *
12551      * @attr ref android.R.styleable#View_screenReaderFocusable
12552      */
12553     public void setScreenReaderFocusable(boolean screenReaderFocusable) {
12554         updatePflags3AndNotifyA11yIfChanged(PFLAG3_SCREEN_READER_FOCUSABLE, screenReaderFocusable);
12555     }
12556 
12557     /**
12558      * Gets whether this view is a heading for accessibility purposes.
12559      *
12560      * @return {@code true} if the view is a heading, {@code false} otherwise.
12561      *
12562      * @attr ref android.R.styleable#View_accessibilityHeading
12563      */
12564     @InspectableProperty
12565     public boolean isAccessibilityHeading() {
12566         return (mPrivateFlags3 & PFLAG3_ACCESSIBILITY_HEADING) != 0;
12567     }
12568 
12569     /**
12570      * Set if view is a heading for a section of content for accessibility purposes.
12571      *
12572      * @param isHeading {@code true} if the view is a heading, {@code false} otherwise.
12573      *
12574      * @attr ref android.R.styleable#View_accessibilityHeading
12575      */
12576     public void setAccessibilityHeading(boolean isHeading) {
12577         updatePflags3AndNotifyA11yIfChanged(PFLAG3_ACCESSIBILITY_HEADING, isHeading);
12578     }
12579 
12580     private void updatePflags3AndNotifyA11yIfChanged(int mask, boolean newValue) {
12581         int pflags3 = mPrivateFlags3;
12582         if (newValue) {
12583             pflags3 |= mask;
12584         } else {
12585             pflags3 &= ~mask;
12586         }
12587 
12588         if (pflags3 != mPrivateFlags3) {
12589             mPrivateFlags3 = pflags3;
12590             notifyViewAccessibilityStateChangedIfNeeded(
12591                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
12592         }
12593     }
12594 
12595     /**
12596      * Find the nearest view in the specified direction that can take focus.
12597      * This does not actually give focus to that view.
12598      *
12599      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
12600      *
12601      * @return The nearest focusable in the specified direction, or null if none
12602      *         can be found.
12603      */
12604     public View focusSearch(@FocusRealDirection int direction) {
12605         if (mParent != null) {
12606             return mParent.focusSearch(this, direction);
12607         } else {
12608             return null;
12609         }
12610     }
12611 
12612     /**
12613      * Returns whether this View is a root of a keyboard navigation cluster.
12614      *
12615      * @return True if this view is a root of a cluster, or false otherwise.
12616      * @attr ref android.R.styleable#View_keyboardNavigationCluster
12617      */
12618     @ViewDebug.ExportedProperty(category = "focus")
12619     @InspectableProperty
12620     public final boolean isKeyboardNavigationCluster() {
12621         return (mPrivateFlags3 & PFLAG3_CLUSTER) != 0;
12622     }
12623 
12624     /**
12625      * Searches up the view hierarchy to find the top-most cluster. All deeper/nested clusters
12626      * will be ignored.
12627      *
12628      * @return the keyboard navigation cluster that this view is in (can be this view)
12629      *         or {@code null} if not in one
12630      */
12631     View findKeyboardNavigationCluster() {
12632         if (mParent instanceof View) {
12633             View cluster = ((View) mParent).findKeyboardNavigationCluster();
12634             if (cluster != null) {
12635                 return cluster;
12636             } else if (isKeyboardNavigationCluster()) {
12637                 return this;
12638             }
12639         }
12640         return null;
12641     }
12642 
12643     /**
12644      * Set whether this view is a root of a keyboard navigation cluster.
12645      *
12646      * @param isCluster If true, this view is a root of a cluster.
12647      *
12648      * @attr ref android.R.styleable#View_keyboardNavigationCluster
12649      */
12650     public void setKeyboardNavigationCluster(boolean isCluster) {
12651         if (isCluster) {
12652             mPrivateFlags3 |= PFLAG3_CLUSTER;
12653         } else {
12654             mPrivateFlags3 &= ~PFLAG3_CLUSTER;
12655         }
12656     }
12657 
12658     /**
12659      * Sets this View as the one which receives focus the next time cluster navigation jumps
12660      * to the cluster containing this View. This does NOT change focus even if the cluster
12661      * containing this view is current.
12662      *
12663      * @hide
12664      */
12665     @TestApi
12666     public final void setFocusedInCluster() {
12667         setFocusedInCluster(findKeyboardNavigationCluster());
12668     }
12669 
12670     private void setFocusedInCluster(View cluster) {
12671         if (this instanceof ViewGroup) {
12672             ((ViewGroup) this).mFocusedInCluster = null;
12673         }
12674         if (cluster == this) {
12675             return;
12676         }
12677         ViewParent parent = mParent;
12678         View child = this;
12679         while (parent instanceof ViewGroup) {
12680             ((ViewGroup) parent).mFocusedInCluster = child;
12681             if (parent == cluster) {
12682                 break;
12683             }
12684             child = (View) parent;
12685             parent = parent.getParent();
12686         }
12687     }
12688 
12689     private void updateFocusedInCluster(View oldFocus, @FocusDirection int direction) {
12690         if (oldFocus != null) {
12691             View oldCluster = oldFocus.findKeyboardNavigationCluster();
12692             View cluster = findKeyboardNavigationCluster();
12693             if (oldCluster != cluster) {
12694                 // Going from one cluster to another, so save last-focused.
12695                 // This covers cluster jumps because they are always FOCUS_DOWN
12696                 oldFocus.setFocusedInCluster(oldCluster);
12697                 if (!(oldFocus.mParent instanceof ViewGroup)) {
12698                     return;
12699                 }
12700                 if (direction == FOCUS_FORWARD || direction == FOCUS_BACKWARD) {
12701                     // This is a result of ordered navigation so consider navigation through
12702                     // the previous cluster "complete" and clear its last-focused memory.
12703                     ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
12704                 } else if (oldFocus instanceof ViewGroup
12705                         && ((ViewGroup) oldFocus).getDescendantFocusability()
12706                                 == ViewGroup.FOCUS_AFTER_DESCENDANTS
12707                         && ViewRootImpl.isViewDescendantOf(this, oldFocus)) {
12708                     // This means oldFocus is not focusable since it obviously has a focusable
12709                     // child (this). Don't restore focus to it in the future.
12710                     ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
12711                 }
12712             }
12713         }
12714     }
12715 
12716     /**
12717      * Returns whether this View should receive focus when the focus is restored for the view
12718      * hierarchy containing this view.
12719      * <p>
12720      * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
12721      * window or serves as a target of cluster navigation.
12722      *
12723      * @see #restoreDefaultFocus()
12724      *
12725      * @return {@code true} if this view is the default-focus view, {@code false} otherwise
12726      * @attr ref android.R.styleable#View_focusedByDefault
12727      */
12728     @ViewDebug.ExportedProperty(category = "focus")
12729     @InspectableProperty
12730     public final boolean isFocusedByDefault() {
12731         return (mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0;
12732     }
12733 
12734     /**
12735      * Sets whether this View should receive focus when the focus is restored for the view
12736      * hierarchy containing this view.
12737      * <p>
12738      * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
12739      * window or serves as a target of cluster navigation.
12740      *
12741      * @param isFocusedByDefault {@code true} to set this view as the default-focus view,
12742      *                           {@code false} otherwise.
12743      *
12744      * @see #restoreDefaultFocus()
12745      *
12746      * @attr ref android.R.styleable#View_focusedByDefault
12747      */
12748     public void setFocusedByDefault(boolean isFocusedByDefault) {
12749         if (isFocusedByDefault == ((mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0)) {
12750             return;
12751         }
12752 
12753         if (isFocusedByDefault) {
12754             mPrivateFlags3 |= PFLAG3_FOCUSED_BY_DEFAULT;
12755         } else {
12756             mPrivateFlags3 &= ~PFLAG3_FOCUSED_BY_DEFAULT;
12757         }
12758 
12759         if (mParent instanceof ViewGroup) {
12760             if (isFocusedByDefault) {
12761                 ((ViewGroup) mParent).setDefaultFocus(this);
12762             } else {
12763                 ((ViewGroup) mParent).clearDefaultFocus(this);
12764             }
12765         }
12766     }
12767 
12768     /**
12769      * Returns whether the view hierarchy with this view as a root contain a default-focus view.
12770      *
12771      * @return {@code true} if this view has default focus, {@code false} otherwise
12772      */
12773     boolean hasDefaultFocus() {
12774         return isFocusedByDefault();
12775     }
12776 
12777     /**
12778      * Find the nearest keyboard navigation cluster in the specified direction.
12779      * This does not actually give focus to that cluster.
12780      *
12781      * @param currentCluster The starting point of the search. Null means the current cluster is not
12782      *                       found yet
12783      * @param direction Direction to look
12784      *
12785      * @return The nearest keyboard navigation cluster in the specified direction, or null if none
12786      *         can be found
12787      */
12788     public View keyboardNavigationClusterSearch(View currentCluster,
12789             @FocusDirection int direction) {
12790         if (isKeyboardNavigationCluster()) {
12791             currentCluster = this;
12792         }
12793         if (isRootNamespace()) {
12794             // Root namespace means we should consider ourselves the top of the
12795             // tree for group searching; otherwise we could be group searching
12796             // into other tabs.  see LocalActivityManager and TabHost for more info.
12797             return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
12798                     this, currentCluster, direction);
12799         } else if (mParent != null) {
12800             return mParent.keyboardNavigationClusterSearch(currentCluster, direction);
12801         }
12802         return null;
12803     }
12804 
12805     /**
12806      * This method is the last chance for the focused view and its ancestors to
12807      * respond to an arrow key. This is called when the focused view did not
12808      * consume the key internally, nor could the view system find a new view in
12809      * the requested direction to give focus to.
12810      *
12811      * @param focused The currently focused view.
12812      * @param direction The direction focus wants to move. One of FOCUS_UP,
12813      *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
12814      * @return True if the this view consumed this unhandled move.
12815      */
12816     public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
12817         return false;
12818     }
12819 
12820     /**
12821      * Sets whether this View should use a default focus highlight when it gets focused but doesn't
12822      * have {@link android.R.attr#state_focused} defined in its background.
12823      *
12824      * @param defaultFocusHighlightEnabled {@code true} to set this view to use a default focus
12825      *                                      highlight, {@code false} otherwise.
12826      *
12827      * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
12828      */
12829     public void setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled) {
12830         mDefaultFocusHighlightEnabled = defaultFocusHighlightEnabled;
12831     }
12832 
12833     /**
12834 
12835     /**
12836      * Returns whether this View should use a default focus highlight when it gets focused but
12837      * doesn't have {@link android.R.attr#state_focused} defined in its background.
12838      *
12839      * @return True if this View should use a default focus highlight.
12840      * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
12841      */
12842     @ViewDebug.ExportedProperty(category = "focus")
12843     @InspectableProperty
12844     public final boolean getDefaultFocusHighlightEnabled() {
12845         return mDefaultFocusHighlightEnabled;
12846     }
12847 
12848     /**
12849      * If a user manually specified the next view id for a particular direction,
12850      * use the root to look up the view.
12851      * @param root The root view of the hierarchy containing this view.
12852      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
12853      * or FOCUS_BACKWARD.
12854      * @return The user specified next view, or null if there is none.
12855      */
12856     View findUserSetNextFocus(View root, @FocusDirection int direction) {
12857         switch (direction) {
12858             case FOCUS_LEFT:
12859                 if (mNextFocusLeftId == View.NO_ID) return null;
12860                 return findViewInsideOutShouldExist(root, mNextFocusLeftId);
12861             case FOCUS_RIGHT:
12862                 if (mNextFocusRightId == View.NO_ID) return null;
12863                 return findViewInsideOutShouldExist(root, mNextFocusRightId);
12864             case FOCUS_UP:
12865                 if (mNextFocusUpId == View.NO_ID) return null;
12866                 return findViewInsideOutShouldExist(root, mNextFocusUpId);
12867             case FOCUS_DOWN:
12868                 if (mNextFocusDownId == View.NO_ID) return null;
12869                 return findViewInsideOutShouldExist(root, mNextFocusDownId);
12870             case FOCUS_FORWARD:
12871                 if (mNextFocusForwardId == View.NO_ID) return null;
12872                 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
12873             case FOCUS_BACKWARD: {
12874                 if (mID == View.NO_ID) return null;
12875                 final View rootView = root;
12876                 final View startView = this;
12877                 // Since we have forward links but no backward links, we need to find the view that
12878                 // forward links to this view. We can't just find the view with the specified ID
12879                 // because view IDs need not be unique throughout the tree.
12880                 return root.findViewByPredicateInsideOut(startView,
12881                     t -> findViewInsideOutShouldExist(rootView, t, t.mNextFocusForwardId)
12882                             == startView);
12883             }
12884         }
12885         return null;
12886     }
12887 
12888     /**
12889      * If a user manually specified the next keyboard-navigation cluster for a particular direction,
12890      * use the root to look up the view.
12891      *
12892      * @param root the root view of the hierarchy containing this view
12893      * @param direction {@link #FOCUS_FORWARD} or {@link #FOCUS_BACKWARD}
12894      * @return the user-specified next cluster, or {@code null} if there is none
12895      */
12896     View findUserSetNextKeyboardNavigationCluster(View root, @FocusDirection int direction) {
12897         switch (direction) {
12898             case FOCUS_FORWARD:
12899                 if (mNextClusterForwardId == View.NO_ID) return null;
12900                 return findViewInsideOutShouldExist(root, mNextClusterForwardId);
12901             case FOCUS_BACKWARD: {
12902                 if (mID == View.NO_ID) return null;
12903                 final int id = mID;
12904                 return root.findViewByPredicateInsideOut(this,
12905                         (Predicate<View>) t -> t.mNextClusterForwardId == id);
12906             }
12907         }
12908         return null;
12909     }
12910 
12911     private View findViewInsideOutShouldExist(View root, int id) {
12912         return findViewInsideOutShouldExist(root, this, id);
12913     }
12914 
12915     private View findViewInsideOutShouldExist(View root, View start, int id) {
12916         if (mMatchIdPredicate == null) {
12917             mMatchIdPredicate = new MatchIdPredicate();
12918         }
12919         mMatchIdPredicate.mId = id;
12920         View result = root.findViewByPredicateInsideOut(start, mMatchIdPredicate);
12921         if (result == null) {
12922             Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
12923         }
12924         return result;
12925     }
12926 
12927     /**
12928      * Find and return all focusable views that are descendants of this view,
12929      * possibly including this view if it is focusable itself.
12930      *
12931      * @param direction The direction of the focus
12932      * @return A list of focusable views
12933      */
12934     public ArrayList<View> getFocusables(@FocusDirection int direction) {
12935         ArrayList<View> result = new ArrayList<View>(24);
12936         addFocusables(result, direction);
12937         return result;
12938     }
12939 
12940     /**
12941      * Add any focusable views that are descendants of this view (possibly
12942      * including this view if it is focusable itself) to views.  If we are in touch mode,
12943      * only add views that are also focusable in touch mode.
12944      *
12945      * @param views Focusable views found so far
12946      * @param direction The direction of the focus
12947      */
12948     public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
12949         addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
12950     }
12951 
12952     /**
12953      * Adds any focusable views that are descendants of this view (possibly
12954      * including this view if it is focusable itself) to views. This method
12955      * adds all focusable views regardless if we are in touch mode or
12956      * only views focusable in touch mode if we are in touch mode or
12957      * only views that can take accessibility focus if accessibility is enabled
12958      * depending on the focusable mode parameter.
12959      *
12960      * @param views Focusable views found so far or null if all we are interested is
12961      *        the number of focusables.
12962      * @param direction The direction of the focus.
12963      * @param focusableMode The type of focusables to be added.
12964      *
12965      * @see #FOCUSABLES_ALL
12966      * @see #FOCUSABLES_TOUCH_MODE
12967      */
12968     public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
12969             @FocusableMode int focusableMode) {
12970         if (views == null) {
12971             return;
12972         }
12973         if (!canTakeFocus()) {
12974             return;
12975         }
12976         if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
12977                 && !isFocusableInTouchMode()) {
12978             return;
12979         }
12980         views.add(this);
12981     }
12982 
12983     /**
12984      * Adds any keyboard navigation cluster roots that are descendants of this view (possibly
12985      * including this view if it is a cluster root itself) to views.
12986      *
12987      * @param views Keyboard navigation cluster roots found so far
12988      * @param direction Direction to look
12989      */
12990     public void addKeyboardNavigationClusters(
12991             @NonNull Collection<View> views,
12992             int direction) {
12993         if (!isKeyboardNavigationCluster()) {
12994             return;
12995         }
12996         if (!hasFocusable()) {
12997             return;
12998         }
12999         views.add(this);
13000     }
13001 
13002     /**
13003      * Finds the Views that contain given text. The containment is case insensitive.
13004      * The search is performed by either the text that the View renders or the content
13005      * description that describes the view for accessibility purposes and the view does
13006      * not render or both. Clients can specify how the search is to be performed via
13007      * passing the {@link #FIND_VIEWS_WITH_TEXT} and
13008      * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
13009      *
13010      * @param outViews The output list of matching Views.
13011      * @param searched The text to match against.
13012      *
13013      * @see #FIND_VIEWS_WITH_TEXT
13014      * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
13015      * @see #setContentDescription(CharSequence)
13016      */
13017     public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
13018             @FindViewFlags int flags) {
13019         if (getAccessibilityNodeProvider() != null) {
13020             if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
13021                 outViews.add(this);
13022             }
13023         } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
13024                 && (searched != null && searched.length() > 0)
13025                 && (mContentDescription != null && mContentDescription.length() > 0)) {
13026             String searchedLowerCase = searched.toString().toLowerCase();
13027             String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
13028             if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
13029                 outViews.add(this);
13030             }
13031         }
13032     }
13033 
13034     /**
13035      * Find and return all touchable views that are descendants of this view,
13036      * possibly including this view if it is touchable itself.
13037      *
13038      * @return A list of touchable views
13039      */
13040     public ArrayList<View> getTouchables() {
13041         ArrayList<View> result = new ArrayList<View>();
13042         addTouchables(result);
13043         return result;
13044     }
13045 
13046     /**
13047      * Add any touchable views that are descendants of this view (possibly
13048      * including this view if it is touchable itself) to views.
13049      *
13050      * @param views Touchable views found so far
13051      */
13052     public void addTouchables(ArrayList<View> views) {
13053         final int viewFlags = mViewFlags;
13054 
13055         if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
13056                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
13057                 && (viewFlags & ENABLED_MASK) == ENABLED) {
13058             views.add(this);
13059         }
13060     }
13061 
13062     /**
13063      * Returns whether this View is accessibility focused.
13064      *
13065      * @return True if this View is accessibility focused.
13066      */
13067     @InspectableProperty(hasAttributeId = false)
13068     public boolean isAccessibilityFocused() {
13069         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
13070     }
13071 
13072     /**
13073      * Call this to try to give accessibility focus to this view.
13074      *
13075      * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
13076      * returns false or the view is no visible or the view already has accessibility
13077      * focus.
13078      *
13079      * See also {@link #focusSearch(int)}, which is what you call to say that you
13080      * have focus, and you want your parent to look for the next one.
13081      *
13082      * @return Whether this view actually took accessibility focus.
13083      *
13084      * @hide
13085      */
13086     @UnsupportedAppUsage
13087     public boolean requestAccessibilityFocus() {
13088         AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
13089         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
13090             return false;
13091         }
13092         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
13093             return false;
13094         }
13095         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
13096             mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
13097             ViewRootImpl viewRootImpl = getViewRootImpl();
13098             if (viewRootImpl != null) {
13099                 viewRootImpl.setAccessibilityFocus(this, null);
13100             }
13101             invalidate();
13102             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
13103             return true;
13104         }
13105         return false;
13106     }
13107 
13108     /**
13109      * Call this to try to clear accessibility focus of this view.
13110      *
13111      * See also {@link #focusSearch(int)}, which is what you call to say that you
13112      * have focus, and you want your parent to look for the next one.
13113      *
13114      * @hide
13115      */
13116     @UnsupportedAppUsage
13117     public void clearAccessibilityFocus() {
13118         clearAccessibilityFocusNoCallbacks(0);
13119 
13120         // Clear the global reference of accessibility focus if this view or
13121         // any of its descendants had accessibility focus. This will NOT send
13122         // an event or update internal state if focus is cleared from a
13123         // descendant view, which may leave views in inconsistent states.
13124         final ViewRootImpl viewRootImpl = getViewRootImpl();
13125         if (viewRootImpl != null) {
13126             final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
13127             if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
13128                 viewRootImpl.setAccessibilityFocus(null, null);
13129             }
13130         }
13131     }
13132 
13133     private void sendAccessibilityHoverEvent(int eventType) {
13134         // Since we are not delivering to a client accessibility events from not
13135         // important views (unless the clinet request that) we need to fire the
13136         // event from the deepest view exposed to the client. As a consequence if
13137         // the user crosses a not exposed view the client will see enter and exit
13138         // of the exposed predecessor followed by and enter and exit of that same
13139         // predecessor when entering and exiting the not exposed descendant. This
13140         // is fine since the client has a clear idea which view is hovered at the
13141         // price of a couple more events being sent. This is a simple and
13142         // working solution.
13143         View source = this;
13144         while (true) {
13145             if (source.includeForAccessibility()) {
13146                 source.sendAccessibilityEvent(eventType);
13147                 return;
13148             }
13149             ViewParent parent = source.getParent();
13150             if (parent instanceof View) {
13151                 source = (View) parent;
13152             } else {
13153                 return;
13154             }
13155         }
13156     }
13157 
13158     /**
13159      * Clears accessibility focus without calling any callback methods
13160      * normally invoked in {@link #clearAccessibilityFocus()}. This method
13161      * is used separately from that one for clearing accessibility focus when
13162      * giving this focus to another view.
13163      *
13164      * @param action The action, if any, that led to focus being cleared. Set to
13165      * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
13166      * the window.
13167      */
13168     void clearAccessibilityFocusNoCallbacks(int action) {
13169         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
13170             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
13171             invalidate();
13172             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
13173                 AccessibilityEvent event = AccessibilityEvent.obtain(
13174                         AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
13175                 event.setAction(action);
13176                 if (mAccessibilityDelegate != null) {
13177                     mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
13178                 } else {
13179                     sendAccessibilityEventUnchecked(event);
13180                 }
13181             }
13182         }
13183     }
13184 
13185     /**
13186      * Call this to try to give focus to a specific view or to one of its
13187      * descendants.
13188      *
13189      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
13190      * false), or if it can't be focused due to other conditions (not focusable in touch mode
13191      * ({@link #isFocusableInTouchMode}) while the device is in touch mode, not visible, not
13192      * enabled, or has no size).
13193      *
13194      * See also {@link #focusSearch(int)}, which is what you call to say that you
13195      * have focus, and you want your parent to look for the next one.
13196      *
13197      * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
13198      * {@link #FOCUS_DOWN} and <code>null</code>.
13199      *
13200      * @return Whether this view or one of its descendants actually took focus.
13201      */
13202     public final boolean requestFocus() {
13203         return requestFocus(View.FOCUS_DOWN);
13204     }
13205 
13206     /**
13207      * This will request focus for whichever View was last focused within this
13208      * cluster before a focus-jump out of it.
13209      *
13210      * @hide
13211      */
13212     @TestApi
13213     public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
13214         // Prioritize focusableByDefault over algorithmic focus selection.
13215         if (restoreDefaultFocus()) {
13216             return true;
13217         }
13218         return requestFocus(direction);
13219     }
13220 
13221     /**
13222      * This will request focus for whichever View not in a cluster was last focused before a
13223      * focus-jump to a cluster. If no non-cluster View has previously had focus, this will focus
13224      * the "first" focusable view it finds.
13225      *
13226      * @hide
13227      */
13228     @TestApi
13229     public boolean restoreFocusNotInCluster() {
13230         return requestFocus(View.FOCUS_DOWN);
13231     }
13232 
13233     /**
13234      * Gives focus to the default-focus view in the view hierarchy that has this view as a root.
13235      * If the default-focus view cannot be found, falls back to calling {@link #requestFocus(int)}.
13236      *
13237      * @return Whether this view or one of its descendants actually took focus
13238      */
13239     public boolean restoreDefaultFocus() {
13240         return requestFocus(View.FOCUS_DOWN);
13241     }
13242 
13243     /**
13244      * Call this to try to give focus to a specific view or to one of its
13245      * descendants and give it a hint about what direction focus is heading.
13246      *
13247      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
13248      * false), or if it is focusable and it is not focusable in touch mode
13249      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
13250      *
13251      * See also {@link #focusSearch(int)}, which is what you call to say that you
13252      * have focus, and you want your parent to look for the next one.
13253      *
13254      * This is equivalent to calling {@link #requestFocus(int, Rect)} with
13255      * <code>null</code> set for the previously focused rectangle.
13256      *
13257      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
13258      * @return Whether this view or one of its descendants actually took focus.
13259      */
13260     public final boolean requestFocus(int direction) {
13261         return requestFocus(direction, null);
13262     }
13263 
13264     /**
13265      * Call this to try to give focus to a specific view or to one of its descendants
13266      * and give it hints about the direction and a specific rectangle that the focus
13267      * is coming from.  The rectangle can help give larger views a finer grained hint
13268      * about where focus is coming from, and therefore, where to show selection, or
13269      * forward focus change internally.
13270      *
13271      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
13272      * false), or if it is focusable and it is not focusable in touch mode
13273      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
13274      *
13275      * A View will not take focus if it is not visible.
13276      *
13277      * A View will not take focus if one of its parents has
13278      * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
13279      * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
13280      *
13281      * See also {@link #focusSearch(int)}, which is what you call to say that you
13282      * have focus, and you want your parent to look for the next one.
13283      *
13284      * You may wish to override this method if your custom {@link View} has an internal
13285      * {@link View} that it wishes to forward the request to.
13286      *
13287      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
13288      * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
13289      *        to give a finer grained hint about where focus is coming from.  May be null
13290      *        if there is no hint.
13291      * @return Whether this view or one of its descendants actually took focus.
13292      */
13293     public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
13294         return requestFocusNoSearch(direction, previouslyFocusedRect);
13295     }
13296 
13297     private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
13298         // need to be focusable
13299         if (!canTakeFocus()) {
13300             return false;
13301         }
13302 
13303         // need to be focusable in touch mode if in touch mode
13304         if (isInTouchMode() &&
13305             (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
13306                return false;
13307         }
13308 
13309         // need to not have any parents blocking us
13310         if (hasAncestorThatBlocksDescendantFocus()) {
13311             return false;
13312         }
13313 
13314         if (!isLayoutValid()) {
13315             mPrivateFlags |= PFLAG_WANTS_FOCUS;
13316         } else {
13317             clearParentsWantFocus();
13318         }
13319 
13320         handleFocusGainInternal(direction, previouslyFocusedRect);
13321         return true;
13322     }
13323 
13324     void clearParentsWantFocus() {
13325         if (mParent instanceof View) {
13326             ((View) mParent).mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
13327             ((View) mParent).clearParentsWantFocus();
13328         }
13329     }
13330 
13331     /**
13332      * Call this to try to give focus to a specific view or to one of its descendants. This is a
13333      * special variant of {@link #requestFocus() } that will allow views that are not focusable in
13334      * touch mode to request focus when they are touched.
13335      *
13336      * @return Whether this view or one of its descendants actually took focus.
13337      *
13338      * @see #isInTouchMode()
13339      *
13340      */
13341     public final boolean requestFocusFromTouch() {
13342         // Leave touch mode if we need to
13343         if (isInTouchMode()) {
13344             ViewRootImpl viewRoot = getViewRootImpl();
13345             if (viewRoot != null) {
13346                 viewRoot.ensureTouchMode(false);
13347             }
13348         }
13349         return requestFocus(View.FOCUS_DOWN);
13350     }
13351 
13352     /**
13353      * @return Whether any ancestor of this view blocks descendant focus.
13354      */
13355     private boolean hasAncestorThatBlocksDescendantFocus() {
13356         final boolean focusableInTouchMode = isFocusableInTouchMode();
13357         ViewParent ancestor = mParent;
13358         while (ancestor instanceof ViewGroup) {
13359             final ViewGroup vgAncestor = (ViewGroup) ancestor;
13360             if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
13361                     || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
13362                 return true;
13363             } else {
13364                 ancestor = vgAncestor.getParent();
13365             }
13366         }
13367         return false;
13368     }
13369 
13370     /**
13371      * Gets the mode for determining whether this View is important for accessibility.
13372      * A view is important for accessibility if it fires accessibility events and if it
13373      * is reported to accessibility services that query the screen.
13374      *
13375      * @return The mode for determining whether a view is important for accessibility, one
13376      * of {@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, {@link #IMPORTANT_FOR_ACCESSIBILITY_YES},
13377      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO}, or
13378      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}.
13379      *
13380      * @attr ref android.R.styleable#View_importantForAccessibility
13381      *
13382      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
13383      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
13384      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
13385      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
13386      */
13387     @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
13388             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
13389             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
13390             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
13391             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
13392                     to = "noHideDescendants")
13393         })
13394     @InspectableProperty(enumMapping = {
13395             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_AUTO, name = "auto"),
13396             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_YES, name = "yes"),
13397             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_NO, name = "no"),
13398             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
13399                     name = "noHideDescendants"),
13400     })
13401     public int getImportantForAccessibility() {
13402         return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
13403                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
13404     }
13405 
13406     /**
13407      * Sets the live region mode for this view. This indicates to accessibility
13408      * services whether they should automatically notify the user about changes
13409      * to the view's content description or text, or to the content descriptions
13410      * or text of the view's children (where applicable).
13411      * <p>
13412      * For example, in a login screen with a TextView that displays an "incorrect
13413      * password" notification, that view should be marked as a live region with
13414      * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
13415      * <p>
13416      * To disable change notifications for this view, use
13417      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
13418      * mode for most views.
13419      * <p>
13420      * To indicate that the user should be notified of changes, use
13421      * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
13422      * <p>
13423      * If the view's changes should interrupt ongoing speech and notify the user
13424      * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
13425      *
13426      * @param mode The live region mode for this view, one of:
13427      *        <ul>
13428      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
13429      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
13430      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
13431      *        </ul>
13432      * @attr ref android.R.styleable#View_accessibilityLiveRegion
13433      */
13434     public void setAccessibilityLiveRegion(int mode) {
13435         if (mode != getAccessibilityLiveRegion()) {
13436             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
13437             mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
13438                     & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
13439             notifyViewAccessibilityStateChangedIfNeeded(
13440                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
13441         }
13442     }
13443 
13444     /**
13445      * Gets the live region mode for this View.
13446      *
13447      * @return The live region mode for the view.
13448      *
13449      * @attr ref android.R.styleable#View_accessibilityLiveRegion
13450      *
13451      * @see #setAccessibilityLiveRegion(int)
13452      */
13453     @InspectableProperty(enumMapping = {
13454             @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_NONE, name = "none"),
13455             @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_POLITE, name = "polite"),
13456             @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_ASSERTIVE, name = "assertive")
13457     })
13458     public int getAccessibilityLiveRegion() {
13459         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
13460                 >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
13461     }
13462 
13463     /**
13464      * Sets how to determine whether this view is important for accessibility
13465      * which is if it fires accessibility events and if it is reported to
13466      * accessibility services that query the screen.
13467      *
13468      * @param mode How to determine whether this view is important for accessibility.
13469      *
13470      * @attr ref android.R.styleable#View_importantForAccessibility
13471      *
13472      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
13473      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
13474      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
13475      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
13476      */
13477     public void setImportantForAccessibility(int mode) {
13478         final int oldMode = getImportantForAccessibility();
13479         if (mode != oldMode) {
13480             final boolean hideDescendants =
13481                     mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
13482 
13483             // If this node or its descendants are no longer important, try to
13484             // clear accessibility focus.
13485             if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
13486                 final View focusHost = findAccessibilityFocusHost(hideDescendants);
13487                 if (focusHost != null) {
13488                     focusHost.clearAccessibilityFocus();
13489                 }
13490             }
13491 
13492             // If we're moving between AUTO and another state, we might not need
13493             // to send a subtree changed notification. We'll store the computed
13494             // importance, since we'll need to check it later to make sure.
13495             final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
13496                     || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
13497             final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
13498             mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
13499             mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
13500                     & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
13501             if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
13502                 notifySubtreeAccessibilityStateChangedIfNeeded();
13503             } else {
13504                 notifyViewAccessibilityStateChangedIfNeeded(
13505                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
13506             }
13507         }
13508     }
13509 
13510     /**
13511      * Returns the view within this view's hierarchy that is hosting
13512      * accessibility focus.
13513      *
13514      * @param searchDescendants whether to search for focus in descendant views
13515      * @return the view hosting accessibility focus, or {@code null}
13516      */
13517     private View findAccessibilityFocusHost(boolean searchDescendants) {
13518         if (isAccessibilityFocusedViewOrHost()) {
13519             return this;
13520         }
13521 
13522         if (searchDescendants) {
13523             final ViewRootImpl viewRoot = getViewRootImpl();
13524             if (viewRoot != null) {
13525                 final View focusHost = viewRoot.getAccessibilityFocusedHost();
13526                 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
13527                     return focusHost;
13528                 }
13529             }
13530         }
13531 
13532         return null;
13533     }
13534 
13535     /**
13536      * Computes whether this view should be exposed for accessibility. In
13537      * general, views that are interactive or provide information are exposed
13538      * while views that serve only as containers are hidden.
13539      * <p>
13540      * If an ancestor of this view has importance
13541      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
13542      * returns <code>false</code>.
13543      * <p>
13544      * Otherwise, the value is computed according to the view's
13545      * {@link #getImportantForAccessibility()} value:
13546      * <ol>
13547      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
13548      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
13549      * </code>
13550      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
13551      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
13552      * view satisfies any of the following:
13553      * <ul>
13554      * <li>Is actionable, e.g. {@link #isClickable()},
13555      * {@link #isLongClickable()}, or {@link #isFocusable()}
13556      * <li>Has an {@link AccessibilityDelegate}
13557      * <li>Has an interaction listener, e.g. {@link OnTouchListener},
13558      * {@link OnKeyListener}, etc.
13559      * <li>Is an accessibility live region, e.g.
13560      * {@link #getAccessibilityLiveRegion()} is not
13561      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
13562      * </ul>
13563      * <li>Has an accessibility pane title, see {@link #setAccessibilityPaneTitle}</li>
13564      * </ol>
13565      *
13566      * @return Whether the view is exposed for accessibility.
13567      * @see #setImportantForAccessibility(int)
13568      * @see #getImportantForAccessibility()
13569      */
13570     public boolean isImportantForAccessibility() {
13571         final int mode = getImportantForAccessibility();
13572         if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
13573                 || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
13574             return false;
13575         }
13576 
13577         // Check parent mode to ensure we're not hidden.
13578         ViewParent parent = mParent;
13579         while (parent instanceof View) {
13580             if (((View) parent).getImportantForAccessibility()
13581                     == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
13582                 return false;
13583             }
13584             parent = parent.getParent();
13585         }
13586 
13587         return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
13588                 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
13589                 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE
13590                 || isAccessibilityPane();
13591     }
13592 
13593     /**
13594      * Gets the parent for accessibility purposes. Note that the parent for
13595      * accessibility is not necessary the immediate parent. It is the first
13596      * predecessor that is important for accessibility.
13597      *
13598      * @return The parent for accessibility purposes.
13599      */
13600     public ViewParent getParentForAccessibility() {
13601         if (mParent instanceof View) {
13602             View parentView = (View) mParent;
13603             if (parentView.includeForAccessibility()) {
13604                 return mParent;
13605             } else {
13606                 return mParent.getParentForAccessibility();
13607             }
13608         }
13609         return null;
13610     }
13611 
13612     /** @hide */
13613     View getSelfOrParentImportantForA11y() {
13614         if (isImportantForAccessibility()) return this;
13615         ViewParent parent = getParentForAccessibility();
13616         if (parent instanceof View) return (View) parent;
13617         return null;
13618     }
13619 
13620     /**
13621      * Adds the children of this View relevant for accessibility to the given list
13622      * as output. Since some Views are not important for accessibility the added
13623      * child views are not necessarily direct children of this view, rather they are
13624      * the first level of descendants important for accessibility.
13625      *
13626      * @param outChildren The output list that will receive children for accessibility.
13627      */
13628     public void addChildrenForAccessibility(ArrayList<View> outChildren) {
13629 
13630     }
13631 
13632     /**
13633      * Whether to regard this view for accessibility. A view is regarded for
13634      * accessibility if it is important for accessibility or the querying
13635      * accessibility service has explicitly requested that view not
13636      * important for accessibility are regarded.
13637      *
13638      * @return Whether to regard the view for accessibility.
13639      *
13640      * @hide
13641      */
13642     @UnsupportedAppUsage
13643     public boolean includeForAccessibility() {
13644         if (mAttachInfo != null) {
13645             return (mAttachInfo.mAccessibilityFetchFlags
13646                     & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
13647                     || isImportantForAccessibility();
13648         }
13649         return false;
13650     }
13651 
13652     /**
13653      * Returns whether the View is considered actionable from
13654      * accessibility perspective. Such view are important for
13655      * accessibility.
13656      *
13657      * @return True if the view is actionable for accessibility.
13658      *
13659      * @hide
13660      */
13661     public boolean isActionableForAccessibility() {
13662         return (isClickable() || isLongClickable() || isFocusable());
13663     }
13664 
13665     /**
13666      * Returns whether the View has registered callbacks which makes it
13667      * important for accessibility.
13668      *
13669      * @return True if the view is actionable for accessibility.
13670      */
13671     private boolean hasListenersForAccessibility() {
13672         ListenerInfo info = getListenerInfo();
13673         return mTouchDelegate != null || info.mOnKeyListener != null
13674                 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
13675                 || info.mOnHoverListener != null || info.mOnDragListener != null;
13676     }
13677 
13678     /**
13679      * Notifies that the accessibility state of this view changed. The change
13680      * is local to this view and does not represent structural changes such
13681      * as children and parent. For example, the view became focusable. The
13682      * notification is at at most once every
13683      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
13684      * to avoid unnecessary load to the system. Also once a view has a pending
13685      * notification this method is a NOP until the notification has been sent.
13686      *
13687      * @hide
13688      */
13689     @UnsupportedAppUsage
13690     public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
13691         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
13692             return;
13693         }
13694 
13695         // Changes to views with a pane title count as window state changes, as the pane title
13696         // marks them as significant parts of the UI.
13697         if ((changeType != AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE)
13698                 && isAccessibilityPane()) {
13699             // If the pane isn't visible, content changed events are sufficient unless we're
13700             // reporting that the view just disappeared
13701             if ((getVisibility() == VISIBLE)
13702                     || (changeType == AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED)) {
13703                 final AccessibilityEvent event = AccessibilityEvent.obtain();
13704                 onInitializeAccessibilityEvent(event);
13705                 event.setEventType(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
13706                 event.setContentChangeTypes(changeType);
13707                 event.setSource(this);
13708                 onPopulateAccessibilityEvent(event);
13709                 if (mParent != null) {
13710                     try {
13711                         mParent.requestSendAccessibilityEvent(this, event);
13712                     } catch (AbstractMethodError e) {
13713                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName()
13714                                 + " does not fully implement ViewParent", e);
13715                     }
13716                 }
13717                 return;
13718             }
13719         }
13720 
13721         // If this is a live region, we should send a subtree change event
13722         // from this view immediately. Otherwise, we can let it propagate up.
13723         if (getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE) {
13724             final AccessibilityEvent event = AccessibilityEvent.obtain();
13725             event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
13726             event.setContentChangeTypes(changeType);
13727             sendAccessibilityEventUnchecked(event);
13728         } else if (mParent != null) {
13729             try {
13730                 mParent.notifySubtreeAccessibilityStateChanged(this, this, changeType);
13731             } catch (AbstractMethodError e) {
13732                 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
13733                         " does not fully implement ViewParent", e);
13734             }
13735         }
13736     }
13737 
13738     /**
13739      * Notifies that the accessibility state of this view changed. The change
13740      * is *not* local to this view and does represent structural changes such
13741      * as children and parent. For example, the view size changed. The
13742      * notification is at at most once every
13743      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
13744      * to avoid unnecessary load to the system. Also once a view has a pending
13745      * notification this method is a NOP until the notification has been sent.
13746      *
13747      * @hide
13748      */
13749     @UnsupportedAppUsage
13750     public void notifySubtreeAccessibilityStateChangedIfNeeded() {
13751         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
13752             return;
13753         }
13754 
13755         if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
13756             mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
13757             if (mParent != null) {
13758                 try {
13759                     mParent.notifySubtreeAccessibilityStateChanged(
13760                             this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
13761                 } catch (AbstractMethodError e) {
13762                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
13763                             " does not fully implement ViewParent", e);
13764                 }
13765             }
13766         }
13767     }
13768 
13769     /**
13770      * Changes the visibility of this View without triggering any other changes. This should only
13771      * be used by animation frameworks, such as {@link android.transition.Transition}, where
13772      * visibility changes should not adjust focus or trigger a new layout. Application developers
13773      * should use {@link #setVisibility} instead to ensure that the hierarchy is correctly updated.
13774      *
13775      * <p>Only call this method when a temporary visibility must be applied during an
13776      * animation and the original visibility value is guaranteed to be reset after the
13777      * animation completes. Use {@link #setVisibility} in all other cases.</p>
13778      *
13779      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
13780      * @see #setVisibility(int)
13781      */
13782     public void setTransitionVisibility(@Visibility int visibility) {
13783         mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
13784     }
13785 
13786     /**
13787      * Reset the flag indicating the accessibility state of the subtree rooted
13788      * at this view changed.
13789      */
13790     void resetSubtreeAccessibilityStateChanged() {
13791         mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
13792     }
13793 
13794     /**
13795      * Report an accessibility action to this view's parents for delegated processing.
13796      *
13797      * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
13798      * call this method to delegate an accessibility action to a supporting parent. If the parent
13799      * returns true from its
13800      * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
13801      * method this method will return true to signify that the action was consumed.</p>
13802      *
13803      * <p>This method is useful for implementing nested scrolling child views. If
13804      * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
13805      * a custom view implementation may invoke this method to allow a parent to consume the
13806      * scroll first. If this method returns true the custom view should skip its own scrolling
13807      * behavior.</p>
13808      *
13809      * @param action Accessibility action to delegate
13810      * @param arguments Optional action arguments
13811      * @return true if the action was consumed by a parent
13812      */
13813     public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
13814         for (ViewParent p = getParent(); p != null; p = p.getParent()) {
13815             if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
13816                 return true;
13817             }
13818         }
13819         return false;
13820     }
13821 
13822     /**
13823      * Performs the specified accessibility action on the view. For
13824      * possible accessibility actions look at {@link AccessibilityNodeInfo}.
13825      * <p>
13826      * If an {@link AccessibilityDelegate} has been specified via calling
13827      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
13828      * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
13829      * is responsible for handling this call.
13830      * </p>
13831      *
13832      * <p>The default implementation will delegate
13833      * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
13834      * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
13835      * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
13836      *
13837      * @param action The action to perform.
13838      * @param arguments Optional action arguments.
13839      * @return Whether the action was performed.
13840      */
13841     public boolean performAccessibilityAction(int action, Bundle arguments) {
13842       if (mAccessibilityDelegate != null) {
13843           return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
13844       } else {
13845           return performAccessibilityActionInternal(action, arguments);
13846       }
13847     }
13848 
13849    /**
13850     * @see #performAccessibilityAction(int, Bundle)
13851     *
13852     * Note: Called from the default {@link AccessibilityDelegate}.
13853     *
13854     * @hide
13855     */
13856     @UnsupportedAppUsage
13857     public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
13858         if (isNestedScrollingEnabled()
13859                 && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
13860                 || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
13861                 || action == R.id.accessibilityActionScrollUp
13862                 || action == R.id.accessibilityActionScrollLeft
13863                 || action == R.id.accessibilityActionScrollDown
13864                 || action == R.id.accessibilityActionScrollRight)) {
13865             if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
13866                 return true;
13867             }
13868         }
13869 
13870         switch (action) {
13871             case AccessibilityNodeInfo.ACTION_CLICK: {
13872                 if (isClickable()) {
13873                     performClickInternal();
13874                     return true;
13875                 }
13876             } break;
13877             case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
13878                 if (isLongClickable()) {
13879                     performLongClick();
13880                     return true;
13881                 }
13882             } break;
13883             case AccessibilityNodeInfo.ACTION_FOCUS: {
13884                 if (!hasFocus()) {
13885                     // Get out of touch mode since accessibility
13886                     // wants to move focus around.
13887                     getViewRootImpl().ensureTouchMode(false);
13888                     return requestFocus();
13889                 }
13890             } break;
13891             case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
13892                 if (hasFocus()) {
13893                     clearFocus();
13894                     return !isFocused();
13895                 }
13896             } break;
13897             case AccessibilityNodeInfo.ACTION_SELECT: {
13898                 if (!isSelected()) {
13899                     setSelected(true);
13900                     return isSelected();
13901                 }
13902             } break;
13903             case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
13904                 if (isSelected()) {
13905                     setSelected(false);
13906                     return !isSelected();
13907                 }
13908             } break;
13909             case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
13910                 if (!isAccessibilityFocused()) {
13911                     return requestAccessibilityFocus();
13912                 }
13913             } break;
13914             case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
13915                 if (isAccessibilityFocused()) {
13916                     clearAccessibilityFocus();
13917                     return true;
13918                 }
13919             } break;
13920             case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
13921                 if (arguments != null) {
13922                     final int granularity = arguments.getInt(
13923                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
13924                     final boolean extendSelection = arguments.getBoolean(
13925                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
13926                     return traverseAtGranularity(granularity, true, extendSelection);
13927                 }
13928             } break;
13929             case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
13930                 if (arguments != null) {
13931                     final int granularity = arguments.getInt(
13932                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
13933                     final boolean extendSelection = arguments.getBoolean(
13934                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
13935                     return traverseAtGranularity(granularity, false, extendSelection);
13936                 }
13937             } break;
13938             case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
13939                 CharSequence text = getIterableTextForAccessibility();
13940                 if (text == null) {
13941                     return false;
13942                 }
13943                 final int start = (arguments != null) ? arguments.getInt(
13944                         AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
13945                 final int end = (arguments != null) ? arguments.getInt(
13946                 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
13947                 // Only cursor position can be specified (selection length == 0)
13948                 if ((getAccessibilitySelectionStart() != start
13949                         || getAccessibilitySelectionEnd() != end)
13950                         && (start == end)) {
13951                     setAccessibilitySelection(start, end);
13952                     notifyViewAccessibilityStateChangedIfNeeded(
13953                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
13954                     return true;
13955                 }
13956             } break;
13957             case R.id.accessibilityActionShowOnScreen: {
13958                 if (mAttachInfo != null) {
13959                     final Rect r = mAttachInfo.mTmpInvalRect;
13960                     getDrawingRect(r);
13961                     return requestRectangleOnScreen(r, true);
13962                 }
13963             } break;
13964             case R.id.accessibilityActionContextClick: {
13965                 if (isContextClickable()) {
13966                     performContextClick();
13967                     return true;
13968                 }
13969             } break;
13970             case R.id.accessibilityActionShowTooltip: {
13971                 if ((mTooltipInfo != null) && (mTooltipInfo.mTooltipPopup != null)) {
13972                     // Tooltip already showing
13973                     return false;
13974                 }
13975                 return showLongClickTooltip(0, 0);
13976             }
13977             case R.id.accessibilityActionHideTooltip: {
13978                 if ((mTooltipInfo == null) || (mTooltipInfo.mTooltipPopup == null)) {
13979                     // No tooltip showing
13980                     return false;
13981                 }
13982                 hideTooltip();
13983                 return true;
13984             }
13985         }
13986         return false;
13987     }
13988 
13989     private boolean traverseAtGranularity(int granularity, boolean forward,
13990             boolean extendSelection) {
13991         CharSequence text = getIterableTextForAccessibility();
13992         if (text == null || text.length() == 0) {
13993             return false;
13994         }
13995         TextSegmentIterator iterator = getIteratorForGranularity(granularity);
13996         if (iterator == null) {
13997             return false;
13998         }
13999         int current = getAccessibilitySelectionEnd();
14000         if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
14001             current = forward ? 0 : text.length();
14002         }
14003         final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
14004         if (range == null) {
14005             return false;
14006         }
14007         final int segmentStart = range[0];
14008         final int segmentEnd = range[1];
14009         int selectionStart;
14010         int selectionEnd;
14011         if (extendSelection && isAccessibilitySelectionExtendable()) {
14012             selectionStart = getAccessibilitySelectionStart();
14013             if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
14014                 selectionStart = forward ? segmentStart : segmentEnd;
14015             }
14016             selectionEnd = forward ? segmentEnd : segmentStart;
14017         } else {
14018             selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
14019         }
14020         setAccessibilitySelection(selectionStart, selectionEnd);
14021         final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
14022                 : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
14023         sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
14024         return true;
14025     }
14026 
14027     /**
14028      * Gets the text reported for accessibility purposes.
14029      *
14030      * @return The accessibility text.
14031      *
14032      * @hide
14033      */
14034     @UnsupportedAppUsage
14035     public CharSequence getIterableTextForAccessibility() {
14036         return getContentDescription();
14037     }
14038 
14039     /**
14040      * Gets whether accessibility selection can be extended.
14041      *
14042      * @return If selection is extensible.
14043      *
14044      * @hide
14045      */
14046     public boolean isAccessibilitySelectionExtendable() {
14047         return false;
14048     }
14049 
14050     /**
14051      * @hide
14052      */
14053     public int getAccessibilitySelectionStart() {
14054         return mAccessibilityCursorPosition;
14055     }
14056 
14057     /**
14058      * @hide
14059      */
14060     public int getAccessibilitySelectionEnd() {
14061         return getAccessibilitySelectionStart();
14062     }
14063 
14064     /**
14065      * @hide
14066      */
14067     public void setAccessibilitySelection(int start, int end) {
14068         if (start ==  end && end == mAccessibilityCursorPosition) {
14069             return;
14070         }
14071         if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
14072             mAccessibilityCursorPosition = start;
14073         } else {
14074             mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
14075         }
14076         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
14077     }
14078 
14079     private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
14080             int fromIndex, int toIndex) {
14081         if (mParent == null) {
14082             return;
14083         }
14084         AccessibilityEvent event = AccessibilityEvent.obtain(
14085                 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
14086         onInitializeAccessibilityEvent(event);
14087         onPopulateAccessibilityEvent(event);
14088         event.setFromIndex(fromIndex);
14089         event.setToIndex(toIndex);
14090         event.setAction(action);
14091         event.setMovementGranularity(granularity);
14092         mParent.requestSendAccessibilityEvent(this, event);
14093     }
14094 
14095     /**
14096      * @hide
14097      */
14098     @UnsupportedAppUsage
14099     public TextSegmentIterator getIteratorForGranularity(int granularity) {
14100         switch (granularity) {
14101             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
14102                 CharSequence text = getIterableTextForAccessibility();
14103                 if (text != null && text.length() > 0) {
14104                     CharacterTextSegmentIterator iterator =
14105                         CharacterTextSegmentIterator.getInstance(
14106                                 mContext.getResources().getConfiguration().locale);
14107                     iterator.initialize(text.toString());
14108                     return iterator;
14109                 }
14110             } break;
14111             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
14112                 CharSequence text = getIterableTextForAccessibility();
14113                 if (text != null && text.length() > 0) {
14114                     WordTextSegmentIterator iterator =
14115                         WordTextSegmentIterator.getInstance(
14116                                 mContext.getResources().getConfiguration().locale);
14117                     iterator.initialize(text.toString());
14118                     return iterator;
14119                 }
14120             } break;
14121             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
14122                 CharSequence text = getIterableTextForAccessibility();
14123                 if (text != null && text.length() > 0) {
14124                     ParagraphTextSegmentIterator iterator =
14125                         ParagraphTextSegmentIterator.getInstance();
14126                     iterator.initialize(text.toString());
14127                     return iterator;
14128                 }
14129             } break;
14130         }
14131         return null;
14132     }
14133 
14134     /**
14135      * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
14136      * and {@link #onFinishTemporaryDetach()}.
14137      *
14138      * <p>This method always returns {@code true} when called directly or indirectly from
14139      * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
14140      * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
14141      * <ul>
14142      *     <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
14143      *     <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
14144      * </ul>
14145      * </p>
14146      *
14147      * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
14148      * and {@link #onFinishTemporaryDetach()}.
14149      */
14150     public final boolean isTemporarilyDetached() {
14151         return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
14152     }
14153 
14154     /**
14155      * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
14156      * a container View.
14157      */
14158     @CallSuper
14159     public void dispatchStartTemporaryDetach() {
14160         mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
14161         notifyEnterOrExitForAutoFillIfNeeded(false);
14162         notifyAppearedOrDisappearedForContentCaptureIfNeeded(false);
14163         onStartTemporaryDetach();
14164     }
14165 
14166     /**
14167      * This is called when a container is going to temporarily detach a child, with
14168      * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
14169      * It will either be followed by {@link #onFinishTemporaryDetach()} or
14170      * {@link #onDetachedFromWindow()} when the container is done.
14171      */
14172     public void onStartTemporaryDetach() {
14173         removeUnsetPressCallback();
14174         mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
14175     }
14176 
14177     /**
14178      * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
14179      * a container View.
14180      */
14181     @CallSuper
14182     public void dispatchFinishTemporaryDetach() {
14183         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
14184         onFinishTemporaryDetach();
14185         if (hasWindowFocus() && hasFocus()) {
14186             notifyFocusChangeToImeFocusController(true /* hasFocus */);
14187         }
14188         notifyEnterOrExitForAutoFillIfNeeded(true);
14189         notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
14190     }
14191 
14192     /**
14193      * Called after {@link #onStartTemporaryDetach} when the container is done
14194      * changing the view.
14195      */
14196     public void onFinishTemporaryDetach() {
14197     }
14198 
14199     /**
14200      * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
14201      * for this view's window.  Returns null if the view is not currently attached
14202      * to the window.  Normally you will not need to use this directly, but
14203      * just use the standard high-level event callbacks like
14204      * {@link #onKeyDown(int, KeyEvent)}.
14205      */
14206     public KeyEvent.DispatcherState getKeyDispatcherState() {
14207         return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
14208     }
14209 
14210     /**
14211      * Dispatch a key event before it is processed by any input method
14212      * associated with the view hierarchy.  This can be used to intercept
14213      * key events in special situations before the IME consumes them; a
14214      * typical example would be handling the BACK key to update the application's
14215      * UI instead of allowing the IME to see it and close itself.
14216      *
14217      * @param event The key event to be dispatched.
14218      * @return True if the event was handled, false otherwise.
14219      */
14220     public boolean dispatchKeyEventPreIme(KeyEvent event) {
14221         return onKeyPreIme(event.getKeyCode(), event);
14222     }
14223 
14224     /**
14225      * Dispatch a key event to the next view on the focus path. This path runs
14226      * from the top of the view tree down to the currently focused view. If this
14227      * view has focus, it will dispatch to itself. Otherwise it will dispatch
14228      * the next node down the focus path. This method also fires any key
14229      * listeners.
14230      *
14231      * @param event The key event to be dispatched.
14232      * @return True if the event was handled, false otherwise.
14233      */
14234     public boolean dispatchKeyEvent(KeyEvent event) {
14235         if (mInputEventConsistencyVerifier != null) {
14236             mInputEventConsistencyVerifier.onKeyEvent(event, 0);
14237         }
14238 
14239         // Give any attached key listener a first crack at the event.
14240         //noinspection SimplifiableIfStatement
14241         ListenerInfo li = mListenerInfo;
14242         if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
14243                 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
14244             return true;
14245         }
14246 
14247         if (event.dispatch(this, mAttachInfo != null
14248                 ? mAttachInfo.mKeyDispatchState : null, this)) {
14249             return true;
14250         }
14251 
14252         if (mInputEventConsistencyVerifier != null) {
14253             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
14254         }
14255         return false;
14256     }
14257 
14258     /**
14259      * Dispatches a key shortcut event.
14260      *
14261      * @param event The key event to be dispatched.
14262      * @return True if the event was handled by the view, false otherwise.
14263      */
14264     public boolean dispatchKeyShortcutEvent(KeyEvent event) {
14265         return onKeyShortcut(event.getKeyCode(), event);
14266     }
14267 
14268     /**
14269      * Pass the touch screen motion event down to the target view, or this
14270      * view if it is the target.
14271      *
14272      * @param event The motion event to be dispatched.
14273      * @return True if the event was handled by the view, false otherwise.
14274      */
14275     public boolean dispatchTouchEvent(MotionEvent event) {
14276         // If the event should be handled by accessibility focus first.
14277         if (event.isTargetAccessibilityFocus()) {
14278             // We don't have focus or no virtual descendant has it, do not handle the event.
14279             if (!isAccessibilityFocusedViewOrHost()) {
14280                 return false;
14281             }
14282             // We have focus and got the event, then use normal event dispatch.
14283             event.setTargetAccessibilityFocus(false);
14284         }
14285         boolean result = false;
14286 
14287         if (mInputEventConsistencyVerifier != null) {
14288             mInputEventConsistencyVerifier.onTouchEvent(event, 0);
14289         }
14290 
14291         final int actionMasked = event.getActionMasked();
14292         if (actionMasked == MotionEvent.ACTION_DOWN) {
14293             // Defensive cleanup for new gesture
14294             stopNestedScroll();
14295         }
14296 
14297         if (onFilterTouchEventForSecurity(event)) {
14298             if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
14299                 result = true;
14300             }
14301             //noinspection SimplifiableIfStatement
14302             ListenerInfo li = mListenerInfo;
14303             if (li != null && li.mOnTouchListener != null
14304                     && (mViewFlags & ENABLED_MASK) == ENABLED
14305                     && li.mOnTouchListener.onTouch(this, event)) {
14306                 result = true;
14307             }
14308 
14309             if (!result && onTouchEvent(event)) {
14310                 result = true;
14311             }
14312         }
14313 
14314         if (!result && mInputEventConsistencyVerifier != null) {
14315             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
14316         }
14317 
14318         // Clean up after nested scrolls if this is the end of a gesture;
14319         // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
14320         // of the gesture.
14321         if (actionMasked == MotionEvent.ACTION_UP ||
14322                 actionMasked == MotionEvent.ACTION_CANCEL ||
14323                 (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
14324             stopNestedScroll();
14325         }
14326 
14327         return result;
14328     }
14329 
14330     boolean isAccessibilityFocusedViewOrHost() {
14331         return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
14332                 .getAccessibilityFocusedHost() == this);
14333     }
14334 
14335     /**
14336      * Returns whether this view can receive pointer events.
14337      *
14338      * @return {@code true} if this view can receive pointer events.
14339      * @hide
14340      */
14341     protected boolean canReceivePointerEvents() {
14342         return (mViewFlags & VISIBILITY_MASK) == VISIBLE || getAnimation() != null;
14343     }
14344 
14345     /**
14346      * Filter the touch event to apply security policies.
14347      *
14348      * @param event The motion event to be filtered.
14349      * @return True if the event should be dispatched, false if the event should be dropped.
14350      *
14351      * @see #getFilterTouchesWhenObscured
14352      */
14353     public boolean onFilterTouchEventForSecurity(MotionEvent event) {
14354         //noinspection RedundantIfStatement
14355         if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
14356                 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
14357             // Window is obscured, drop this touch.
14358             return false;
14359         }
14360         return true;
14361     }
14362 
14363     /**
14364      * Pass a trackball motion event down to the focused view.
14365      *
14366      * @param event The motion event to be dispatched.
14367      * @return True if the event was handled by the view, false otherwise.
14368      */
14369     public boolean dispatchTrackballEvent(MotionEvent event) {
14370         if (mInputEventConsistencyVerifier != null) {
14371             mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
14372         }
14373 
14374         return onTrackballEvent(event);
14375     }
14376 
14377     /**
14378      * Pass a captured pointer event down to the focused view.
14379      *
14380      * @param event The motion event to be dispatched.
14381      * @return True if the event was handled by the view, false otherwise.
14382      */
14383     public boolean dispatchCapturedPointerEvent(MotionEvent event) {
14384         if (!hasPointerCapture()) {
14385             return false;
14386         }
14387         //noinspection SimplifiableIfStatement
14388         ListenerInfo li = mListenerInfo;
14389         if (li != null && li.mOnCapturedPointerListener != null
14390                 && li.mOnCapturedPointerListener.onCapturedPointer(this, event)) {
14391             return true;
14392         }
14393         return onCapturedPointerEvent(event);
14394     }
14395 
14396     /**
14397      * Dispatch a generic motion event.
14398      * <p>
14399      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
14400      * are delivered to the view under the pointer.  All other generic motion events are
14401      * delivered to the focused view.  Hover events are handled specially and are delivered
14402      * to {@link #onHoverEvent(MotionEvent)}.
14403      * </p>
14404      *
14405      * @param event The motion event to be dispatched.
14406      * @return True if the event was handled by the view, false otherwise.
14407      */
14408     public boolean dispatchGenericMotionEvent(MotionEvent event) {
14409         if (mInputEventConsistencyVerifier != null) {
14410             mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
14411         }
14412 
14413         final int source = event.getSource();
14414         if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
14415             final int action = event.getAction();
14416             if (action == MotionEvent.ACTION_HOVER_ENTER
14417                     || action == MotionEvent.ACTION_HOVER_MOVE
14418                     || action == MotionEvent.ACTION_HOVER_EXIT) {
14419                 if (dispatchHoverEvent(event)) {
14420                     return true;
14421                 }
14422             } else if (dispatchGenericPointerEvent(event)) {
14423                 return true;
14424             }
14425         } else if (dispatchGenericFocusedEvent(event)) {
14426             return true;
14427         }
14428 
14429         if (dispatchGenericMotionEventInternal(event)) {
14430             return true;
14431         }
14432 
14433         if (mInputEventConsistencyVerifier != null) {
14434             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
14435         }
14436         return false;
14437     }
14438 
14439     private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
14440         //noinspection SimplifiableIfStatement
14441         ListenerInfo li = mListenerInfo;
14442         if (li != null && li.mOnGenericMotionListener != null
14443                 && (mViewFlags & ENABLED_MASK) == ENABLED
14444                 && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
14445             return true;
14446         }
14447 
14448         if (onGenericMotionEvent(event)) {
14449             return true;
14450         }
14451 
14452         final int actionButton = event.getActionButton();
14453         switch (event.getActionMasked()) {
14454             case MotionEvent.ACTION_BUTTON_PRESS:
14455                 if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
14456                         && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
14457                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
14458                     if (performContextClick(event.getX(), event.getY())) {
14459                         mInContextButtonPress = true;
14460                         setPressed(true, event.getX(), event.getY());
14461                         removeTapCallback();
14462                         removeLongPressCallback();
14463                         return true;
14464                     }
14465                 }
14466                 break;
14467 
14468             case MotionEvent.ACTION_BUTTON_RELEASE:
14469                 if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
14470                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
14471                     mInContextButtonPress = false;
14472                     mIgnoreNextUpEvent = true;
14473                 }
14474                 break;
14475         }
14476 
14477         if (mInputEventConsistencyVerifier != null) {
14478             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
14479         }
14480         return false;
14481     }
14482 
14483     /**
14484      * Dispatch a hover event.
14485      * <p>
14486      * Do not call this method directly.
14487      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
14488      * </p>
14489      *
14490      * @param event The motion event to be dispatched.
14491      * @return True if the event was handled by the view, false otherwise.
14492      */
14493     protected boolean dispatchHoverEvent(MotionEvent event) {
14494         ListenerInfo li = mListenerInfo;
14495         //noinspection SimplifiableIfStatement
14496         if (li != null && li.mOnHoverListener != null
14497                 && (mViewFlags & ENABLED_MASK) == ENABLED
14498                 && li.mOnHoverListener.onHover(this, event)) {
14499             return true;
14500         }
14501 
14502         return onHoverEvent(event);
14503     }
14504 
14505     /**
14506      * Returns true if the view has a child to which it has recently sent
14507      * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
14508      * it does not have a hovered child, then it must be the innermost hovered view.
14509      * @hide
14510      */
14511     protected boolean hasHoveredChild() {
14512         return false;
14513     }
14514 
14515     /**
14516      * Returns true if the given point, in local coordinates, is inside the hovered child.
14517      *
14518      * @hide
14519      */
14520     protected boolean pointInHoveredChild(MotionEvent event) {
14521         return false;
14522     }
14523 
14524     /**
14525      * Dispatch a generic motion event to the view under the first pointer.
14526      * <p>
14527      * Do not call this method directly.
14528      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
14529      * </p>
14530      *
14531      * @param event The motion event to be dispatched.
14532      * @return True if the event was handled by the view, false otherwise.
14533      */
14534     protected boolean dispatchGenericPointerEvent(MotionEvent event) {
14535         return false;
14536     }
14537 
14538     /**
14539      * Dispatch a generic motion event to the currently focused view.
14540      * <p>
14541      * Do not call this method directly.
14542      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
14543      * </p>
14544      *
14545      * @param event The motion event to be dispatched.
14546      * @return True if the event was handled by the view, false otherwise.
14547      */
14548     protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
14549         return false;
14550     }
14551 
14552     /**
14553      * Dispatch a pointer event.
14554      * <p>
14555      * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
14556      * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
14557      * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
14558      * and should not be expected to handle other pointing device features.
14559      * </p>
14560      *
14561      * @param event The motion event to be dispatched.
14562      * @return True if the event was handled by the view, false otherwise.
14563      * @hide
14564      */
14565     @UnsupportedAppUsage
14566     public final boolean dispatchPointerEvent(MotionEvent event) {
14567         if (event.isTouchEvent()) {
14568             return dispatchTouchEvent(event);
14569         } else {
14570             return dispatchGenericMotionEvent(event);
14571         }
14572     }
14573 
14574     /**
14575      * Called when the window containing this view gains or loses window focus.
14576      * ViewGroups should override to route to their children.
14577      *
14578      * @param hasFocus True if the window containing this view now has focus,
14579      *        false otherwise.
14580      */
14581     public void dispatchWindowFocusChanged(boolean hasFocus) {
14582         onWindowFocusChanged(hasFocus);
14583     }
14584 
14585     /**
14586      * Called when the window containing this view gains or loses focus.  Note
14587      * that this is separate from view focus: to receive key events, both
14588      * your view and its window must have focus.  If a window is displayed
14589      * on top of yours that takes input focus, then your own window will lose
14590      * focus but the view focus will remain unchanged.
14591      *
14592      * @param hasWindowFocus True if the window containing this view now has
14593      *        focus, false otherwise.
14594      */
14595     public void onWindowFocusChanged(boolean hasWindowFocus) {
14596         if (!hasWindowFocus) {
14597             if (isPressed()) {
14598                 setPressed(false);
14599             }
14600             mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
14601             if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
14602                 notifyFocusChangeToImeFocusController(false /* hasFocus */);
14603             }
14604             removeLongPressCallback();
14605             removeTapCallback();
14606             onFocusLost();
14607         } else if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
14608             notifyFocusChangeToImeFocusController(true /* hasFocus */);
14609         }
14610 
14611         refreshDrawableState();
14612     }
14613 
14614     /**
14615      * Returns true if this view is in a window that currently has window focus.
14616      * Note that this is not the same as the view itself having focus.
14617      *
14618      * @return True if this view is in a window that currently has window focus.
14619      */
14620     public boolean hasWindowFocus() {
14621         return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
14622     }
14623 
14624     /**
14625      * @return {@code true} if this view is in a window that currently has IME focusable state.
14626      * @hide
14627      */
14628     public boolean hasImeFocus() {
14629         return getViewRootImpl() != null && getViewRootImpl().getImeFocusController().hasImeFocus();
14630     }
14631 
14632     /**
14633      * Dispatch a view visibility change down the view hierarchy.
14634      * ViewGroups should override to route to their children.
14635      * @param changedView The view whose visibility changed. Could be 'this' or
14636      * an ancestor view.
14637      * @param visibility The new visibility of changedView: {@link #VISIBLE},
14638      * {@link #INVISIBLE} or {@link #GONE}.
14639      */
14640     protected void dispatchVisibilityChanged(@NonNull View changedView,
14641             @Visibility int visibility) {
14642         onVisibilityChanged(changedView, visibility);
14643     }
14644 
14645     /**
14646      * Called when the visibility of the view or an ancestor of the view has
14647      * changed.
14648      *
14649      * @param changedView The view whose visibility changed. May be
14650      *                    {@code this} or an ancestor view.
14651      * @param visibility The new visibility, one of {@link #VISIBLE},
14652      *                   {@link #INVISIBLE} or {@link #GONE}.
14653      */
14654     protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
14655     }
14656 
14657     /**
14658      * Dispatch a hint about whether this view is displayed. For instance, when
14659      * a View moves out of the screen, it might receives a display hint indicating
14660      * the view is not displayed. Applications should not <em>rely</em> on this hint
14661      * as there is no guarantee that they will receive one.
14662      *
14663      * @param hint A hint about whether or not this view is displayed:
14664      * {@link #VISIBLE} or {@link #INVISIBLE}.
14665      */
14666     public void dispatchDisplayHint(@Visibility int hint) {
14667         onDisplayHint(hint);
14668     }
14669 
14670     /**
14671      * Gives this view a hint about whether is displayed or not. For instance, when
14672      * a View moves out of the screen, it might receives a display hint indicating
14673      * the view is not displayed. Applications should not <em>rely</em> on this hint
14674      * as there is no guarantee that they will receive one.
14675      *
14676      * @param hint A hint about whether or not this view is displayed:
14677      * {@link #VISIBLE} or {@link #INVISIBLE}.
14678      */
14679     protected void onDisplayHint(@Visibility int hint) {
14680     }
14681 
14682     /**
14683      * Dispatch a window visibility change down the view hierarchy.
14684      * ViewGroups should override to route to their children.
14685      *
14686      * @param visibility The new visibility of the window.
14687      *
14688      * @see #onWindowVisibilityChanged(int)
14689      */
14690     public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
14691         onWindowVisibilityChanged(visibility);
14692     }
14693 
14694     /**
14695      * Called when the window containing has change its visibility
14696      * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
14697      * that this tells you whether or not your window is being made visible
14698      * to the window manager; this does <em>not</em> tell you whether or not
14699      * your window is obscured by other windows on the screen, even if it
14700      * is itself visible.
14701      *
14702      * @param visibility The new visibility of the window.
14703      */
14704     protected void onWindowVisibilityChanged(@Visibility int visibility) {
14705         if (visibility == VISIBLE) {
14706             initialAwakenScrollBars();
14707         }
14708     }
14709 
14710     /**
14711      * @return true if this view and all ancestors are visible as of the last
14712      * {@link #onVisibilityAggregated(boolean)} call.
14713      */
14714     boolean isAggregatedVisible() {
14715         return (mPrivateFlags3 & PFLAG3_AGGREGATED_VISIBLE) != 0;
14716     }
14717 
14718     /**
14719      * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
14720      * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
14721      * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
14722      *
14723      * @param isVisible true if this view's visibility to the user is uninterrupted by its
14724      *                  ancestors or by window visibility
14725      * @return true if this view is visible to the user, not counting clipping or overlapping
14726      */
14727     boolean dispatchVisibilityAggregated(boolean isVisible) {
14728         final boolean thisVisible = getVisibility() == VISIBLE;
14729         // If we're not visible but something is telling us we are, ignore it.
14730         if (thisVisible || !isVisible) {
14731             onVisibilityAggregated(isVisible);
14732         }
14733         return thisVisible && isVisible;
14734     }
14735 
14736     /**
14737      * Called when the user-visibility of this View is potentially affected by a change
14738      * to this view itself, an ancestor view or the window this view is attached to.
14739      *
14740      * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
14741      *                  and this view's window is also visible
14742      */
14743     @CallSuper
14744     public void onVisibilityAggregated(boolean isVisible) {
14745         // Update our internal visibility tracking so we can detect changes
14746         boolean oldVisible = isAggregatedVisible();
14747         mPrivateFlags3 = isVisible ? (mPrivateFlags3 | PFLAG3_AGGREGATED_VISIBLE)
14748                 : (mPrivateFlags3 & ~PFLAG3_AGGREGATED_VISIBLE);
14749         if (isVisible && mAttachInfo != null) {
14750             initialAwakenScrollBars();
14751         }
14752 
14753         final Drawable dr = mBackground;
14754         if (dr != null && isVisible != dr.isVisible()) {
14755             dr.setVisible(isVisible, false);
14756         }
14757         final Drawable hl = mDefaultFocusHighlight;
14758         if (hl != null && isVisible != hl.isVisible()) {
14759             hl.setVisible(isVisible, false);
14760         }
14761         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
14762         if (fg != null && isVisible != fg.isVisible()) {
14763             fg.setVisible(isVisible, false);
14764         }
14765 
14766         if (isAutofillable()) {
14767             AutofillManager afm = getAutofillManager();
14768 
14769             if (afm != null && getAutofillViewId() > LAST_APP_AUTOFILL_ID) {
14770                 if (mVisibilityChangeForAutofillHandler != null) {
14771                     mVisibilityChangeForAutofillHandler.removeMessages(0);
14772                 }
14773 
14774                 // If the view is in the background but still part of the hierarchy this is called
14775                 // with isVisible=false. Hence visibility==false requires further checks
14776                 if (isVisible) {
14777                     afm.notifyViewVisibilityChanged(this, true);
14778                 } else {
14779                     if (mVisibilityChangeForAutofillHandler == null) {
14780                         mVisibilityChangeForAutofillHandler =
14781                                 new VisibilityChangeForAutofillHandler(afm, this);
14782                     }
14783                     // Let current operation (e.g. removal of the view from the hierarchy)
14784                     // finish before checking state
14785                     mVisibilityChangeForAutofillHandler.obtainMessage(0, this).sendToTarget();
14786                 }
14787             }
14788         }
14789 
14790         if (isVisible != oldVisible) {
14791             if (isAccessibilityPane()) {
14792                 notifyViewAccessibilityStateChangedIfNeeded(isVisible
14793                         ? AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_APPEARED
14794                         : AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED);
14795             }
14796 
14797             notifyAppearedOrDisappearedForContentCaptureIfNeeded(isVisible);
14798 
14799             if (!getSystemGestureExclusionRects().isEmpty()) {
14800                 postUpdateSystemGestureExclusionRects();
14801             }
14802         }
14803     }
14804 
14805     /**
14806      * Returns the current visibility of the window this view is attached to
14807      * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
14808      *
14809      * @return Returns the current visibility of the view's window.
14810      */
14811     @Visibility
14812     public int getWindowVisibility() {
14813         return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
14814     }
14815 
14816     /**
14817      * Retrieve the overall visible display size in which the window this view is
14818      * attached to has been positioned in.  This takes into account screen
14819      * decorations above the window, for both cases where the window itself
14820      * is being position inside of them or the window is being placed under
14821      * then and covered insets are used for the window to position its content
14822      * inside.  In effect, this tells you the available area where content can
14823      * be placed and remain visible to users.
14824      *
14825      * <p>This function requires an IPC back to the window manager to retrieve
14826      * the requested information, so should not be used in performance critical
14827      * code like drawing.
14828      *
14829      * @param outRect Filled in with the visible display frame.  If the view
14830      * is not attached to a window, this is simply the raw display size.
14831      */
14832     public void getWindowVisibleDisplayFrame(Rect outRect) {
14833         if (mAttachInfo != null) {
14834             try {
14835                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
14836             } catch (RemoteException e) {
14837                 return;
14838             }
14839             // XXX This is really broken, and probably all needs to be done
14840             // in the window manager, and we need to know more about whether
14841             // we want the area behind or in front of the IME.
14842             final Rect insets = mAttachInfo.mVisibleInsets;
14843             outRect.left += insets.left;
14844             outRect.top += insets.top;
14845             outRect.right -= insets.right;
14846             outRect.bottom -= insets.bottom;
14847             return;
14848         }
14849         // The view is not attached to a display so we don't have a context.
14850         // Make a best guess about the display size.
14851         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
14852         d.getRectSize(outRect);
14853     }
14854 
14855     /**
14856      * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
14857      * is currently in without any insets.
14858      *
14859      * @hide
14860      */
14861     @UnsupportedAppUsage
14862     public void getWindowDisplayFrame(Rect outRect) {
14863         if (mAttachInfo != null) {
14864             try {
14865                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
14866             } catch (RemoteException e) {
14867                 return;
14868             }
14869             return;
14870         }
14871         // The view is not attached to a display so we don't have a context.
14872         // Make a best guess about the display size.
14873         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
14874         d.getRectSize(outRect);
14875     }
14876 
14877     /**
14878      * Dispatch a notification about a resource configuration change down
14879      * the view hierarchy.
14880      * ViewGroups should override to route to their children.
14881      *
14882      * @param newConfig The new resource configuration.
14883      *
14884      * @see #onConfigurationChanged(android.content.res.Configuration)
14885      */
14886     public void dispatchConfigurationChanged(Configuration newConfig) {
14887         onConfigurationChanged(newConfig);
14888     }
14889 
14890     /**
14891      * Called when the current configuration of the resources being used
14892      * by the application have changed.  You can use this to decide when
14893      * to reload resources that can changed based on orientation and other
14894      * configuration characteristics.  You only need to use this if you are
14895      * not relying on the normal {@link android.app.Activity} mechanism of
14896      * recreating the activity instance upon a configuration change.
14897      *
14898      * @param newConfig The new resource configuration.
14899      */
14900     protected void onConfigurationChanged(Configuration newConfig) {
14901     }
14902 
14903     /**
14904      * Private function to aggregate all per-view attributes in to the view
14905      * root.
14906      */
14907     void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
14908         performCollectViewAttributes(attachInfo, visibility);
14909     }
14910 
14911     void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
14912         if ((visibility & VISIBILITY_MASK) == VISIBLE) {
14913             if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
14914                 attachInfo.mKeepScreenOn = true;
14915             }
14916             attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
14917             ListenerInfo li = mListenerInfo;
14918             if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
14919                 attachInfo.mHasSystemUiListeners = true;
14920             }
14921         }
14922     }
14923 
14924     void needGlobalAttributesUpdate(boolean force) {
14925         final AttachInfo ai = mAttachInfo;
14926         if (ai != null && !ai.mRecomputeGlobalAttributes) {
14927             if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
14928                     || ai.mHasSystemUiListeners) {
14929                 ai.mRecomputeGlobalAttributes = true;
14930             }
14931         }
14932     }
14933 
14934     /**
14935      * Returns whether the device is currently in touch mode.  Touch mode is entered
14936      * once the user begins interacting with the device by touch, and affects various
14937      * things like whether focus is always visible to the user.
14938      *
14939      * @return Whether the device is in touch mode.
14940      */
14941     @ViewDebug.ExportedProperty
14942     public boolean isInTouchMode() {
14943         if (mAttachInfo != null) {
14944             return mAttachInfo.mInTouchMode;
14945         } else {
14946             return ViewRootImpl.isInTouchMode();
14947         }
14948     }
14949 
14950     /**
14951      * Returns the context the view is running in, through which it can
14952      * access the current theme, resources, etc.
14953      *
14954      * @return The view's Context.
14955      */
14956     @ViewDebug.CapturedViewProperty
14957     public final Context getContext() {
14958         return mContext;
14959     }
14960 
14961     /**
14962      * Handle a key event before it is processed by any input method
14963      * associated with the view hierarchy.  This can be used to intercept
14964      * key events in special situations before the IME consumes them; a
14965      * typical example would be handling the BACK key to update the application's
14966      * UI instead of allowing the IME to see it and close itself.
14967      *
14968      * @param keyCode The value in event.getKeyCode().
14969      * @param event Description of the key event.
14970      * @return If you handled the event, return true. If you want to allow the
14971      *         event to be handled by the next receiver, return false.
14972      */
14973     public boolean onKeyPreIme(int keyCode, KeyEvent event) {
14974         return false;
14975     }
14976 
14977     /**
14978      * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
14979      * KeyEvent.Callback.onKeyDown()}: perform press of the view
14980      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
14981      * is released, if the view is enabled and clickable.
14982      * <p>
14983      * Key presses in software keyboards will generally NOT trigger this
14984      * listener, although some may elect to do so in some situations. Do not
14985      * rely on this to catch software key presses.
14986      *
14987      * @param keyCode a key code that represents the button pressed, from
14988      *                {@link android.view.KeyEvent}
14989      * @param event the KeyEvent object that defines the button action
14990      */
14991     public boolean onKeyDown(int keyCode, KeyEvent event) {
14992         if (KeyEvent.isConfirmKey(keyCode)) {
14993             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
14994                 return true;
14995             }
14996 
14997             if (event.getRepeatCount() == 0) {
14998                 // Long clickable items don't necessarily have to be clickable.
14999                 final boolean clickable = (mViewFlags & CLICKABLE) == CLICKABLE
15000                         || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
15001                 if (clickable || (mViewFlags & TOOLTIP) == TOOLTIP) {
15002                     // For the purposes of menu anchoring and drawable hotspots,
15003                     // key events are considered to be at the center of the view.
15004                     final float x = getWidth() / 2f;
15005                     final float y = getHeight() / 2f;
15006                     if (clickable) {
15007                         setPressed(true, x, y);
15008                     }
15009                     checkForLongClick(
15010                             ViewConfiguration.getLongPressTimeout(),
15011                             x,
15012                             y,
15013                             // This is not a touch gesture -- do not classify it as one.
15014                             TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION);
15015                     return true;
15016                 }
15017             }
15018         }
15019 
15020         return false;
15021     }
15022 
15023     /**
15024      * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
15025      * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
15026      * the event).
15027      * <p>Key presses in software keyboards will generally NOT trigger this listener,
15028      * although some may elect to do so in some situations. Do not rely on this to
15029      * catch software key presses.
15030      */
15031     public boolean onKeyLongPress(int keyCode, KeyEvent event) {
15032         return false;
15033     }
15034 
15035     /**
15036      * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
15037      * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
15038      * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
15039      * or {@link KeyEvent#KEYCODE_SPACE} is released.
15040      * <p>Key presses in software keyboards will generally NOT trigger this listener,
15041      * although some may elect to do so in some situations. Do not rely on this to
15042      * catch software key presses.
15043      *
15044      * @param keyCode A key code that represents the button pressed, from
15045      *                {@link android.view.KeyEvent}.
15046      * @param event   The KeyEvent object that defines the button action.
15047      */
15048     public boolean onKeyUp(int keyCode, KeyEvent event) {
15049         if (KeyEvent.isConfirmKey(keyCode)) {
15050             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
15051                 return true;
15052             }
15053             if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
15054                 setPressed(false);
15055 
15056                 if (!mHasPerformedLongPress) {
15057                     // This is a tap, so remove the longpress check
15058                     removeLongPressCallback();
15059                     if (!event.isCanceled()) {
15060                         return performClickInternal();
15061                     }
15062                 }
15063             }
15064         }
15065         return false;
15066     }
15067 
15068     /**
15069      * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
15070      * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
15071      * the event).
15072      * <p>Key presses in software keyboards will generally NOT trigger this listener,
15073      * although some may elect to do so in some situations. Do not rely on this to
15074      * catch software key presses.
15075      *
15076      * @param keyCode     A key code that represents the button pressed, from
15077      *                    {@link android.view.KeyEvent}.
15078      * @param repeatCount The number of times the action was made.
15079      * @param event       The KeyEvent object that defines the button action.
15080      */
15081     public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
15082         return false;
15083     }
15084 
15085     /**
15086      * Called on the focused view when a key shortcut event is not handled.
15087      * Override this method to implement local key shortcuts for the View.
15088      * Key shortcuts can also be implemented by setting the
15089      * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
15090      *
15091      * @param keyCode The value in event.getKeyCode().
15092      * @param event Description of the key event.
15093      * @return If you handled the event, return true. If you want to allow the
15094      *         event to be handled by the next receiver, return false.
15095      */
15096     public boolean onKeyShortcut(int keyCode, KeyEvent event) {
15097         return false;
15098     }
15099 
15100     /**
15101      * Check whether the called view is a text editor, in which case it
15102      * would make sense to automatically display a soft input window for
15103      * it.  Subclasses should override this if they implement
15104      * {@link #onCreateInputConnection(EditorInfo)} to return true if
15105      * a call on that method would return a non-null InputConnection, and
15106      * they are really a first-class editor that the user would normally
15107      * start typing on when the go into a window containing your view.
15108      *
15109      * <p>The default implementation always returns false.  This does
15110      * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
15111      * will not be called or the user can not otherwise perform edits on your
15112      * view; it is just a hint to the system that this is not the primary
15113      * purpose of this view.
15114      *
15115      * @return Returns true if this view is a text editor, else false.
15116      */
15117     public boolean onCheckIsTextEditor() {
15118         return false;
15119     }
15120 
15121     /**
15122      * Create a new InputConnection for an InputMethod to interact
15123      * with the view.  The default implementation returns null, since it doesn't
15124      * support input methods.  You can override this to implement such support.
15125      * This is only needed for views that take focus and text input.
15126      *
15127      * <p>When implementing this, you probably also want to implement
15128      * {@link #onCheckIsTextEditor()} to indicate you will return a
15129      * non-null InputConnection.</p>
15130      *
15131      * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
15132      * object correctly and in its entirety, so that the connected IME can rely
15133      * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
15134      * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
15135      * must be filled in with the correct cursor position for IMEs to work correctly
15136      * with your application.</p>
15137      *
15138      * @param outAttrs Fill in with attribute information about the connection.
15139      */
15140     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
15141         return null;
15142     }
15143 
15144     /**
15145      * Called by the {@link android.view.inputmethod.InputMethodManager}
15146      * when a view who is not the current
15147      * input connection target is trying to make a call on the manager.  The
15148      * default implementation returns false; you can override this to return
15149      * true for certain views if you are performing InputConnection proxying
15150      * to them.
15151      * @param view The View that is making the InputMethodManager call.
15152      * @return Return true to allow the call, false to reject.
15153      */
15154     public boolean checkInputConnectionProxy(View view) {
15155         return false;
15156     }
15157 
15158     /**
15159      * Show the context menu for this view. It is not safe to hold on to the
15160      * menu after returning from this method.
15161      *
15162      * You should normally not overload this method. Overload
15163      * {@link #onCreateContextMenu(ContextMenu)} or define an
15164      * {@link OnCreateContextMenuListener} to add items to the context menu.
15165      *
15166      * @param menu The context menu to populate
15167      */
15168     public void createContextMenu(ContextMenu menu) {
15169         ContextMenuInfo menuInfo = getContextMenuInfo();
15170 
15171         // Sets the current menu info so all items added to menu will have
15172         // my extra info set.
15173         ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
15174 
15175         onCreateContextMenu(menu);
15176         ListenerInfo li = mListenerInfo;
15177         if (li != null && li.mOnCreateContextMenuListener != null) {
15178             li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
15179         }
15180 
15181         // Clear the extra information so subsequent items that aren't mine don't
15182         // have my extra info.
15183         ((MenuBuilder)menu).setCurrentMenuInfo(null);
15184 
15185         if (mParent != null) {
15186             mParent.createContextMenu(menu);
15187         }
15188     }
15189 
15190     /**
15191      * Views should implement this if they have extra information to associate
15192      * with the context menu. The return result is supplied as a parameter to
15193      * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
15194      * callback.
15195      *
15196      * @return Extra information about the item for which the context menu
15197      *         should be shown. This information will vary across different
15198      *         subclasses of View.
15199      */
15200     protected ContextMenuInfo getContextMenuInfo() {
15201         return null;
15202     }
15203 
15204     /**
15205      * Views should implement this if the view itself is going to add items to
15206      * the context menu.
15207      *
15208      * @param menu the context menu to populate
15209      */
15210     protected void onCreateContextMenu(ContextMenu menu) {
15211     }
15212 
15213     /**
15214      * Implement this method to handle trackball motion events.  The
15215      * <em>relative</em> movement of the trackball since the last event
15216      * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
15217      * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
15218      * that a movement of 1 corresponds to the user pressing one DPAD key (so
15219      * they will often be fractional values, representing the more fine-grained
15220      * movement information available from a trackball).
15221      *
15222      * @param event The motion event.
15223      * @return True if the event was handled, false otherwise.
15224      */
15225     public boolean onTrackballEvent(MotionEvent event) {
15226         return false;
15227     }
15228 
15229     /**
15230      * Implement this method to handle generic motion events.
15231      * <p>
15232      * Generic motion events describe joystick movements, mouse hovers, track pad
15233      * touches, scroll wheel movements and other input events.  The
15234      * {@link MotionEvent#getSource() source} of the motion event specifies
15235      * the class of input that was received.  Implementations of this method
15236      * must examine the bits in the source before processing the event.
15237      * The following code example shows how this is done.
15238      * </p><p>
15239      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
15240      * are delivered to the view under the pointer.  All other generic motion events are
15241      * delivered to the focused view.
15242      * </p>
15243      * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
15244      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
15245      *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
15246      *             // process the joystick movement...
15247      *             return true;
15248      *         }
15249      *     }
15250      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
15251      *         switch (event.getAction()) {
15252      *             case MotionEvent.ACTION_HOVER_MOVE:
15253      *                 // process the mouse hover movement...
15254      *                 return true;
15255      *             case MotionEvent.ACTION_SCROLL:
15256      *                 // process the scroll wheel movement...
15257      *                 return true;
15258      *         }
15259      *     }
15260      *     return super.onGenericMotionEvent(event);
15261      * }</pre>
15262      *
15263      * @param event The generic motion event being processed.
15264      * @return True if the event was handled, false otherwise.
15265      */
15266     public boolean onGenericMotionEvent(MotionEvent event) {
15267         return false;
15268     }
15269 
15270     /**
15271      * Dispatching hover events to {@link TouchDelegate} to improve accessibility.
15272      * <p>
15273      * This method is dispatching hover events to the delegate target to support explore by touch.
15274      * Similar to {@link ViewGroup#dispatchTouchEvent}, this method send proper hover events to
15275      * the delegate target according to the pointer and the touch area of the delegate while touch
15276      * exploration enabled.
15277      * </p>
15278      *
15279      * @param event The motion event dispatch to the delegate target.
15280      * @return True if the event was handled, false otherwise.
15281      *
15282      * @see #onHoverEvent
15283      */
15284     private boolean dispatchTouchExplorationHoverEvent(MotionEvent event) {
15285         final AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
15286         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
15287             return false;
15288         }
15289 
15290         final boolean oldHoveringTouchDelegate = mHoveringTouchDelegate;
15291         final int action = event.getActionMasked();
15292         boolean pointInDelegateRegion = false;
15293         boolean handled = false;
15294 
15295         final AccessibilityNodeInfo.TouchDelegateInfo info = mTouchDelegate.getTouchDelegateInfo();
15296         for (int i = 0; i < info.getRegionCount(); i++) {
15297             Region r = info.getRegionAt(i);
15298             if (r.contains((int) event.getX(), (int) event.getY())) {
15299                 pointInDelegateRegion = true;
15300             }
15301         }
15302 
15303         // Explore by touch should dispatch events to children under the pointer first if any
15304         // before dispatching to TouchDelegate. For non-hoverable views that do not consume
15305         // hover events but receive accessibility focus, it should also not delegate to these
15306         // views when hovered.
15307         if (!oldHoveringTouchDelegate) {
15308             if ((action == MotionEvent.ACTION_HOVER_ENTER
15309                     || action == MotionEvent.ACTION_HOVER_MOVE)
15310                     && !pointInHoveredChild(event)
15311                     && pointInDelegateRegion) {
15312                 mHoveringTouchDelegate = true;
15313             }
15314         } else {
15315             if (action == MotionEvent.ACTION_HOVER_EXIT
15316                     || (action == MotionEvent.ACTION_HOVER_MOVE
15317                         && (pointInHoveredChild(event) || !pointInDelegateRegion))) {
15318                 mHoveringTouchDelegate = false;
15319             }
15320         }
15321         switch (action) {
15322             case MotionEvent.ACTION_HOVER_MOVE:
15323                 if (oldHoveringTouchDelegate && mHoveringTouchDelegate) {
15324                     // Inside bounds, dispatch as is.
15325                     handled = mTouchDelegate.onTouchExplorationHoverEvent(event);
15326                 } else if (!oldHoveringTouchDelegate && mHoveringTouchDelegate) {
15327                     // Moving inbound, synthesize hover enter.
15328                     MotionEvent eventNoHistory = (event.getHistorySize() == 0)
15329                             ? event : MotionEvent.obtainNoHistory(event);
15330                     eventNoHistory.setAction(MotionEvent.ACTION_HOVER_ENTER);
15331                     handled = mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
15332                     eventNoHistory.setAction(action);
15333                     handled |= mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
15334                 } else if (oldHoveringTouchDelegate && !mHoveringTouchDelegate) {
15335                     // Moving outbound, synthesize hover exit.
15336                     final boolean hoverExitPending = event.isHoverExitPending();
15337                     event.setHoverExitPending(true);
15338                     mTouchDelegate.onTouchExplorationHoverEvent(event);
15339                     MotionEvent eventNoHistory = (event.getHistorySize() == 0)
15340                             ? event : MotionEvent.obtainNoHistory(event);
15341                     eventNoHistory.setHoverExitPending(hoverExitPending);
15342                     eventNoHistory.setAction(MotionEvent.ACTION_HOVER_EXIT);
15343                     mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
15344                 }  // else: outside bounds, do nothing.
15345                 break;
15346             case MotionEvent.ACTION_HOVER_ENTER:
15347                 if (!oldHoveringTouchDelegate && mHoveringTouchDelegate) {
15348                     handled = mTouchDelegate.onTouchExplorationHoverEvent(event);
15349                 }
15350                 break;
15351             case MotionEvent.ACTION_HOVER_EXIT:
15352                 if (oldHoveringTouchDelegate) {
15353                     mTouchDelegate.onTouchExplorationHoverEvent(event);
15354                 }
15355                 break;
15356         }
15357         return handled;
15358     }
15359 
15360     /**
15361      * Implement this method to handle hover events.
15362      * <p>
15363      * This method is called whenever a pointer is hovering into, over, or out of the
15364      * bounds of a view and the view is not currently being touched.
15365      * Hover events are represented as pointer events with action
15366      * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
15367      * or {@link MotionEvent#ACTION_HOVER_EXIT}.
15368      * </p>
15369      * <ul>
15370      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
15371      * when the pointer enters the bounds of the view.</li>
15372      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
15373      * when the pointer has already entered the bounds of the view and has moved.</li>
15374      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
15375      * when the pointer has exited the bounds of the view or when the pointer is
15376      * about to go down due to a button click, tap, or similar user action that
15377      * causes the view to be touched.</li>
15378      * </ul>
15379      * <p>
15380      * The view should implement this method to return true to indicate that it is
15381      * handling the hover event, such as by changing its drawable state.
15382      * </p><p>
15383      * The default implementation calls {@link #setHovered} to update the hovered state
15384      * of the view when a hover enter or hover exit event is received, if the view
15385      * is enabled and is clickable.  The default implementation also sends hover
15386      * accessibility events.
15387      * </p>
15388      *
15389      * @param event The motion event that describes the hover.
15390      * @return True if the view handled the hover event.
15391      *
15392      * @see #isHovered
15393      * @see #setHovered
15394      * @see #onHoverChanged
15395      */
15396     public boolean onHoverEvent(MotionEvent event) {
15397         if (mTouchDelegate != null && dispatchTouchExplorationHoverEvent(event)) {
15398             return true;
15399         }
15400 
15401         // The root view may receive hover (or touch) events that are outside the bounds of
15402         // the window.  This code ensures that we only send accessibility events for
15403         // hovers that are actually within the bounds of the root view.
15404         final int action = event.getActionMasked();
15405         if (!mSendingHoverAccessibilityEvents) {
15406             if ((action == MotionEvent.ACTION_HOVER_ENTER
15407                     || action == MotionEvent.ACTION_HOVER_MOVE)
15408                     && !hasHoveredChild()
15409                     && pointInView(event.getX(), event.getY())) {
15410                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
15411                 mSendingHoverAccessibilityEvents = true;
15412             }
15413         } else {
15414             if (action == MotionEvent.ACTION_HOVER_EXIT
15415                     || (action == MotionEvent.ACTION_HOVER_MOVE
15416                             && !pointInView(event.getX(), event.getY()))) {
15417                 mSendingHoverAccessibilityEvents = false;
15418                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
15419             }
15420         }
15421 
15422         if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
15423                 && event.isFromSource(InputDevice.SOURCE_MOUSE)
15424                 && isOnScrollbar(event.getX(), event.getY())) {
15425             awakenScrollBars();
15426         }
15427 
15428         // If we consider ourself hoverable, or if we we're already hovered,
15429         // handle changing state in response to ENTER and EXIT events.
15430         if (isHoverable() || isHovered()) {
15431             switch (action) {
15432                 case MotionEvent.ACTION_HOVER_ENTER:
15433                     setHovered(true);
15434                     break;
15435                 case MotionEvent.ACTION_HOVER_EXIT:
15436                     setHovered(false);
15437                     break;
15438             }
15439 
15440             // Dispatch the event to onGenericMotionEvent before returning true.
15441             // This is to provide compatibility with existing applications that
15442             // handled HOVER_MOVE events in onGenericMotionEvent and that would
15443             // break because of the new default handling for hoverable views
15444             // in onHoverEvent.
15445             // Note that onGenericMotionEvent will be called by default when
15446             // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
15447             dispatchGenericMotionEventInternal(event);
15448             // The event was already handled by calling setHovered(), so always
15449             // return true.
15450             return true;
15451         }
15452 
15453         return false;
15454     }
15455 
15456     /**
15457      * Returns true if the view should handle {@link #onHoverEvent}
15458      * by calling {@link #setHovered} to change its hovered state.
15459      *
15460      * @return True if the view is hoverable.
15461      */
15462     private boolean isHoverable() {
15463         final int viewFlags = mViewFlags;
15464         if ((viewFlags & ENABLED_MASK) == DISABLED) {
15465             return false;
15466         }
15467 
15468         return (viewFlags & CLICKABLE) == CLICKABLE
15469                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
15470                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
15471     }
15472 
15473     /**
15474      * Returns true if the view is currently hovered.
15475      *
15476      * @return True if the view is currently hovered.
15477      *
15478      * @see #setHovered
15479      * @see #onHoverChanged
15480      */
15481     @ViewDebug.ExportedProperty
15482     public boolean isHovered() {
15483         return (mPrivateFlags & PFLAG_HOVERED) != 0;
15484     }
15485 
15486     /**
15487      * Sets whether the view is currently hovered.
15488      * <p>
15489      * Calling this method also changes the drawable state of the view.  This
15490      * enables the view to react to hover by using different drawable resources
15491      * to change its appearance.
15492      * </p><p>
15493      * The {@link #onHoverChanged} method is called when the hovered state changes.
15494      * </p>
15495      *
15496      * @param hovered True if the view is hovered.
15497      *
15498      * @see #isHovered
15499      * @see #onHoverChanged
15500      */
15501     public void setHovered(boolean hovered) {
15502         if (hovered) {
15503             if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
15504                 mPrivateFlags |= PFLAG_HOVERED;
15505                 refreshDrawableState();
15506                 onHoverChanged(true);
15507             }
15508         } else {
15509             if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
15510                 mPrivateFlags &= ~PFLAG_HOVERED;
15511                 refreshDrawableState();
15512                 onHoverChanged(false);
15513             }
15514         }
15515     }
15516 
15517     /**
15518      * Implement this method to handle hover state changes.
15519      * <p>
15520      * This method is called whenever the hover state changes as a result of a
15521      * call to {@link #setHovered}.
15522      * </p>
15523      *
15524      * @param hovered The current hover state, as returned by {@link #isHovered}.
15525      *
15526      * @see #isHovered
15527      * @see #setHovered
15528      */
15529     public void onHoverChanged(boolean hovered) {
15530     }
15531 
15532     /**
15533      * Handles scroll bar dragging by mouse input.
15534      *
15535      * @hide
15536      * @param event The motion event.
15537      *
15538      * @return true if the event was handled as a scroll bar dragging, false otherwise.
15539      */
15540     protected boolean handleScrollBarDragging(MotionEvent event) {
15541         if (mScrollCache == null) {
15542             return false;
15543         }
15544         final float x = event.getX();
15545         final float y = event.getY();
15546         final int action = event.getAction();
15547         if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
15548                 && action != MotionEvent.ACTION_DOWN)
15549                     || !event.isFromSource(InputDevice.SOURCE_MOUSE)
15550                     || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
15551             mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
15552             return false;
15553         }
15554 
15555         switch (action) {
15556             case MotionEvent.ACTION_MOVE:
15557                 if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
15558                     return false;
15559                 }
15560                 if (mScrollCache.mScrollBarDraggingState
15561                         == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
15562                     final Rect bounds = mScrollCache.mScrollBarBounds;
15563                     getVerticalScrollBarBounds(bounds, null);
15564                     final int range = computeVerticalScrollRange();
15565                     final int offset = computeVerticalScrollOffset();
15566                     final int extent = computeVerticalScrollExtent();
15567 
15568                     final int thumbLength = ScrollBarUtils.getThumbLength(
15569                             bounds.height(), bounds.width(), extent, range);
15570                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
15571                             bounds.height(), thumbLength, extent, range, offset);
15572 
15573                     final float diff = y - mScrollCache.mScrollBarDraggingPos;
15574                     final float maxThumbOffset = bounds.height() - thumbLength;
15575                     final float newThumbOffset =
15576                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
15577                     final int height = getHeight();
15578                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
15579                             && height > 0 && extent > 0) {
15580                         final int newY = Math.round((range - extent)
15581                                 / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
15582                         if (newY != getScrollY()) {
15583                             mScrollCache.mScrollBarDraggingPos = y;
15584                             setScrollY(newY);
15585                         }
15586                     }
15587                     return true;
15588                 }
15589                 if (mScrollCache.mScrollBarDraggingState
15590                         == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
15591                     final Rect bounds = mScrollCache.mScrollBarBounds;
15592                     getHorizontalScrollBarBounds(bounds, null);
15593                     final int range = computeHorizontalScrollRange();
15594                     final int offset = computeHorizontalScrollOffset();
15595                     final int extent = computeHorizontalScrollExtent();
15596 
15597                     final int thumbLength = ScrollBarUtils.getThumbLength(
15598                             bounds.width(), bounds.height(), extent, range);
15599                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
15600                             bounds.width(), thumbLength, extent, range, offset);
15601 
15602                     final float diff = x - mScrollCache.mScrollBarDraggingPos;
15603                     final float maxThumbOffset = bounds.width() - thumbLength;
15604                     final float newThumbOffset =
15605                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
15606                     final int width = getWidth();
15607                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
15608                             && width > 0 && extent > 0) {
15609                         final int newX = Math.round((range - extent)
15610                                 / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
15611                         if (newX != getScrollX()) {
15612                             mScrollCache.mScrollBarDraggingPos = x;
15613                             setScrollX(newX);
15614                         }
15615                     }
15616                     return true;
15617                 }
15618             case MotionEvent.ACTION_DOWN:
15619                 if (mScrollCache.state == ScrollabilityCache.OFF) {
15620                     return false;
15621                 }
15622                 if (isOnVerticalScrollbarThumb(x, y)) {
15623                     mScrollCache.mScrollBarDraggingState =
15624                             ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
15625                     mScrollCache.mScrollBarDraggingPos = y;
15626                     return true;
15627                 }
15628                 if (isOnHorizontalScrollbarThumb(x, y)) {
15629                     mScrollCache.mScrollBarDraggingState =
15630                             ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
15631                     mScrollCache.mScrollBarDraggingPos = x;
15632                     return true;
15633                 }
15634         }
15635         mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
15636         return false;
15637     }
15638 
15639     /**
15640      * Implement this method to handle touch screen motion events.
15641      * <p>
15642      * If this method is used to detect click actions, it is recommended that
15643      * the actions be performed by implementing and calling
15644      * {@link #performClick()}. This will ensure consistent system behavior,
15645      * including:
15646      * <ul>
15647      * <li>obeying click sound preferences
15648      * <li>dispatching OnClickListener calls
15649      * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
15650      * accessibility features are enabled
15651      * </ul>
15652      *
15653      * @param event The motion event.
15654      * @return True if the event was handled, false otherwise.
15655      */
15656     public boolean onTouchEvent(MotionEvent event) {
15657         final float x = event.getX();
15658         final float y = event.getY();
15659         final int viewFlags = mViewFlags;
15660         final int action = event.getAction();
15661 
15662         final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE
15663                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
15664                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
15665 
15666         if ((viewFlags & ENABLED_MASK) == DISABLED) {
15667             if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
15668                 setPressed(false);
15669             }
15670             mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
15671             // A disabled view that is clickable still consumes the touch
15672             // events, it just doesn't respond to them.
15673             return clickable;
15674         }
15675         if (mTouchDelegate != null) {
15676             if (mTouchDelegate.onTouchEvent(event)) {
15677                 return true;
15678             }
15679         }
15680 
15681         if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
15682             switch (action) {
15683                 case MotionEvent.ACTION_UP:
15684                     mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
15685                     if ((viewFlags & TOOLTIP) == TOOLTIP) {
15686                         handleTooltipUp();
15687                     }
15688                     if (!clickable) {
15689                         removeTapCallback();
15690                         removeLongPressCallback();
15691                         mInContextButtonPress = false;
15692                         mHasPerformedLongPress = false;
15693                         mIgnoreNextUpEvent = false;
15694                         break;
15695                     }
15696                     boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
15697                     if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
15698                         // take focus if we don't have it already and we should in
15699                         // touch mode.
15700                         boolean focusTaken = false;
15701                         if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
15702                             focusTaken = requestFocus();
15703                         }
15704 
15705                         if (prepressed) {
15706                             // The button is being released before we actually
15707                             // showed it as pressed.  Make it show the pressed
15708                             // state now (before scheduling the click) to ensure
15709                             // the user sees it.
15710                             setPressed(true, x, y);
15711                         }
15712 
15713                         if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
15714                             // This is a tap, so remove the longpress check
15715                             removeLongPressCallback();
15716 
15717                             // Only perform take click actions if we were in the pressed state
15718                             if (!focusTaken) {
15719                                 // Use a Runnable and post this rather than calling
15720                                 // performClick directly. This lets other visual state
15721                                 // of the view update before click actions start.
15722                                 if (mPerformClick == null) {
15723                                     mPerformClick = new PerformClick();
15724                                 }
15725                                 if (!post(mPerformClick)) {
15726                                     performClickInternal();
15727                                 }
15728                             }
15729                         }
15730 
15731                         if (mUnsetPressedState == null) {
15732                             mUnsetPressedState = new UnsetPressedState();
15733                         }
15734 
15735                         if (prepressed) {
15736                             postDelayed(mUnsetPressedState,
15737                                     ViewConfiguration.getPressedStateDuration());
15738                         } else if (!post(mUnsetPressedState)) {
15739                             // If the post failed, unpress right now
15740                             mUnsetPressedState.run();
15741                         }
15742 
15743                         removeTapCallback();
15744                     }
15745                     mIgnoreNextUpEvent = false;
15746                     break;
15747 
15748                 case MotionEvent.ACTION_DOWN:
15749                     if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
15750                         mPrivateFlags3 |= PFLAG3_FINGER_DOWN;
15751                     }
15752                     mHasPerformedLongPress = false;
15753 
15754                     if (!clickable) {
15755                         checkForLongClick(
15756                                 ViewConfiguration.getLongPressTimeout(),
15757                                 x,
15758                                 y,
15759                                 TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
15760                         break;
15761                     }
15762 
15763                     if (performButtonActionOnTouchDown(event)) {
15764                         break;
15765                     }
15766 
15767                     // Walk up the hierarchy to determine if we're inside a scrolling container.
15768                     boolean isInScrollingContainer = isInScrollingContainer();
15769 
15770                     // For views inside a scrolling container, delay the pressed feedback for
15771                     // a short period in case this is a scroll.
15772                     if (isInScrollingContainer) {
15773                         mPrivateFlags |= PFLAG_PREPRESSED;
15774                         if (mPendingCheckForTap == null) {
15775                             mPendingCheckForTap = new CheckForTap();
15776                         }
15777                         mPendingCheckForTap.x = event.getX();
15778                         mPendingCheckForTap.y = event.getY();
15779                         postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
15780                     } else {
15781                         // Not inside a scrolling container, so show the feedback right away
15782                         setPressed(true, x, y);
15783                         checkForLongClick(
15784                                 ViewConfiguration.getLongPressTimeout(),
15785                                 x,
15786                                 y,
15787                                 TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
15788                     }
15789                     break;
15790 
15791                 case MotionEvent.ACTION_CANCEL:
15792                     if (clickable) {
15793                         setPressed(false);
15794                     }
15795                     removeTapCallback();
15796                     removeLongPressCallback();
15797                     mInContextButtonPress = false;
15798                     mHasPerformedLongPress = false;
15799                     mIgnoreNextUpEvent = false;
15800                     mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
15801                     break;
15802 
15803                 case MotionEvent.ACTION_MOVE:
15804                     if (clickable) {
15805                         drawableHotspotChanged(x, y);
15806                     }
15807 
15808                     final int motionClassification = event.getClassification();
15809                     final boolean ambiguousGesture =
15810                             motionClassification == MotionEvent.CLASSIFICATION_AMBIGUOUS_GESTURE;
15811                     int touchSlop = mTouchSlop;
15812                     if (ambiguousGesture && hasPendingLongPressCallback()) {
15813                         if (!pointInView(x, y, touchSlop)) {
15814                             // The default action here is to cancel long press. But instead, we
15815                             // just extend the timeout here, in case the classification
15816                             // stays ambiguous.
15817                             removeLongPressCallback();
15818                             long delay = (long) (ViewConfiguration.getLongPressTimeout()
15819                                     * mAmbiguousGestureMultiplier);
15820                             // Subtract the time already spent
15821                             delay -= event.getEventTime() - event.getDownTime();
15822                             checkForLongClick(
15823                                     delay,
15824                                     x,
15825                                     y,
15826                                     TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
15827                         }
15828                         touchSlop *= mAmbiguousGestureMultiplier;
15829                     }
15830 
15831                     // Be lenient about moving outside of buttons
15832                     if (!pointInView(x, y, touchSlop)) {
15833                         // Outside button
15834                         // Remove any future long press/tap checks
15835                         removeTapCallback();
15836                         removeLongPressCallback();
15837                         if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
15838                             setPressed(false);
15839                         }
15840                         mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
15841                     }
15842 
15843                     final boolean deepPress =
15844                             motionClassification == MotionEvent.CLASSIFICATION_DEEP_PRESS;
15845                     if (deepPress && hasPendingLongPressCallback()) {
15846                         // process the long click action immediately
15847                         removeLongPressCallback();
15848                         checkForLongClick(
15849                                 0 /* send immediately */,
15850                                 x,
15851                                 y,
15852                                 TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS);
15853                     }
15854 
15855                     break;
15856             }
15857 
15858             return true;
15859         }
15860 
15861         return false;
15862     }
15863 
15864     /**
15865      * @hide
15866      */
15867     @UnsupportedAppUsage
15868     public boolean isInScrollingContainer() {
15869         ViewParent p = getParent();
15870         while (p != null && p instanceof ViewGroup) {
15871             if (((ViewGroup) p).shouldDelayChildPressedState()) {
15872                 return true;
15873             }
15874             p = p.getParent();
15875         }
15876         return false;
15877     }
15878 
15879     /**
15880      * Remove the longpress detection timer.
15881      */
15882     private void removeLongPressCallback() {
15883         if (mPendingCheckForLongPress != null) {
15884             removeCallbacks(mPendingCheckForLongPress);
15885         }
15886     }
15887 
15888     /**
15889      * Return true if the long press callback is scheduled to run sometime in the future.
15890      * Return false if there is no scheduled long press callback at the moment.
15891      */
15892     private boolean hasPendingLongPressCallback() {
15893         if (mPendingCheckForLongPress == null) {
15894             return false;
15895         }
15896         final AttachInfo attachInfo = mAttachInfo;
15897         if (attachInfo == null) {
15898             return false;
15899         }
15900         return attachInfo.mHandler.hasCallbacks(mPendingCheckForLongPress);
15901     }
15902 
15903    /**
15904      * Remove the pending click action
15905      */
15906     @UnsupportedAppUsage
15907     private void removePerformClickCallback() {
15908         if (mPerformClick != null) {
15909             removeCallbacks(mPerformClick);
15910         }
15911     }
15912 
15913     /**
15914      * Remove the prepress detection timer.
15915      */
15916     private void removeUnsetPressCallback() {
15917         if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
15918             setPressed(false);
15919             removeCallbacks(mUnsetPressedState);
15920         }
15921     }
15922 
15923     /**
15924      * Remove the tap detection timer.
15925      */
15926     private void removeTapCallback() {
15927         if (mPendingCheckForTap != null) {
15928             mPrivateFlags &= ~PFLAG_PREPRESSED;
15929             removeCallbacks(mPendingCheckForTap);
15930         }
15931     }
15932 
15933     /**
15934      * Cancels a pending long press.  Your subclass can use this if you
15935      * want the context menu to come up if the user presses and holds
15936      * at the same place, but you don't want it to come up if they press
15937      * and then move around enough to cause scrolling.
15938      */
15939     public void cancelLongPress() {
15940         removeLongPressCallback();
15941 
15942         /*
15943          * The prepressed state handled by the tap callback is a display
15944          * construct, but the tap callback will post a long press callback
15945          * less its own timeout. Remove it here.
15946          */
15947         removeTapCallback();
15948     }
15949 
15950     /**
15951      * Sets the TouchDelegate for this View.
15952      */
15953     public void setTouchDelegate(TouchDelegate delegate) {
15954         mTouchDelegate = delegate;
15955     }
15956 
15957     /**
15958      * Gets the TouchDelegate for this View.
15959      */
15960     public TouchDelegate getTouchDelegate() {
15961         return mTouchDelegate;
15962     }
15963 
15964     /**
15965      * Request unbuffered dispatch of the given stream of MotionEvents to this View.
15966      *
15967      * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
15968      * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
15969      * available. This method should only be called for touch events.
15970      *
15971      * <p class="note">This API is not intended for most applications. Buffered dispatch
15972      * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
15973      * streams will not improve your input latency. Side effects include: increased latency,
15974      * jittery scrolls and inability to take advantage of system resampling. Talk to your input
15975      * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
15976      * you.</p>
15977      *
15978      * To receive unbuffered events for arbitrary input device source classes, use
15979      * {@link #requestUnbufferedDispatch(int)},
15980      *
15981      * @see View#requestUnbufferedDispatch(int)
15982      */
15983     public final void requestUnbufferedDispatch(MotionEvent event) {
15984         final int action = event.getAction();
15985         if (mAttachInfo == null
15986                 || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
15987                 || !event.isTouchEvent()) {
15988             return;
15989         }
15990         mAttachInfo.mUnbufferedDispatchRequested = true;
15991     }
15992 
15993     /**
15994      * Request unbuffered dispatch of the given event source class to this view.
15995      * This is similar to {@link View#requestUnbufferedDispatch(MotionEvent)}, but does not
15996      * automatically terminate, and allows the specification of arbitrary input source classes.
15997      *
15998      * @param source The combined input source class to request unbuffered dispatch for. All
15999      *               events coming from these source classes will not be buffered. Set to
16000      *               {@link InputDevice#SOURCE_CLASS_NONE} in order to return to default behaviour.
16001      *
16002      * @see View#requestUnbufferedDispatch(MotionEvent)
16003      */
16004     public final void requestUnbufferedDispatch(@InputSourceClass int source) {
16005         if (mUnbufferedInputSource == source) {
16006             return;
16007         }
16008         mUnbufferedInputSource = source;
16009         if (mParent != null) {
16010             mParent.onDescendantUnbufferedRequested();
16011         }
16012     }
16013 
16014     private boolean hasSize() {
16015         return (mBottom > mTop) && (mRight > mLeft);
16016     }
16017 
16018     private boolean canTakeFocus() {
16019         return ((mViewFlags & VISIBILITY_MASK) == VISIBLE)
16020                 && ((mViewFlags & FOCUSABLE) == FOCUSABLE)
16021                 && ((mViewFlags & ENABLED_MASK) == ENABLED)
16022                 && (sCanFocusZeroSized || !isLayoutValid() || hasSize());
16023     }
16024 
16025     /**
16026      * Set flags controlling behavior of this view.
16027      *
16028      * @param flags Constant indicating the value which should be set
16029      * @param mask Constant indicating the bit range that should be changed
16030      */
16031     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
16032     void setFlags(int flags, int mask) {
16033         final boolean accessibilityEnabled =
16034                 AccessibilityManager.getInstance(mContext).isEnabled();
16035         final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
16036 
16037         int old = mViewFlags;
16038         mViewFlags = (mViewFlags & ~mask) | (flags & mask);
16039 
16040         int changed = mViewFlags ^ old;
16041         if (changed == 0) {
16042             return;
16043         }
16044         int privateFlags = mPrivateFlags;
16045         boolean shouldNotifyFocusableAvailable = false;
16046 
16047         // If focusable is auto, update the FOCUSABLE bit.
16048         int focusableChangedByAuto = 0;
16049         if (((mViewFlags & FOCUSABLE_AUTO) != 0)
16050                 && (changed & (FOCUSABLE_MASK | CLICKABLE)) != 0) {
16051             // Heuristic only takes into account whether view is clickable.
16052             final int newFocus;
16053             if ((mViewFlags & CLICKABLE) != 0) {
16054                 newFocus = FOCUSABLE;
16055             } else {
16056                 newFocus = NOT_FOCUSABLE;
16057             }
16058             mViewFlags = (mViewFlags & ~FOCUSABLE) | newFocus;
16059             focusableChangedByAuto = (old & FOCUSABLE) ^ (newFocus & FOCUSABLE);
16060             changed = (changed & ~FOCUSABLE) | focusableChangedByAuto;
16061         }
16062 
16063         /* Check if the FOCUSABLE bit has changed */
16064         if (((changed & FOCUSABLE) != 0) && ((privateFlags & PFLAG_HAS_BOUNDS) != 0)) {
16065             if (((old & FOCUSABLE) == FOCUSABLE)
16066                     && ((privateFlags & PFLAG_FOCUSED) != 0)) {
16067                 /* Give up focus if we are no longer focusable */
16068                 clearFocus();
16069                 if (mParent instanceof ViewGroup) {
16070                     ((ViewGroup) mParent).clearFocusedInCluster();
16071                 }
16072             } else if (((old & FOCUSABLE) == NOT_FOCUSABLE)
16073                     && ((privateFlags & PFLAG_FOCUSED) == 0)) {
16074                 /*
16075                  * Tell the view system that we are now available to take focus
16076                  * if no one else already has it.
16077                  */
16078                 if (mParent != null) {
16079                     ViewRootImpl viewRootImpl = getViewRootImpl();
16080                     if (!sAutoFocusableOffUIThreadWontNotifyParents
16081                             || focusableChangedByAuto == 0
16082                             || viewRootImpl == null
16083                             || viewRootImpl.mThread == Thread.currentThread()) {
16084                         shouldNotifyFocusableAvailable = canTakeFocus();
16085                     }
16086                 }
16087             }
16088         }
16089 
16090         final int newVisibility = flags & VISIBILITY_MASK;
16091         if (newVisibility == VISIBLE) {
16092             if ((changed & VISIBILITY_MASK) != 0) {
16093                 /*
16094                  * If this view is becoming visible, invalidate it in case it changed while
16095                  * it was not visible. Marking it drawn ensures that the invalidation will
16096                  * go through.
16097                  */
16098                 mPrivateFlags |= PFLAG_DRAWN;
16099                 invalidate(true);
16100 
16101                 needGlobalAttributesUpdate(true);
16102 
16103                 // a view becoming visible is worth notifying the parent about in case nothing has
16104                 // focus. Even if this specific view isn't focusable, it may contain something that
16105                 // is, so let the root view try to give this focus if nothing else does.
16106                 shouldNotifyFocusableAvailable = hasSize();
16107             }
16108         }
16109 
16110         if ((changed & ENABLED_MASK) != 0) {
16111             if ((mViewFlags & ENABLED_MASK) == ENABLED) {
16112                 // a view becoming enabled should notify the parent as long as the view is also
16113                 // visible and the parent wasn't already notified by becoming visible during this
16114                 // setFlags invocation.
16115                 shouldNotifyFocusableAvailable = canTakeFocus();
16116             } else {
16117                 if (isFocused()) clearFocus();
16118             }
16119         }
16120 
16121         if (shouldNotifyFocusableAvailable && mParent != null) {
16122             mParent.focusableViewAvailable(this);
16123         }
16124 
16125         /* Check if the GONE bit has changed */
16126         if ((changed & GONE) != 0) {
16127             needGlobalAttributesUpdate(false);
16128             requestLayout();
16129 
16130             if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
16131                 if (hasFocus()) {
16132                     clearFocus();
16133                     if (mParent instanceof ViewGroup) {
16134                         ((ViewGroup) mParent).clearFocusedInCluster();
16135                     }
16136                 }
16137                 clearAccessibilityFocus();
16138                 destroyDrawingCache();
16139                 if (mParent instanceof View) {
16140                     // GONE views noop invalidation, so invalidate the parent
16141                     ((View) mParent).invalidate(true);
16142                 }
16143                 // Mark the view drawn to ensure that it gets invalidated properly the next
16144                 // time it is visible and gets invalidated
16145                 mPrivateFlags |= PFLAG_DRAWN;
16146             }
16147             if (mAttachInfo != null) {
16148                 mAttachInfo.mViewVisibilityChanged = true;
16149             }
16150         }
16151 
16152         /* Check if the VISIBLE bit has changed */
16153         if ((changed & INVISIBLE) != 0) {
16154             needGlobalAttributesUpdate(false);
16155             /*
16156              * If this view is becoming invisible, set the DRAWN flag so that
16157              * the next invalidate() will not be skipped.
16158              */
16159             mPrivateFlags |= PFLAG_DRAWN;
16160 
16161             if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
16162                 // root view becoming invisible shouldn't clear focus and accessibility focus
16163                 if (getRootView() != this) {
16164                     if (hasFocus()) {
16165                         clearFocus();
16166                         if (mParent instanceof ViewGroup) {
16167                             ((ViewGroup) mParent).clearFocusedInCluster();
16168                         }
16169                     }
16170                     clearAccessibilityFocus();
16171                 }
16172             }
16173             if (mAttachInfo != null) {
16174                 mAttachInfo.mViewVisibilityChanged = true;
16175             }
16176         }
16177 
16178         if ((changed & VISIBILITY_MASK) != 0) {
16179             // If the view is invisible, cleanup its display list to free up resources
16180             if (newVisibility != VISIBLE && mAttachInfo != null) {
16181                 cleanupDraw();
16182             }
16183 
16184             if (mParent instanceof ViewGroup) {
16185                 ViewGroup parent = (ViewGroup) mParent;
16186                 parent.onChildVisibilityChanged(this, (changed & VISIBILITY_MASK),
16187                         newVisibility);
16188                 parent.invalidate(true);
16189             } else if (mParent != null) {
16190                 mParent.invalidateChild(this, null);
16191             }
16192 
16193             if (mAttachInfo != null) {
16194                 dispatchVisibilityChanged(this, newVisibility);
16195 
16196                 // Aggregated visibility changes are dispatched to attached views
16197                 // in visible windows where the parent is currently shown/drawn
16198                 // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
16199                 // discounting clipping or overlapping. This makes it a good place
16200                 // to change animation states.
16201                 if (mParent != null && getWindowVisibility() == VISIBLE &&
16202                         ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
16203                     dispatchVisibilityAggregated(newVisibility == VISIBLE);
16204                 }
16205                 notifySubtreeAccessibilityStateChangedIfNeeded();
16206             }
16207         }
16208 
16209         if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
16210             destroyDrawingCache();
16211         }
16212 
16213         if ((changed & DRAWING_CACHE_ENABLED) != 0) {
16214             destroyDrawingCache();
16215             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
16216             invalidateParentCaches();
16217         }
16218 
16219         if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
16220             destroyDrawingCache();
16221             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
16222         }
16223 
16224         if ((changed & DRAW_MASK) != 0) {
16225             if ((mViewFlags & WILL_NOT_DRAW) != 0) {
16226                 if (mBackground != null
16227                         || mDefaultFocusHighlight != null
16228                         || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
16229                     mPrivateFlags &= ~PFLAG_SKIP_DRAW;
16230                 } else {
16231                     mPrivateFlags |= PFLAG_SKIP_DRAW;
16232                 }
16233             } else {
16234                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
16235             }
16236             requestLayout();
16237             invalidate(true);
16238         }
16239 
16240         if ((changed & KEEP_SCREEN_ON) != 0) {
16241             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
16242                 mParent.recomputeViewAttributes(this);
16243             }
16244         }
16245 
16246         if (accessibilityEnabled) {
16247             // If we're an accessibility pane and the visibility changed, we already have sent
16248             // a state change, so we really don't need to report other changes.
16249             if (isAccessibilityPane()) {
16250                 changed &= ~VISIBILITY_MASK;
16251             }
16252             if ((changed & FOCUSABLE) != 0 || (changed & VISIBILITY_MASK) != 0
16253                     || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
16254                     || (changed & CONTEXT_CLICKABLE) != 0) {
16255                 if (oldIncludeForAccessibility != includeForAccessibility()) {
16256                     notifySubtreeAccessibilityStateChangedIfNeeded();
16257                 } else {
16258                     notifyViewAccessibilityStateChangedIfNeeded(
16259                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
16260                 }
16261             } else if ((changed & ENABLED_MASK) != 0) {
16262                 notifyViewAccessibilityStateChangedIfNeeded(
16263                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
16264             }
16265         }
16266     }
16267 
16268     /**
16269      * Change the view's z order in the tree, so it's on top of other sibling
16270      * views. This ordering change may affect layout, if the parent container
16271      * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
16272      * to {@link android.os.Build.VERSION_CODES#KITKAT} this
16273      * method should be followed by calls to {@link #requestLayout()} and
16274      * {@link View#invalidate()} on the view's parent to force the parent to redraw
16275      * with the new child ordering.
16276      *
16277      * @see ViewGroup#bringChildToFront(View)
16278      */
16279     public void bringToFront() {
16280         if (mParent != null) {
16281             mParent.bringChildToFront(this);
16282         }
16283     }
16284 
16285     /**
16286      * This is called in response to an internal scroll in this view (i.e., the
16287      * view scrolled its own contents). This is typically as a result of
16288      * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
16289      * called.
16290      *
16291      * @param l Current horizontal scroll origin.
16292      * @param t Current vertical scroll origin.
16293      * @param oldl Previous horizontal scroll origin.
16294      * @param oldt Previous vertical scroll origin.
16295      */
16296     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
16297         notifySubtreeAccessibilityStateChangedIfNeeded();
16298         postSendViewScrolledAccessibilityEventCallback(l - oldl, t - oldt);
16299 
16300         mBackgroundSizeChanged = true;
16301         mDefaultFocusHighlightSizeChanged = true;
16302         if (mForegroundInfo != null) {
16303             mForegroundInfo.mBoundsChanged = true;
16304         }
16305 
16306         final AttachInfo ai = mAttachInfo;
16307         if (ai != null) {
16308             ai.mViewScrollChanged = true;
16309         }
16310 
16311         if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
16312             mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
16313         }
16314     }
16315 
16316     /**
16317      * Interface definition for a callback to be invoked when the scroll
16318      * X or Y positions of a view change.
16319      * <p>
16320      * <b>Note:</b> Some views handle scrolling independently from View and may
16321      * have their own separate listeners for scroll-type events. For example,
16322      * {@link android.widget.ListView ListView} allows clients to register an
16323      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
16324      * to listen for changes in list scroll position.
16325      *
16326      * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
16327      */
16328     public interface OnScrollChangeListener {
16329         /**
16330          * Called when the scroll position of a view changes.
16331          *
16332          * @param v The view whose scroll position has changed.
16333          * @param scrollX Current horizontal scroll origin.
16334          * @param scrollY Current vertical scroll origin.
16335          * @param oldScrollX Previous horizontal scroll origin.
16336          * @param oldScrollY Previous vertical scroll origin.
16337          */
16338         void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
16339     }
16340 
16341     /**
16342      * Interface definition for a callback to be invoked when the layout bounds of a view
16343      * changes due to layout processing.
16344      */
16345     public interface OnLayoutChangeListener {
16346         /**
16347          * Called when the layout bounds of a view changes due to layout processing.
16348          *
16349          * @param v The view whose bounds have changed.
16350          * @param left The new value of the view's left property.
16351          * @param top The new value of the view's top property.
16352          * @param right The new value of the view's right property.
16353          * @param bottom The new value of the view's bottom property.
16354          * @param oldLeft The previous value of the view's left property.
16355          * @param oldTop The previous value of the view's top property.
16356          * @param oldRight The previous value of the view's right property.
16357          * @param oldBottom The previous value of the view's bottom property.
16358          */
16359         void onLayoutChange(View v, int left, int top, int right, int bottom,
16360             int oldLeft, int oldTop, int oldRight, int oldBottom);
16361     }
16362 
16363     /**
16364      * This is called during layout when the size of this view has changed. If
16365      * you were just added to the view hierarchy, you're called with the old
16366      * values of 0.
16367      *
16368      * @param w Current width of this view.
16369      * @param h Current height of this view.
16370      * @param oldw Old width of this view.
16371      * @param oldh Old height of this view.
16372      */
16373     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
16374     }
16375 
16376     /**
16377      * Called by draw to draw the child views. This may be overridden
16378      * by derived classes to gain control just before its children are drawn
16379      * (but after its own view has been drawn).
16380      * @param canvas the canvas on which to draw the view
16381      */
16382     protected void dispatchDraw(Canvas canvas) {
16383 
16384     }
16385 
16386     /**
16387      * Gets the parent of this view. Note that the parent is a
16388      * ViewParent and not necessarily a View.
16389      *
16390      * @return Parent of this view.
16391      */
16392     public final ViewParent getParent() {
16393         return mParent;
16394     }
16395 
16396     /**
16397      * Set the horizontal scrolled position of your view. This will cause a call to
16398      * {@link #onScrollChanged(int, int, int, int)} and the view will be
16399      * invalidated.
16400      * @param value the x position to scroll to
16401      */
16402     public void setScrollX(int value) {
16403         scrollTo(value, mScrollY);
16404     }
16405 
16406     /**
16407      * Set the vertical scrolled position of your view. This will cause a call to
16408      * {@link #onScrollChanged(int, int, int, int)} and the view will be
16409      * invalidated.
16410      * @param value the y position to scroll to
16411      */
16412     public void setScrollY(int value) {
16413         scrollTo(mScrollX, value);
16414     }
16415 
16416     /**
16417      * Return the scrolled left position of this view. This is the left edge of
16418      * the displayed part of your view. You do not need to draw any pixels
16419      * farther left, since those are outside of the frame of your view on
16420      * screen.
16421      *
16422      * @return The left edge of the displayed part of your view, in pixels.
16423      */
16424     @InspectableProperty
16425     public final int getScrollX() {
16426         return mScrollX;
16427     }
16428 
16429     /**
16430      * Return the scrolled top position of this view. This is the top edge of
16431      * the displayed part of your view. You do not need to draw any pixels above
16432      * it, since those are outside of the frame of your view on screen.
16433      *
16434      * @return The top edge of the displayed part of your view, in pixels.
16435      */
16436     @InspectableProperty
16437     public final int getScrollY() {
16438         return mScrollY;
16439     }
16440 
16441     /**
16442      * Return the width of your view.
16443      *
16444      * @return The width of your view, in pixels.
16445      */
16446     @ViewDebug.ExportedProperty(category = "layout")
16447     public final int getWidth() {
16448         return mRight - mLeft;
16449     }
16450 
16451     /**
16452      * Return the height of your view.
16453      *
16454      * @return The height of your view, in pixels.
16455      */
16456     @ViewDebug.ExportedProperty(category = "layout")
16457     public final int getHeight() {
16458         return mBottom - mTop;
16459     }
16460 
16461     /**
16462      * Return the visible drawing bounds of your view. Fills in the output
16463      * rectangle with the values from getScrollX(), getScrollY(),
16464      * getWidth(), and getHeight(). These bounds do not account for any
16465      * transformation properties currently set on the view, such as
16466      * {@link #setScaleX(float)} or {@link #setRotation(float)}.
16467      *
16468      * @param outRect The (scrolled) drawing bounds of the view.
16469      */
16470     public void getDrawingRect(Rect outRect) {
16471         outRect.left = mScrollX;
16472         outRect.top = mScrollY;
16473         outRect.right = mScrollX + (mRight - mLeft);
16474         outRect.bottom = mScrollY + (mBottom - mTop);
16475     }
16476 
16477     /**
16478      * Like {@link #getMeasuredWidthAndState()}, but only returns the
16479      * raw width component (that is the result is masked by
16480      * {@link #MEASURED_SIZE_MASK}).
16481      *
16482      * @return The raw measured width of this view.
16483      */
16484     public final int getMeasuredWidth() {
16485         return mMeasuredWidth & MEASURED_SIZE_MASK;
16486     }
16487 
16488     /**
16489      * Return the full width measurement information for this view as computed
16490      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
16491      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
16492      * This should be used during measurement and layout calculations only. Use
16493      * {@link #getWidth()} to see how wide a view is after layout.
16494      *
16495      * @return The measured width of this view as a bit mask.
16496      */
16497     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
16498             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
16499                     name = "MEASURED_STATE_TOO_SMALL"),
16500     })
16501     public final int getMeasuredWidthAndState() {
16502         return mMeasuredWidth;
16503     }
16504 
16505     /**
16506      * Like {@link #getMeasuredHeightAndState()}, but only returns the
16507      * raw height component (that is the result is masked by
16508      * {@link #MEASURED_SIZE_MASK}).
16509      *
16510      * @return The raw measured height of this view.
16511      */
16512     public final int getMeasuredHeight() {
16513         return mMeasuredHeight & MEASURED_SIZE_MASK;
16514     }
16515 
16516     /**
16517      * Return the full height measurement information for this view as computed
16518      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
16519      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
16520      * This should be used during measurement and layout calculations only. Use
16521      * {@link #getHeight()} to see how high a view is after layout.
16522      *
16523      * @return The measured height of this view as a bit mask.
16524      */
16525     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
16526             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
16527                     name = "MEASURED_STATE_TOO_SMALL"),
16528     })
16529     public final int getMeasuredHeightAndState() {
16530         return mMeasuredHeight;
16531     }
16532 
16533     /**
16534      * Return only the state bits of {@link #getMeasuredWidthAndState()}
16535      * and {@link #getMeasuredHeightAndState()}, combined into one integer.
16536      * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
16537      * and the height component is at the shifted bits
16538      * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
16539      */
16540     public final int getMeasuredState() {
16541         return (mMeasuredWidth&MEASURED_STATE_MASK)
16542                 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
16543                         & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
16544     }
16545 
16546     /**
16547      * The transform matrix of this view, which is calculated based on the current
16548      * rotation, scale, and pivot properties.
16549      *
16550      * @see #getRotation()
16551      * @see #getScaleX()
16552      * @see #getScaleY()
16553      * @see #getPivotX()
16554      * @see #getPivotY()
16555      * @return The current transform matrix for the view
16556      */
16557     public Matrix getMatrix() {
16558         ensureTransformationInfo();
16559         final Matrix matrix = mTransformationInfo.mMatrix;
16560         mRenderNode.getMatrix(matrix);
16561         return matrix;
16562     }
16563 
16564     /**
16565      * Returns true if the transform matrix is the identity matrix.
16566      * Recomputes the matrix if necessary.
16567      *
16568      * @return True if the transform matrix is the identity matrix, false otherwise.
16569      * @hide
16570      */
16571     @UnsupportedAppUsage
16572     public final boolean hasIdentityMatrix() {
16573         return mRenderNode.hasIdentityMatrix();
16574     }
16575 
16576     @UnsupportedAppUsage
16577     void ensureTransformationInfo() {
16578         if (mTransformationInfo == null) {
16579             mTransformationInfo = new TransformationInfo();
16580         }
16581     }
16582 
16583     /**
16584      * Utility method to retrieve the inverse of the current mMatrix property.
16585      * We cache the matrix to avoid recalculating it when transform properties
16586      * have not changed.
16587      *
16588      * @return The inverse of the current matrix of this view.
16589      * @hide
16590      */
16591     @UnsupportedAppUsage
16592     public final Matrix getInverseMatrix() {
16593         ensureTransformationInfo();
16594         if (mTransformationInfo.mInverseMatrix == null) {
16595             mTransformationInfo.mInverseMatrix = new Matrix();
16596         }
16597         final Matrix matrix = mTransformationInfo.mInverseMatrix;
16598         mRenderNode.getInverseMatrix(matrix);
16599         return matrix;
16600     }
16601 
16602     /**
16603      * Gets the distance along the Z axis from the camera to this view.
16604      *
16605      * @see #setCameraDistance(float)
16606      *
16607      * @return The distance along the Z axis.
16608      */
16609     public float getCameraDistance() {
16610         final float dpi = mResources.getDisplayMetrics().densityDpi;
16611         return mRenderNode.getCameraDistance() * dpi;
16612     }
16613 
16614     /**
16615      * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
16616      * views are drawn) from the camera to this view. The camera's distance
16617      * affects 3D transformations, for instance rotations around the X and Y
16618      * axis. If the rotationX or rotationY properties are changed and this view is
16619      * large (more than half the size of the screen), it is recommended to always
16620      * use a camera distance that's greater than the height (X axis rotation) or
16621      * the width (Y axis rotation) of this view.</p>
16622      *
16623      * <p>The distance of the camera from the view plane can have an affect on the
16624      * perspective distortion of the view when it is rotated around the x or y axis.
16625      * For example, a large distance will result in a large viewing angle, and there
16626      * will not be much perspective distortion of the view as it rotates. A short
16627      * distance may cause much more perspective distortion upon rotation, and can
16628      * also result in some drawing artifacts if the rotated view ends up partially
16629      * behind the camera (which is why the recommendation is to use a distance at
16630      * least as far as the size of the view, if the view is to be rotated.)</p>
16631      *
16632      * <p>The distance is expressed in "depth pixels." The default distance depends
16633      * on the screen density. For instance, on a medium density display, the
16634      * default distance is 1280. On a high density display, the default distance
16635      * is 1920.</p>
16636      *
16637      * <p>If you want to specify a distance that leads to visually consistent
16638      * results across various densities, use the following formula:</p>
16639      * <pre>
16640      * float scale = context.getResources().getDisplayMetrics().density;
16641      * view.setCameraDistance(distance * scale);
16642      * </pre>
16643      *
16644      * <p>The density scale factor of a high density display is 1.5,
16645      * and 1920 = 1280 * 1.5.</p>
16646      *
16647      * @param distance The distance in "depth pixels", if negative the opposite
16648      *        value is used
16649      *
16650      * @see #setRotationX(float)
16651      * @see #setRotationY(float)
16652      */
16653     public void setCameraDistance(float distance) {
16654         final float dpi = mResources.getDisplayMetrics().densityDpi;
16655 
16656         invalidateViewProperty(true, false);
16657         mRenderNode.setCameraDistance(Math.abs(distance) / dpi);
16658         invalidateViewProperty(false, false);
16659 
16660         invalidateParentIfNeededAndWasQuickRejected();
16661     }
16662 
16663     /**
16664      * The degrees that the view is rotated around the pivot point.
16665      *
16666      * @see #setRotation(float)
16667      * @see #getPivotX()
16668      * @see #getPivotY()
16669      *
16670      * @return The degrees of rotation.
16671      */
16672     @ViewDebug.ExportedProperty(category = "drawing")
16673     @InspectableProperty
16674     public float getRotation() {
16675         return mRenderNode.getRotationZ();
16676     }
16677 
16678     /**
16679      * Sets the degrees that the view is rotated around the pivot point. Increasing values
16680      * result in clockwise rotation.
16681      *
16682      * @param rotation The degrees of rotation.
16683      *
16684      * @see #getRotation()
16685      * @see #getPivotX()
16686      * @see #getPivotY()
16687      * @see #setRotationX(float)
16688      * @see #setRotationY(float)
16689      *
16690      * @attr ref android.R.styleable#View_rotation
16691      */
16692     public void setRotation(float rotation) {
16693         if (rotation != getRotation()) {
16694             // Double-invalidation is necessary to capture view's old and new areas
16695             invalidateViewProperty(true, false);
16696             mRenderNode.setRotationZ(rotation);
16697             invalidateViewProperty(false, true);
16698 
16699             invalidateParentIfNeededAndWasQuickRejected();
16700             notifySubtreeAccessibilityStateChangedIfNeeded();
16701         }
16702     }
16703 
16704     /**
16705      * The degrees that the view is rotated around the vertical axis through the pivot point.
16706      *
16707      * @see #getPivotX()
16708      * @see #getPivotY()
16709      * @see #setRotationY(float)
16710      *
16711      * @return The degrees of Y rotation.
16712      */
16713     @ViewDebug.ExportedProperty(category = "drawing")
16714     @InspectableProperty
16715     public float getRotationY() {
16716         return mRenderNode.getRotationY();
16717     }
16718 
16719     /**
16720      * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
16721      * Increasing values result in counter-clockwise rotation from the viewpoint of looking
16722      * down the y axis.
16723      *
16724      * When rotating large views, it is recommended to adjust the camera distance
16725      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
16726      *
16727      * @param rotationY The degrees of Y rotation.
16728      *
16729      * @see #getRotationY()
16730      * @see #getPivotX()
16731      * @see #getPivotY()
16732      * @see #setRotation(float)
16733      * @see #setRotationX(float)
16734      * @see #setCameraDistance(float)
16735      *
16736      * @attr ref android.R.styleable#View_rotationY
16737      */
16738     public void setRotationY(float rotationY) {
16739         if (rotationY != getRotationY()) {
16740             invalidateViewProperty(true, false);
16741             mRenderNode.setRotationY(rotationY);
16742             invalidateViewProperty(false, true);
16743 
16744             invalidateParentIfNeededAndWasQuickRejected();
16745             notifySubtreeAccessibilityStateChangedIfNeeded();
16746         }
16747     }
16748 
16749     /**
16750      * The degrees that the view is rotated around the horizontal axis through the pivot point.
16751      *
16752      * @see #getPivotX()
16753      * @see #getPivotY()
16754      * @see #setRotationX(float)
16755      *
16756      * @return The degrees of X rotation.
16757      */
16758     @ViewDebug.ExportedProperty(category = "drawing")
16759     @InspectableProperty
16760     public float getRotationX() {
16761         return mRenderNode.getRotationX();
16762     }
16763 
16764     /**
16765      * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
16766      * Increasing values result in clockwise rotation from the viewpoint of looking down the
16767      * x axis.
16768      *
16769      * When rotating large views, it is recommended to adjust the camera distance
16770      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
16771      *
16772      * @param rotationX The degrees of X rotation.
16773      *
16774      * @see #getRotationX()
16775      * @see #getPivotX()
16776      * @see #getPivotY()
16777      * @see #setRotation(float)
16778      * @see #setRotationY(float)
16779      * @see #setCameraDistance(float)
16780      *
16781      * @attr ref android.R.styleable#View_rotationX
16782      */
16783     public void setRotationX(float rotationX) {
16784         if (rotationX != getRotationX()) {
16785             invalidateViewProperty(true, false);
16786             mRenderNode.setRotationX(rotationX);
16787             invalidateViewProperty(false, true);
16788 
16789             invalidateParentIfNeededAndWasQuickRejected();
16790             notifySubtreeAccessibilityStateChangedIfNeeded();
16791         }
16792     }
16793 
16794     /**
16795      * The amount that the view is scaled in x around the pivot point, as a proportion of
16796      * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
16797      *
16798      * <p>By default, this is 1.0f.
16799      *
16800      * @see #getPivotX()
16801      * @see #getPivotY()
16802      * @return The scaling factor.
16803      */
16804     @ViewDebug.ExportedProperty(category = "drawing")
16805     @InspectableProperty
16806     public float getScaleX() {
16807         return mRenderNode.getScaleX();
16808     }
16809 
16810     /**
16811      * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
16812      * the view's unscaled width. A value of 1 means that no scaling is applied.
16813      *
16814      * @param scaleX The scaling factor.
16815      * @see #getPivotX()
16816      * @see #getPivotY()
16817      *
16818      * @attr ref android.R.styleable#View_scaleX
16819      */
16820     public void setScaleX(float scaleX) {
16821         if (scaleX != getScaleX()) {
16822             scaleX = sanitizeFloatPropertyValue(scaleX, "scaleX");
16823             invalidateViewProperty(true, false);
16824             mRenderNode.setScaleX(scaleX);
16825             invalidateViewProperty(false, true);
16826 
16827             invalidateParentIfNeededAndWasQuickRejected();
16828             notifySubtreeAccessibilityStateChangedIfNeeded();
16829         }
16830     }
16831 
16832     /**
16833      * The amount that the view is scaled in y around the pivot point, as a proportion of
16834      * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
16835      *
16836      * <p>By default, this is 1.0f.
16837      *
16838      * @see #getPivotX()
16839      * @see #getPivotY()
16840      * @return The scaling factor.
16841      */
16842     @ViewDebug.ExportedProperty(category = "drawing")
16843     @InspectableProperty
16844     public float getScaleY() {
16845         return mRenderNode.getScaleY();
16846     }
16847 
16848     /**
16849      * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
16850      * the view's unscaled width. A value of 1 means that no scaling is applied.
16851      *
16852      * @param scaleY The scaling factor.
16853      * @see #getPivotX()
16854      * @see #getPivotY()
16855      *
16856      * @attr ref android.R.styleable#View_scaleY
16857      */
16858     public void setScaleY(float scaleY) {
16859         if (scaleY != getScaleY()) {
16860             scaleY = sanitizeFloatPropertyValue(scaleY, "scaleY");
16861             invalidateViewProperty(true, false);
16862             mRenderNode.setScaleY(scaleY);
16863             invalidateViewProperty(false, true);
16864 
16865             invalidateParentIfNeededAndWasQuickRejected();
16866             notifySubtreeAccessibilityStateChangedIfNeeded();
16867         }
16868     }
16869 
16870     /**
16871      * The x location of the point around which the view is {@link #setRotation(float) rotated}
16872      * and {@link #setScaleX(float) scaled}.
16873      *
16874      * @see #getRotation()
16875      * @see #getScaleX()
16876      * @see #getScaleY()
16877      * @see #getPivotY()
16878      * @return The x location of the pivot point.
16879      *
16880      * @attr ref android.R.styleable#View_transformPivotX
16881      */
16882     @ViewDebug.ExportedProperty(category = "drawing")
16883     @InspectableProperty(name = "transformPivotX")
16884     public float getPivotX() {
16885         return mRenderNode.getPivotX();
16886     }
16887 
16888     /**
16889      * Sets the x location of the point around which the view is
16890      * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
16891      * By default, the pivot point is centered on the object.
16892      * Setting this property disables this behavior and causes the view to use only the
16893      * explicitly set pivotX and pivotY values.
16894      *
16895      * @param pivotX The x location of the pivot point.
16896      * @see #getRotation()
16897      * @see #getScaleX()
16898      * @see #getScaleY()
16899      * @see #getPivotY()
16900      *
16901      * @attr ref android.R.styleable#View_transformPivotX
16902      */
16903     public void setPivotX(float pivotX) {
16904         if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
16905             invalidateViewProperty(true, false);
16906             mRenderNode.setPivotX(pivotX);
16907             invalidateViewProperty(false, true);
16908 
16909             invalidateParentIfNeededAndWasQuickRejected();
16910         }
16911     }
16912 
16913     /**
16914      * The y location of the point around which the view is {@link #setRotation(float) rotated}
16915      * and {@link #setScaleY(float) scaled}.
16916      *
16917      * @see #getRotation()
16918      * @see #getScaleX()
16919      * @see #getScaleY()
16920      * @see #getPivotY()
16921      * @return The y location of the pivot point.
16922      *
16923      * @attr ref android.R.styleable#View_transformPivotY
16924      */
16925     @ViewDebug.ExportedProperty(category = "drawing")
16926     @InspectableProperty(name = "transformPivotY")
16927     public float getPivotY() {
16928         return mRenderNode.getPivotY();
16929     }
16930 
16931     /**
16932      * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
16933      * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
16934      * Setting this property disables this behavior and causes the view to use only the
16935      * explicitly set pivotX and pivotY values.
16936      *
16937      * @param pivotY The y location of the pivot point.
16938      * @see #getRotation()
16939      * @see #getScaleX()
16940      * @see #getScaleY()
16941      * @see #getPivotY()
16942      *
16943      * @attr ref android.R.styleable#View_transformPivotY
16944      */
16945     public void setPivotY(float pivotY) {
16946         if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
16947             invalidateViewProperty(true, false);
16948             mRenderNode.setPivotY(pivotY);
16949             invalidateViewProperty(false, true);
16950 
16951             invalidateParentIfNeededAndWasQuickRejected();
16952         }
16953     }
16954 
16955     /**
16956      * Returns whether or not a pivot has been set by a call to {@link #setPivotX(float)} or
16957      * {@link #setPivotY(float)}. If no pivot has been set then the pivot will be the center
16958      * of the view.
16959      *
16960      * @return True if a pivot has been set, false if the default pivot is being used
16961      */
16962     public boolean isPivotSet() {
16963         return mRenderNode.isPivotExplicitlySet();
16964     }
16965 
16966     /**
16967      * Clears any pivot previously set by a call to  {@link #setPivotX(float)} or
16968      * {@link #setPivotY(float)}. After calling this {@link #isPivotSet()} will be false
16969      * and the pivot used for rotation will return to default of being centered on the view.
16970      */
16971     public void resetPivot() {
16972         if (mRenderNode.resetPivot()) {
16973             invalidateViewProperty(false, false);
16974         }
16975     }
16976 
16977     /**
16978      * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
16979      * completely transparent and 1 means the view is completely opaque.
16980      *
16981      * <p>By default this is 1.0f.
16982      * @return The opacity of the view.
16983      */
16984     @ViewDebug.ExportedProperty(category = "drawing")
16985     @InspectableProperty
16986     public float getAlpha() {
16987         return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
16988     }
16989 
16990     /**
16991      * Sets the behavior for overlapping rendering for this view (see {@link
16992      * #hasOverlappingRendering()} for more details on this behavior). Calling this method
16993      * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
16994      * providing the value which is then used internally. That is, when {@link
16995      * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
16996      * #hasOverlappingRendering()} is ignored and the value passed into this method is used
16997      * instead.
16998      *
16999      * @param hasOverlappingRendering The value for overlapping rendering to be used internally
17000      * instead of that returned by {@link #hasOverlappingRendering()}.
17001      *
17002      * @attr ref android.R.styleable#View_forceHasOverlappingRendering
17003      */
17004     public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
17005         mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
17006         if (hasOverlappingRendering) {
17007             mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
17008         } else {
17009             mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
17010         }
17011     }
17012 
17013     /**
17014      * Returns the value for overlapping rendering that is used internally. This is either
17015      * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
17016      * the return value of {@link #hasOverlappingRendering()}, otherwise.
17017      *
17018      * @return The value for overlapping rendering being used internally.
17019      */
17020     public final boolean getHasOverlappingRendering() {
17021         return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
17022                 (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
17023                 hasOverlappingRendering();
17024     }
17025 
17026     /**
17027      * Returns whether this View has content which overlaps.
17028      *
17029      * <p>This function, intended to be overridden by specific View types, is an optimization when
17030      * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
17031      * an offscreen buffer and then composited into place, which can be expensive. If the view has
17032      * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
17033      * directly. An example of overlapping rendering is a TextView with a background image, such as
17034      * a Button. An example of non-overlapping rendering is a TextView with no background, or an
17035      * ImageView with only the foreground image. The default implementation returns true; subclasses
17036      * should override if they have cases which can be optimized.</p>
17037      *
17038      * <p><strong>Note:</strong> The return value of this method is ignored if {@link
17039      * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
17040      *
17041      * @return true if the content in this view might overlap, false otherwise.
17042      */
17043     @ViewDebug.ExportedProperty(category = "drawing")
17044     public boolean hasOverlappingRendering() {
17045         return true;
17046     }
17047 
17048     /**
17049      * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
17050      * completely transparent and 1 means the view is completely opaque.
17051      *
17052      * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
17053      * can have significant performance implications, especially for large views. It is best to use
17054      * the alpha property sparingly and transiently, as in the case of fading animations.</p>
17055      *
17056      * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
17057      * strongly recommended for performance reasons to either override
17058      * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
17059      * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
17060      * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
17061      * the default path for rendering an unlayered View with alpha could add multiple milliseconds
17062      * of rendering cost, even for simple or small views. Starting with
17063      * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
17064      * applied to the view at the rendering level.</p>
17065      *
17066      * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
17067      * responsible for applying the opacity itself.</p>
17068      *
17069      * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
17070      * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
17071      * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
17072      * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
17073      *
17074      * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
17075      * value will clip a View to its bounds, unless the View returns <code>false</code> from
17076      * {@link #hasOverlappingRendering}.</p>
17077      *
17078      * @param alpha The opacity of the view.
17079      *
17080      * @see #hasOverlappingRendering()
17081      * @see #setLayerType(int, android.graphics.Paint)
17082      *
17083      * @attr ref android.R.styleable#View_alpha
17084      */
17085     public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
17086         ensureTransformationInfo();
17087         if (mTransformationInfo.mAlpha != alpha) {
17088             setAlphaInternal(alpha);
17089             if (onSetAlpha((int) (alpha * 255))) {
17090                 mPrivateFlags |= PFLAG_ALPHA_SET;
17091                 // subclass is handling alpha - don't optimize rendering cache invalidation
17092                 invalidateParentCaches();
17093                 invalidate(true);
17094             } else {
17095                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
17096                 invalidateViewProperty(true, false);
17097                 mRenderNode.setAlpha(getFinalAlpha());
17098             }
17099         }
17100     }
17101 
17102     /**
17103      * Faster version of setAlpha() which performs the same steps except there are
17104      * no calls to invalidate(). The caller of this function should perform proper invalidation
17105      * on the parent and this object. The return value indicates whether the subclass handles
17106      * alpha (the return value for onSetAlpha()).
17107      *
17108      * @param alpha The new value for the alpha property
17109      * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
17110      *         the new value for the alpha property is different from the old value
17111      */
17112     @UnsupportedAppUsage(maxTargetSdk  = Build.VERSION_CODES.P, trackingBug = 123768435)
17113     boolean setAlphaNoInvalidation(float alpha) {
17114         ensureTransformationInfo();
17115         if (mTransformationInfo.mAlpha != alpha) {
17116             setAlphaInternal(alpha);
17117             boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
17118             if (subclassHandlesAlpha) {
17119                 mPrivateFlags |= PFLAG_ALPHA_SET;
17120                 return true;
17121             } else {
17122                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
17123                 mRenderNode.setAlpha(getFinalAlpha());
17124             }
17125         }
17126         return false;
17127     }
17128 
17129     void setAlphaInternal(float alpha) {
17130         float oldAlpha = mTransformationInfo.mAlpha;
17131         mTransformationInfo.mAlpha = alpha;
17132         // Report visibility changes, which can affect children, to accessibility
17133         if ((alpha == 0) ^ (oldAlpha == 0)) {
17134             notifySubtreeAccessibilityStateChangedIfNeeded();
17135         }
17136     }
17137 
17138     /**
17139      * This property is intended only for use by the Fade transition, which animates it
17140      * to produce a visual translucency that does not side-effect (or get affected by)
17141      * the real alpha property. This value is composited with the other alpha value
17142      * (and the AlphaAnimation value, when that is present) to produce a final visual
17143      * translucency result, which is what is passed into the DisplayList.
17144      */
17145     public void setTransitionAlpha(float alpha) {
17146         ensureTransformationInfo();
17147         if (mTransformationInfo.mTransitionAlpha != alpha) {
17148             mTransformationInfo.mTransitionAlpha = alpha;
17149             mPrivateFlags &= ~PFLAG_ALPHA_SET;
17150             invalidateViewProperty(true, false);
17151             mRenderNode.setAlpha(getFinalAlpha());
17152         }
17153     }
17154 
17155     /**
17156      * Calculates the visual alpha of this view, which is a combination of the actual
17157      * alpha value and the transitionAlpha value (if set).
17158      */
17159     private float getFinalAlpha() {
17160         if (mTransformationInfo != null) {
17161             return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
17162         }
17163         return 1;
17164     }
17165 
17166     /**
17167      * This property is intended only for use by the Fade transition, which animates
17168      * it to produce a visual translucency that does not side-effect (or get affected
17169      * by) the real alpha property. This value is composited with the other alpha
17170      * value (and the AlphaAnimation value, when that is present) to produce a final
17171      * visual translucency result, which is what is passed into the DisplayList.
17172      */
17173     @ViewDebug.ExportedProperty(category = "drawing")
17174     public float getTransitionAlpha() {
17175         return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
17176     }
17177 
17178     /**
17179      * Sets whether or not to allow force dark to apply to this view.
17180      *
17181      * Setting this to false will disable the auto-dark feature on everything this view
17182      * draws, including any descendants.
17183      *
17184      * Setting this to true will allow this view to be automatically made dark, however
17185      * a value of 'true' will not override any 'false' value in its parent chain nor will
17186      * it prevent any 'false' in any of its children.
17187      *
17188      * The default behavior of force dark is also influenced by the Theme's
17189      * {@link android.R.styleable#Theme_isLightTheme isLightTheme} attribute.
17190      * If a theme is isLightTheme="false", then force dark is globally disabled for that theme.
17191      *
17192      * @param allow Whether or not to allow force dark.
17193      */
17194     public void setForceDarkAllowed(boolean allow) {
17195         if (mRenderNode.setForceDarkAllowed(allow)) {
17196             // Currently toggling force-dark requires a new display list push to apply
17197             // TODO: Make it not clobber the display list so this is just a damageSelf() instead
17198             invalidate();
17199         }
17200     }
17201 
17202     /**
17203      * See {@link #setForceDarkAllowed(boolean)}
17204      *
17205      * @return true if force dark is allowed (default), false if it is disabled
17206      */
17207     @ViewDebug.ExportedProperty(category = "drawing")
17208     @InspectableProperty
17209     public boolean isForceDarkAllowed() {
17210         return mRenderNode.isForceDarkAllowed();
17211     }
17212 
17213     /**
17214      * Top position of this view relative to its parent.
17215      *
17216      * @return The top of this view, in pixels.
17217      */
17218     @ViewDebug.CapturedViewProperty
17219     public final int getTop() {
17220         return mTop;
17221     }
17222 
17223     /**
17224      * Sets the top position of this view relative to its parent. This method is meant to be called
17225      * by the layout system and should not generally be called otherwise, because the property
17226      * may be changed at any time by the layout.
17227      *
17228      * @param top The top of this view, in pixels.
17229      */
17230     public final void setTop(int top) {
17231         if (top != mTop) {
17232             final boolean matrixIsIdentity = hasIdentityMatrix();
17233             if (matrixIsIdentity) {
17234                 if (mAttachInfo != null) {
17235                     int minTop;
17236                     int yLoc;
17237                     if (top < mTop) {
17238                         minTop = top;
17239                         yLoc = top - mTop;
17240                     } else {
17241                         minTop = mTop;
17242                         yLoc = 0;
17243                     }
17244                     invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
17245                 }
17246             } else {
17247                 // Double-invalidation is necessary to capture view's old and new areas
17248                 invalidate(true);
17249             }
17250 
17251             int width = mRight - mLeft;
17252             int oldHeight = mBottom - mTop;
17253 
17254             mTop = top;
17255             mRenderNode.setTop(mTop);
17256 
17257             sizeChange(width, mBottom - mTop, width, oldHeight);
17258 
17259             if (!matrixIsIdentity) {
17260                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
17261                 invalidate(true);
17262             }
17263             mBackgroundSizeChanged = true;
17264             mDefaultFocusHighlightSizeChanged = true;
17265             if (mForegroundInfo != null) {
17266                 mForegroundInfo.mBoundsChanged = true;
17267             }
17268             invalidateParentIfNeeded();
17269         }
17270     }
17271 
17272     /**
17273      * Bottom position of this view relative to its parent.
17274      *
17275      * @return The bottom of this view, in pixels.
17276      */
17277     @ViewDebug.CapturedViewProperty
17278     public final int getBottom() {
17279         return mBottom;
17280     }
17281 
17282     /**
17283      * True if this view has changed since the last time being drawn.
17284      *
17285      * @return The dirty state of this view.
17286      */
17287     public boolean isDirty() {
17288         return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
17289     }
17290 
17291     /**
17292      * Sets the bottom position of this view relative to its parent. This method is meant to be
17293      * called by the layout system and should not generally be called otherwise, because the
17294      * property may be changed at any time by the layout.
17295      *
17296      * @param bottom The bottom of this view, in pixels.
17297      */
17298     public final void setBottom(int bottom) {
17299         if (bottom != mBottom) {
17300             final boolean matrixIsIdentity = hasIdentityMatrix();
17301             if (matrixIsIdentity) {
17302                 if (mAttachInfo != null) {
17303                     int maxBottom;
17304                     if (bottom < mBottom) {
17305                         maxBottom = mBottom;
17306                     } else {
17307                         maxBottom = bottom;
17308                     }
17309                     invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
17310                 }
17311             } else {
17312                 // Double-invalidation is necessary to capture view's old and new areas
17313                 invalidate(true);
17314             }
17315 
17316             int width = mRight - mLeft;
17317             int oldHeight = mBottom - mTop;
17318 
17319             mBottom = bottom;
17320             mRenderNode.setBottom(mBottom);
17321 
17322             sizeChange(width, mBottom - mTop, width, oldHeight);
17323 
17324             if (!matrixIsIdentity) {
17325                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
17326                 invalidate(true);
17327             }
17328             mBackgroundSizeChanged = true;
17329             mDefaultFocusHighlightSizeChanged = true;
17330             if (mForegroundInfo != null) {
17331                 mForegroundInfo.mBoundsChanged = true;
17332             }
17333             invalidateParentIfNeeded();
17334         }
17335     }
17336 
17337     /**
17338      * Left position of this view relative to its parent.
17339      *
17340      * @return The left edge of this view, in pixels.
17341      */
17342     @ViewDebug.CapturedViewProperty
17343     public final int getLeft() {
17344         return mLeft;
17345     }
17346 
17347     /**
17348      * Sets the left position of this view relative to its parent. This method is meant to be called
17349      * by the layout system and should not generally be called otherwise, because the property
17350      * may be changed at any time by the layout.
17351      *
17352      * @param left The left of this view, in pixels.
17353      */
17354     public final void setLeft(int left) {
17355         if (left != mLeft) {
17356             final boolean matrixIsIdentity = hasIdentityMatrix();
17357             if (matrixIsIdentity) {
17358                 if (mAttachInfo != null) {
17359                     int minLeft;
17360                     int xLoc;
17361                     if (left < mLeft) {
17362                         minLeft = left;
17363                         xLoc = left - mLeft;
17364                     } else {
17365                         minLeft = mLeft;
17366                         xLoc = 0;
17367                     }
17368                     invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
17369                 }
17370             } else {
17371                 // Double-invalidation is necessary to capture view's old and new areas
17372                 invalidate(true);
17373             }
17374 
17375             int oldWidth = mRight - mLeft;
17376             int height = mBottom - mTop;
17377 
17378             mLeft = left;
17379             mRenderNode.setLeft(left);
17380 
17381             sizeChange(mRight - mLeft, height, oldWidth, height);
17382 
17383             if (!matrixIsIdentity) {
17384                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
17385                 invalidate(true);
17386             }
17387             mBackgroundSizeChanged = true;
17388             mDefaultFocusHighlightSizeChanged = true;
17389             if (mForegroundInfo != null) {
17390                 mForegroundInfo.mBoundsChanged = true;
17391             }
17392             invalidateParentIfNeeded();
17393         }
17394     }
17395 
17396     /**
17397      * Right position of this view relative to its parent.
17398      *
17399      * @return The right edge of this view, in pixels.
17400      */
17401     @ViewDebug.CapturedViewProperty
17402     public final int getRight() {
17403         return mRight;
17404     }
17405 
17406     /**
17407      * Sets the right position of this view relative to its parent. This method is meant to be called
17408      * by the layout system and should not generally be called otherwise, because the property
17409      * may be changed at any time by the layout.
17410      *
17411      * @param right The right of this view, in pixels.
17412      */
17413     public final void setRight(int right) {
17414         if (right != mRight) {
17415             final boolean matrixIsIdentity = hasIdentityMatrix();
17416             if (matrixIsIdentity) {
17417                 if (mAttachInfo != null) {
17418                     int maxRight;
17419                     if (right < mRight) {
17420                         maxRight = mRight;
17421                     } else {
17422                         maxRight = right;
17423                     }
17424                     invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
17425                 }
17426             } else {
17427                 // Double-invalidation is necessary to capture view's old and new areas
17428                 invalidate(true);
17429             }
17430 
17431             int oldWidth = mRight - mLeft;
17432             int height = mBottom - mTop;
17433 
17434             mRight = right;
17435             mRenderNode.setRight(mRight);
17436 
17437             sizeChange(mRight - mLeft, height, oldWidth, height);
17438 
17439             if (!matrixIsIdentity) {
17440                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
17441                 invalidate(true);
17442             }
17443             mBackgroundSizeChanged = true;
17444             mDefaultFocusHighlightSizeChanged = true;
17445             if (mForegroundInfo != null) {
17446                 mForegroundInfo.mBoundsChanged = true;
17447             }
17448             invalidateParentIfNeeded();
17449         }
17450     }
17451 
17452     private static float sanitizeFloatPropertyValue(float value, String propertyName) {
17453         return sanitizeFloatPropertyValue(value, propertyName, -Float.MAX_VALUE, Float.MAX_VALUE);
17454     }
17455 
17456     private static float sanitizeFloatPropertyValue(float value, String propertyName,
17457             float min, float max) {
17458         // The expected "nothing bad happened" path
17459         if (value >= min && value <= max) return value;
17460 
17461         if (value < min || value == Float.NEGATIVE_INFINITY) {
17462             if (sThrowOnInvalidFloatProperties) {
17463                 throw new IllegalArgumentException("Cannot set '" + propertyName + "' to "
17464                         + value + ", the value must be >= " + min);
17465             }
17466             return min;
17467         }
17468 
17469         if (value > max || value == Float.POSITIVE_INFINITY) {
17470             if (sThrowOnInvalidFloatProperties) {
17471                 throw new IllegalArgumentException("Cannot set '" + propertyName + "' to "
17472                         + value + ", the value must be <= " + max);
17473             }
17474             return max;
17475         }
17476 
17477         if (Float.isNaN(value)) {
17478             if (sThrowOnInvalidFloatProperties) {
17479                 throw new IllegalArgumentException(
17480                         "Cannot set '" + propertyName + "' to Float.NaN");
17481             }
17482             return 0; // Unclear which direction this NaN went so... 0?
17483         }
17484 
17485         // Shouldn't be possible to reach this.
17486         throw new IllegalStateException("How do you get here?? " + value);
17487     }
17488 
17489     /**
17490      * The visual x position of this view, in pixels. This is equivalent to the
17491      * {@link #setTranslationX(float) translationX} property plus the current
17492      * {@link #getLeft() left} property.
17493      *
17494      * @return The visual x position of this view, in pixels.
17495      */
17496     @ViewDebug.ExportedProperty(category = "drawing")
17497     public float getX() {
17498         return mLeft + getTranslationX();
17499     }
17500 
17501     /**
17502      * Sets the visual x position of this view, in pixels. This is equivalent to setting the
17503      * {@link #setTranslationX(float) translationX} property to be the difference between
17504      * the x value passed in and the current {@link #getLeft() left} property.
17505      *
17506      * @param x The visual x position of this view, in pixels.
17507      */
17508     public void setX(float x) {
17509         setTranslationX(x - mLeft);
17510     }
17511 
17512     /**
17513      * The visual y position of this view, in pixels. This is equivalent to the
17514      * {@link #setTranslationY(float) translationY} property plus the current
17515      * {@link #getTop() top} property.
17516      *
17517      * @return The visual y position of this view, in pixels.
17518      */
17519     @ViewDebug.ExportedProperty(category = "drawing")
17520     public float getY() {
17521         return mTop + getTranslationY();
17522     }
17523 
17524     /**
17525      * Sets the visual y position of this view, in pixels. This is equivalent to setting the
17526      * {@link #setTranslationY(float) translationY} property to be the difference between
17527      * the y value passed in and the current {@link #getTop() top} property.
17528      *
17529      * @param y The visual y position of this view, in pixels.
17530      */
17531     public void setY(float y) {
17532         setTranslationY(y - mTop);
17533     }
17534 
17535     /**
17536      * The visual z position of this view, in pixels. This is equivalent to the
17537      * {@link #setTranslationZ(float) translationZ} property plus the current
17538      * {@link #getElevation() elevation} property.
17539      *
17540      * @return The visual z position of this view, in pixels.
17541      */
17542     @ViewDebug.ExportedProperty(category = "drawing")
17543     public float getZ() {
17544         return getElevation() + getTranslationZ();
17545     }
17546 
17547     /**
17548      * Sets the visual z position of this view, in pixels. This is equivalent to setting the
17549      * {@link #setTranslationZ(float) translationZ} property to be the difference between
17550      * the z value passed in and the current {@link #getElevation() elevation} property.
17551      *
17552      * @param z The visual z position of this view, in pixels.
17553      */
17554     public void setZ(float z) {
17555         setTranslationZ(z - getElevation());
17556     }
17557 
17558     /**
17559      * The base elevation of this view relative to its parent, in pixels.
17560      *
17561      * @return The base depth position of the view, in pixels.
17562      */
17563     @ViewDebug.ExportedProperty(category = "drawing")
17564     @InspectableProperty
17565     public float getElevation() {
17566         return mRenderNode.getElevation();
17567     }
17568 
17569     /**
17570      * Sets the base elevation of this view, in pixels.
17571      *
17572      * @attr ref android.R.styleable#View_elevation
17573      */
17574     public void setElevation(float elevation) {
17575         if (elevation != getElevation()) {
17576             elevation = sanitizeFloatPropertyValue(elevation, "elevation");
17577             invalidateViewProperty(true, false);
17578             mRenderNode.setElevation(elevation);
17579             invalidateViewProperty(false, true);
17580 
17581             invalidateParentIfNeededAndWasQuickRejected();
17582         }
17583     }
17584 
17585     /**
17586      * The horizontal location of this view relative to its {@link #getLeft() left} position.
17587      * This position is post-layout, in addition to wherever the object's
17588      * layout placed it.
17589      *
17590      * @return The horizontal position of this view relative to its left position, in pixels.
17591      */
17592     @ViewDebug.ExportedProperty(category = "drawing")
17593     @InspectableProperty
17594     public float getTranslationX() {
17595         return mRenderNode.getTranslationX();
17596     }
17597 
17598     /**
17599      * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
17600      * This effectively positions the object post-layout, in addition to wherever the object's
17601      * layout placed it.
17602      *
17603      * @param translationX The horizontal position of this view relative to its left position,
17604      * in pixels.
17605      *
17606      * @attr ref android.R.styleable#View_translationX
17607      */
17608     public void setTranslationX(float translationX) {
17609         if (translationX != getTranslationX()) {
17610             invalidateViewProperty(true, false);
17611             mRenderNode.setTranslationX(translationX);
17612             invalidateViewProperty(false, true);
17613 
17614             invalidateParentIfNeededAndWasQuickRejected();
17615             notifySubtreeAccessibilityStateChangedIfNeeded();
17616         }
17617     }
17618 
17619     /**
17620      * The vertical location of this view relative to its {@link #getTop() top} position.
17621      * This position is post-layout, in addition to wherever the object's
17622      * layout placed it.
17623      *
17624      * @return The vertical position of this view relative to its top position,
17625      * in pixels.
17626      */
17627     @ViewDebug.ExportedProperty(category = "drawing")
17628     @InspectableProperty
17629     public float getTranslationY() {
17630         return mRenderNode.getTranslationY();
17631     }
17632 
17633     /**
17634      * Sets the vertical location of this view relative to its {@link #getTop() top} position.
17635      * This effectively positions the object post-layout, in addition to wherever the object's
17636      * layout placed it.
17637      *
17638      * @param translationY The vertical position of this view relative to its top position,
17639      * in pixels.
17640      *
17641      * @attr ref android.R.styleable#View_translationY
17642      */
17643     public void setTranslationY(float translationY) {
17644         if (translationY != getTranslationY()) {
17645             invalidateViewProperty(true, false);
17646             mRenderNode.setTranslationY(translationY);
17647             invalidateViewProperty(false, true);
17648 
17649             invalidateParentIfNeededAndWasQuickRejected();
17650             notifySubtreeAccessibilityStateChangedIfNeeded();
17651         }
17652     }
17653 
17654     /**
17655      * The depth location of this view relative to its {@link #getElevation() elevation}.
17656      *
17657      * @return The depth of this view relative to its elevation.
17658      */
17659     @ViewDebug.ExportedProperty(category = "drawing")
17660     @InspectableProperty
17661     public float getTranslationZ() {
17662         return mRenderNode.getTranslationZ();
17663     }
17664 
17665     /**
17666      * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
17667      *
17668      * @attr ref android.R.styleable#View_translationZ
17669      */
17670     public void setTranslationZ(float translationZ) {
17671         if (translationZ != getTranslationZ()) {
17672             translationZ = sanitizeFloatPropertyValue(translationZ, "translationZ");
17673             invalidateViewProperty(true, false);
17674             mRenderNode.setTranslationZ(translationZ);
17675             invalidateViewProperty(false, true);
17676 
17677             invalidateParentIfNeededAndWasQuickRejected();
17678         }
17679     }
17680 
17681     /**
17682      * Changes the transformation matrix on the view. This is used in animation frameworks,
17683      * such as {@link android.transition.Transition}. When the animation finishes, the matrix
17684      * should be cleared by calling this method with <code>null</code> as the matrix parameter.
17685      * Application developers should use transformation methods like {@link #setRotation(float)},
17686      * {@link #setScaleX(float)}, {@link #setScaleX(float)}, {@link #setTranslationX(float)}}
17687      * and {@link #setTranslationY(float)} (float)}} instead.
17688      *
17689      * @param matrix The matrix, null indicates that the matrix should be cleared.
17690      * @see #getAnimationMatrix()
17691      */
17692     public void setAnimationMatrix(@Nullable Matrix matrix) {
17693         invalidateViewProperty(true, false);
17694         mRenderNode.setAnimationMatrix(matrix);
17695         invalidateViewProperty(false, true);
17696 
17697         invalidateParentIfNeededAndWasQuickRejected();
17698     }
17699 
17700     /**
17701      * Return the current transformation matrix of the view. This is used in animation frameworks,
17702      * such as {@link android.transition.Transition}. Returns <code>null</code> when there is no
17703      * transformation provided by {@link #setAnimationMatrix(Matrix)}.
17704      * Application developers should use transformation methods like {@link #setRotation(float)},
17705      * {@link #setScaleX(float)}, {@link #setScaleX(float)}, {@link #setTranslationX(float)}}
17706      * and {@link #setTranslationY(float)} (float)}} instead.
17707      *
17708      * @return the Matrix, null indicates there is no transformation
17709      * @see #setAnimationMatrix(Matrix)
17710      */
17711     @Nullable
17712     public Matrix getAnimationMatrix() {
17713         return mRenderNode.getAnimationMatrix();
17714     }
17715 
17716     /**
17717      * Returns the current StateListAnimator if exists.
17718      *
17719      * @return StateListAnimator or null if it does not exists
17720      * @see    #setStateListAnimator(android.animation.StateListAnimator)
17721      */
17722     @InspectableProperty
17723     public StateListAnimator getStateListAnimator() {
17724         return mStateListAnimator;
17725     }
17726 
17727     /**
17728      * Attaches the provided StateListAnimator to this View.
17729      * <p>
17730      * Any previously attached StateListAnimator will be detached.
17731      *
17732      * @param stateListAnimator The StateListAnimator to update the view
17733      * @see android.animation.StateListAnimator
17734      */
17735     public void setStateListAnimator(StateListAnimator stateListAnimator) {
17736         if (mStateListAnimator == stateListAnimator) {
17737             return;
17738         }
17739         if (mStateListAnimator != null) {
17740             mStateListAnimator.setTarget(null);
17741         }
17742         mStateListAnimator = stateListAnimator;
17743         if (stateListAnimator != null) {
17744             stateListAnimator.setTarget(this);
17745             if (isAttachedToWindow()) {
17746                 stateListAnimator.setState(getDrawableState());
17747             }
17748         }
17749     }
17750 
17751     /**
17752      * Returns whether the Outline should be used to clip the contents of the View.
17753      * <p>
17754      * Note that this flag will only be respected if the View's Outline returns true from
17755      * {@link Outline#canClip()}.
17756      *
17757      * @see #setOutlineProvider(ViewOutlineProvider)
17758      * @see #setClipToOutline(boolean)
17759      */
17760     public final boolean getClipToOutline() {
17761         return mRenderNode.getClipToOutline();
17762     }
17763 
17764     /**
17765      * Sets whether the View's Outline should be used to clip the contents of the View.
17766      * <p>
17767      * Only a single non-rectangular clip can be applied on a View at any time.
17768      * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
17769      * circular reveal} animation take priority over Outline clipping, and
17770      * child Outline clipping takes priority over Outline clipping done by a
17771      * parent.
17772      * <p>
17773      * Note that this flag will only be respected if the View's Outline returns true from
17774      * {@link Outline#canClip()}.
17775      *
17776      * @see #setOutlineProvider(ViewOutlineProvider)
17777      * @see #getClipToOutline()
17778      */
17779     public void setClipToOutline(boolean clipToOutline) {
17780         damageInParent();
17781         if (getClipToOutline() != clipToOutline) {
17782             mRenderNode.setClipToOutline(clipToOutline);
17783         }
17784     }
17785 
17786     // correspond to the enum values of View_outlineProvider
17787     private static final int PROVIDER_BACKGROUND = 0;
17788     private static final int PROVIDER_NONE = 1;
17789     private static final int PROVIDER_BOUNDS = 2;
17790     private static final int PROVIDER_PADDED_BOUNDS = 3;
setOutlineProviderFromAttribute(int providerInt)17791     private void setOutlineProviderFromAttribute(int providerInt) {
17792         switch (providerInt) {
17793             case PROVIDER_BACKGROUND:
17794                 setOutlineProvider(ViewOutlineProvider.BACKGROUND);
17795                 break;
17796             case PROVIDER_NONE:
17797                 setOutlineProvider(null);
17798                 break;
17799             case PROVIDER_BOUNDS:
17800                 setOutlineProvider(ViewOutlineProvider.BOUNDS);
17801                 break;
17802             case PROVIDER_PADDED_BOUNDS:
17803                 setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
17804                 break;
17805         }
17806     }
17807 
17808     /**
17809      * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
17810      * the shape of the shadow it casts, and enables outline clipping.
17811      * <p>
17812      * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
17813      * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
17814      * outline provider with this method allows this behavior to be overridden.
17815      * <p>
17816      * If the ViewOutlineProvider is null, if querying it for an outline returns false,
17817      * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
17818      * <p>
17819      * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
17820      *
17821      * @see #setClipToOutline(boolean)
17822      * @see #getClipToOutline()
17823      * @see #getOutlineProvider()
17824      */
setOutlineProvider(ViewOutlineProvider provider)17825     public void setOutlineProvider(ViewOutlineProvider provider) {
17826         mOutlineProvider = provider;
17827         invalidateOutline();
17828     }
17829 
17830     /**
17831      * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
17832      * that defines the shape of the shadow it casts, and enables outline clipping.
17833      *
17834      * @see #setOutlineProvider(ViewOutlineProvider)
17835      */
17836     @InspectableProperty
getOutlineProvider()17837     public ViewOutlineProvider getOutlineProvider() {
17838         return mOutlineProvider;
17839     }
17840 
17841     /**
17842      * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
17843      *
17844      * @see #setOutlineProvider(ViewOutlineProvider)
17845      */
invalidateOutline()17846     public void invalidateOutline() {
17847         rebuildOutline();
17848 
17849         notifySubtreeAccessibilityStateChangedIfNeeded();
17850         invalidateViewProperty(false, false);
17851     }
17852 
17853     /**
17854      * Internal version of {@link #invalidateOutline()} which invalidates the
17855      * outline without invalidating the view itself. This is intended to be called from
17856      * within methods in the View class itself which are the result of the view being
17857      * invalidated already. For example, when we are drawing the background of a View,
17858      * we invalidate the outline in case it changed in the meantime, but we do not
17859      * need to invalidate the view because we're already drawing the background as part
17860      * of drawing the view in response to an earlier invalidation of the view.
17861      */
rebuildOutline()17862     private void rebuildOutline() {
17863         // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
17864         if (mAttachInfo == null) return;
17865 
17866         if (mOutlineProvider == null) {
17867             // no provider, remove outline
17868             mRenderNode.setOutline(null);
17869         } else {
17870             final Outline outline = mAttachInfo.mTmpOutline;
17871             outline.setEmpty();
17872             outline.setAlpha(1.0f);
17873 
17874             mOutlineProvider.getOutline(this, outline);
17875             mRenderNode.setOutline(outline);
17876         }
17877     }
17878 
17879     /**
17880      * HierarchyViewer only
17881      *
17882      * @hide
17883      */
17884     @ViewDebug.ExportedProperty(category = "drawing")
hasShadow()17885     public boolean hasShadow() {
17886         return mRenderNode.hasShadow();
17887     }
17888 
17889     /**
17890      * Sets the color of the spot shadow that is drawn when the view has a positive Z or
17891      * elevation value.
17892      * <p>
17893      * By default the shadow color is black. Generally, this color will be opaque so the intensity
17894      * of the shadow is consistent between different views with different colors.
17895      * <p>
17896      * The opacity of the final spot shadow is a function of the shadow caster height, the
17897      * alpha channel of the outlineSpotShadowColor (typically opaque), and the
17898      * {@link android.R.attr#spotShadowAlpha} theme attribute.
17899      *
17900      * @attr ref android.R.styleable#View_outlineSpotShadowColor
17901      * @param color The color this View will cast for its elevation spot shadow.
17902      */
setOutlineSpotShadowColor(@olorInt int color)17903     public void setOutlineSpotShadowColor(@ColorInt int color) {
17904         if (mRenderNode.setSpotShadowColor(color)) {
17905             invalidateViewProperty(true, true);
17906         }
17907     }
17908 
17909     /**
17910      * @return The shadow color set by {@link #setOutlineSpotShadowColor(int)}, or black if nothing
17911      * was set
17912      */
17913     @InspectableProperty
getOutlineSpotShadowColor()17914     public @ColorInt int getOutlineSpotShadowColor() {
17915         return mRenderNode.getSpotShadowColor();
17916     }
17917 
17918     /**
17919      * Sets the color of the ambient shadow that is drawn when the view has a positive Z or
17920      * elevation value.
17921      * <p>
17922      * By default the shadow color is black. Generally, this color will be opaque so the intensity
17923      * of the shadow is consistent between different views with different colors.
17924      * <p>
17925      * The opacity of the final ambient shadow is a function of the shadow caster height, the
17926      * alpha channel of the outlineAmbientShadowColor (typically opaque), and the
17927      * {@link android.R.attr#ambientShadowAlpha} theme attribute.
17928      *
17929      * @attr ref android.R.styleable#View_outlineAmbientShadowColor
17930      * @param color The color this View will cast for its elevation shadow.
17931      */
setOutlineAmbientShadowColor(@olorInt int color)17932     public void setOutlineAmbientShadowColor(@ColorInt int color) {
17933         if (mRenderNode.setAmbientShadowColor(color)) {
17934             invalidateViewProperty(true, true);
17935         }
17936     }
17937 
17938     /**
17939      * @return The shadow color set by {@link #setOutlineAmbientShadowColor(int)}, or black if
17940      * nothing was set
17941      */
17942     @InspectableProperty
getOutlineAmbientShadowColor()17943     public @ColorInt int getOutlineAmbientShadowColor() {
17944         return mRenderNode.getAmbientShadowColor();
17945     }
17946 
17947 
17948     /** @hide */
setRevealClip(boolean shouldClip, float x, float y, float radius)17949     public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
17950         mRenderNode.setRevealClip(shouldClip, x, y, radius);
17951         invalidateViewProperty(false, false);
17952     }
17953 
17954     /**
17955      * Hit rectangle in parent's coordinates
17956      *
17957      * @param outRect The hit rectangle of the view.
17958      */
getHitRect(Rect outRect)17959     public void getHitRect(Rect outRect) {
17960         if (hasIdentityMatrix() || mAttachInfo == null) {
17961             outRect.set(mLeft, mTop, mRight, mBottom);
17962         } else {
17963             final RectF tmpRect = mAttachInfo.mTmpTransformRect;
17964             tmpRect.set(0, 0, getWidth(), getHeight());
17965             getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
17966             outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
17967                     (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
17968         }
17969     }
17970 
17971     /**
17972      * Determines whether the given point, in local coordinates is inside the view.
17973      */
pointInView(float localX, float localY)17974     /*package*/ final boolean pointInView(float localX, float localY) {
17975         return pointInView(localX, localY, 0);
17976     }
17977 
17978     /**
17979      * Utility method to determine whether the given point, in local coordinates,
17980      * is inside the view, where the area of the view is expanded by the slop factor.
17981      * This method is called while processing touch-move events to determine if the event
17982      * is still within the view.
17983      *
17984      * @hide
17985      */
17986     @UnsupportedAppUsage
pointInView(float localX, float localY, float slop)17987     public boolean pointInView(float localX, float localY, float slop) {
17988         return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
17989                 localY < ((mBottom - mTop) + slop);
17990     }
17991 
17992     /**
17993      * When a view has focus and the user navigates away from it, the next view is searched for
17994      * starting from the rectangle filled in by this method.
17995      *
17996      * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
17997      * of the view.  However, if your view maintains some idea of internal selection,
17998      * such as a cursor, or a selected row or column, you should override this method and
17999      * fill in a more specific rectangle.
18000      *
18001      * @param r The rectangle to fill in, in this view's coordinates.
18002      */
getFocusedRect(Rect r)18003     public void getFocusedRect(Rect r) {
18004         getDrawingRect(r);
18005     }
18006 
18007     /**
18008      * If some part of this view is not clipped by any of its parents, then
18009      * return that area in r in global (root) coordinates. To convert r to local
18010      * coordinates (without taking possible View rotations into account), offset
18011      * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
18012      * If the view is completely clipped or translated out, return false.
18013      *
18014      * @param r If true is returned, r holds the global coordinates of the
18015      *        visible portion of this view.
18016      * @param globalOffset If true is returned, globalOffset holds the dx,dy
18017      *        between this view and its root. globalOffet may be null.
18018      * @return true if r is non-empty (i.e. part of the view is visible at the
18019      *         root level.
18020      */
getGlobalVisibleRect(Rect r, Point globalOffset)18021     public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
18022         int width = mRight - mLeft;
18023         int height = mBottom - mTop;
18024         if (width > 0 && height > 0) {
18025             r.set(0, 0, width, height);
18026             if (globalOffset != null) {
18027                 globalOffset.set(-mScrollX, -mScrollY);
18028             }
18029             return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
18030         }
18031         return false;
18032     }
18033 
getGlobalVisibleRect(Rect r)18034     public final boolean getGlobalVisibleRect(Rect r) {
18035         return getGlobalVisibleRect(r, null);
18036     }
18037 
getLocalVisibleRect(Rect r)18038     public final boolean getLocalVisibleRect(Rect r) {
18039         final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
18040         if (getGlobalVisibleRect(r, offset)) {
18041             r.offset(-offset.x, -offset.y); // make r local
18042             return true;
18043         }
18044         return false;
18045     }
18046 
18047     /**
18048      * Offset this view's vertical location by the specified number of pixels.
18049      *
18050      * @param offset the number of pixels to offset the view by
18051      */
offsetTopAndBottom(int offset)18052     public void offsetTopAndBottom(int offset) {
18053         if (offset != 0) {
18054             final boolean matrixIsIdentity = hasIdentityMatrix();
18055             if (matrixIsIdentity) {
18056                 if (isHardwareAccelerated()) {
18057                     invalidateViewProperty(false, false);
18058                 } else {
18059                     final ViewParent p = mParent;
18060                     if (p != null && mAttachInfo != null) {
18061                         final Rect r = mAttachInfo.mTmpInvalRect;
18062                         int minTop;
18063                         int maxBottom;
18064                         int yLoc;
18065                         if (offset < 0) {
18066                             minTop = mTop + offset;
18067                             maxBottom = mBottom;
18068                             yLoc = offset;
18069                         } else {
18070                             minTop = mTop;
18071                             maxBottom = mBottom + offset;
18072                             yLoc = 0;
18073                         }
18074                         r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
18075                         p.invalidateChild(this, r);
18076                     }
18077                 }
18078             } else {
18079                 invalidateViewProperty(false, false);
18080             }
18081 
18082             mTop += offset;
18083             mBottom += offset;
18084             mRenderNode.offsetTopAndBottom(offset);
18085             if (isHardwareAccelerated()) {
18086                 invalidateViewProperty(false, false);
18087                 invalidateParentIfNeededAndWasQuickRejected();
18088             } else {
18089                 if (!matrixIsIdentity) {
18090                     invalidateViewProperty(false, true);
18091                 }
18092                 invalidateParentIfNeeded();
18093             }
18094             notifySubtreeAccessibilityStateChangedIfNeeded();
18095         }
18096     }
18097 
18098     /**
18099      * Offset this view's horizontal location by the specified amount of pixels.
18100      *
18101      * @param offset the number of pixels to offset the view by
18102      */
offsetLeftAndRight(int offset)18103     public void offsetLeftAndRight(int offset) {
18104         if (offset != 0) {
18105             final boolean matrixIsIdentity = hasIdentityMatrix();
18106             if (matrixIsIdentity) {
18107                 if (isHardwareAccelerated()) {
18108                     invalidateViewProperty(false, false);
18109                 } else {
18110                     final ViewParent p = mParent;
18111                     if (p != null && mAttachInfo != null) {
18112                         final Rect r = mAttachInfo.mTmpInvalRect;
18113                         int minLeft;
18114                         int maxRight;
18115                         if (offset < 0) {
18116                             minLeft = mLeft + offset;
18117                             maxRight = mRight;
18118                         } else {
18119                             minLeft = mLeft;
18120                             maxRight = mRight + offset;
18121                         }
18122                         r.set(0, 0, maxRight - minLeft, mBottom - mTop);
18123                         p.invalidateChild(this, r);
18124                     }
18125                 }
18126             } else {
18127                 invalidateViewProperty(false, false);
18128             }
18129 
18130             mLeft += offset;
18131             mRight += offset;
18132             mRenderNode.offsetLeftAndRight(offset);
18133             if (isHardwareAccelerated()) {
18134                 invalidateViewProperty(false, false);
18135                 invalidateParentIfNeededAndWasQuickRejected();
18136             } else {
18137                 if (!matrixIsIdentity) {
18138                     invalidateViewProperty(false, true);
18139                 }
18140                 invalidateParentIfNeeded();
18141             }
18142             notifySubtreeAccessibilityStateChangedIfNeeded();
18143         }
18144     }
18145 
18146     /**
18147      * Get the LayoutParams associated with this view. All views should have
18148      * layout parameters. These supply parameters to the <i>parent</i> of this
18149      * view specifying how it should be arranged. There are many subclasses of
18150      * ViewGroup.LayoutParams, and these correspond to the different subclasses
18151      * of ViewGroup that are responsible for arranging their children.
18152      *
18153      * This method may return null if this View is not attached to a parent
18154      * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
18155      * was not invoked successfully. When a View is attached to a parent
18156      * ViewGroup, this method must not return null.
18157      *
18158      * @return The LayoutParams associated with this view, or null if no
18159      *         parameters have been set yet
18160      */
18161     @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
getLayoutParams()18162     public ViewGroup.LayoutParams getLayoutParams() {
18163         return mLayoutParams;
18164     }
18165 
18166     /**
18167      * Set the layout parameters associated with this view. These supply
18168      * parameters to the <i>parent</i> of this view specifying how it should be
18169      * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
18170      * correspond to the different subclasses of ViewGroup that are responsible
18171      * for arranging their children.
18172      *
18173      * @param params The layout parameters for this view, cannot be null
18174      */
setLayoutParams(ViewGroup.LayoutParams params)18175     public void setLayoutParams(ViewGroup.LayoutParams params) {
18176         if (params == null) {
18177             throw new NullPointerException("Layout parameters cannot be null");
18178         }
18179         mLayoutParams = params;
18180         resolveLayoutParams();
18181         if (mParent instanceof ViewGroup) {
18182             ((ViewGroup) mParent).onSetLayoutParams(this, params);
18183         }
18184         requestLayout();
18185     }
18186 
18187     /**
18188      * Resolve the layout parameters depending on the resolved layout direction
18189      *
18190      * @hide
18191      */
resolveLayoutParams()18192     public void resolveLayoutParams() {
18193         if (mLayoutParams != null) {
18194             mLayoutParams.resolveLayoutDirection(getLayoutDirection());
18195         }
18196     }
18197 
18198     /**
18199      * Set the scrolled position of your view. This will cause a call to
18200      * {@link #onScrollChanged(int, int, int, int)} and the view will be
18201      * invalidated.
18202      * @param x the x position to scroll to
18203      * @param y the y position to scroll to
18204      */
scrollTo(int x, int y)18205     public void scrollTo(int x, int y) {
18206         if (mScrollX != x || mScrollY != y) {
18207             int oldX = mScrollX;
18208             int oldY = mScrollY;
18209             mScrollX = x;
18210             mScrollY = y;
18211             invalidateParentCaches();
18212             onScrollChanged(mScrollX, mScrollY, oldX, oldY);
18213             if (!awakenScrollBars()) {
18214                 postInvalidateOnAnimation();
18215             }
18216         }
18217     }
18218 
18219     /**
18220      * Move the scrolled position of your view. This will cause a call to
18221      * {@link #onScrollChanged(int, int, int, int)} and the view will be
18222      * invalidated.
18223      * @param x the amount of pixels to scroll by horizontally
18224      * @param y the amount of pixels to scroll by vertically
18225      */
scrollBy(int x, int y)18226     public void scrollBy(int x, int y) {
18227         scrollTo(mScrollX + x, mScrollY + y);
18228     }
18229 
18230     /**
18231      * <p>Trigger the scrollbars to draw. When invoked this method starts an
18232      * animation to fade the scrollbars out after a default delay. If a subclass
18233      * provides animated scrolling, the start delay should equal the duration
18234      * of the scrolling animation.</p>
18235      *
18236      * <p>The animation starts only if at least one of the scrollbars is
18237      * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
18238      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
18239      * this method returns true, and false otherwise. If the animation is
18240      * started, this method calls {@link #invalidate()}; in that case the
18241      * caller should not call {@link #invalidate()}.</p>
18242      *
18243      * <p>This method should be invoked every time a subclass directly updates
18244      * the scroll parameters.</p>
18245      *
18246      * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
18247      * and {@link #scrollTo(int, int)}.</p>
18248      *
18249      * @return true if the animation is played, false otherwise
18250      *
18251      * @see #awakenScrollBars(int)
18252      * @see #scrollBy(int, int)
18253      * @see #scrollTo(int, int)
18254      * @see #isHorizontalScrollBarEnabled()
18255      * @see #isVerticalScrollBarEnabled()
18256      * @see #setHorizontalScrollBarEnabled(boolean)
18257      * @see #setVerticalScrollBarEnabled(boolean)
18258      */
awakenScrollBars()18259     protected boolean awakenScrollBars() {
18260         return mScrollCache != null &&
18261                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
18262     }
18263 
18264     /**
18265      * Trigger the scrollbars to draw.
18266      * This method differs from awakenScrollBars() only in its default duration.
18267      * initialAwakenScrollBars() will show the scroll bars for longer than
18268      * usual to give the user more of a chance to notice them.
18269      *
18270      * @return true if the animation is played, false otherwise.
18271      */
initialAwakenScrollBars()18272     private boolean initialAwakenScrollBars() {
18273         return mScrollCache != null &&
18274                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
18275     }
18276 
18277     /**
18278      * <p>
18279      * Trigger the scrollbars to draw. When invoked this method starts an
18280      * animation to fade the scrollbars out after a fixed delay. If a subclass
18281      * provides animated scrolling, the start delay should equal the duration of
18282      * the scrolling animation.
18283      * </p>
18284      *
18285      * <p>
18286      * The animation starts only if at least one of the scrollbars is enabled,
18287      * as specified by {@link #isHorizontalScrollBarEnabled()} and
18288      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
18289      * this method returns true, and false otherwise. If the animation is
18290      * started, this method calls {@link #invalidate()}; in that case the caller
18291      * should not call {@link #invalidate()}.
18292      * </p>
18293      *
18294      * <p>
18295      * This method should be invoked every time a subclass directly updates the
18296      * scroll parameters.
18297      * </p>
18298      *
18299      * @param startDelay the delay, in milliseconds, after which the animation
18300      *        should start; when the delay is 0, the animation starts
18301      *        immediately
18302      * @return true if the animation is played, false otherwise
18303      *
18304      * @see #scrollBy(int, int)
18305      * @see #scrollTo(int, int)
18306      * @see #isHorizontalScrollBarEnabled()
18307      * @see #isVerticalScrollBarEnabled()
18308      * @see #setHorizontalScrollBarEnabled(boolean)
18309      * @see #setVerticalScrollBarEnabled(boolean)
18310      */
awakenScrollBars(int startDelay)18311     protected boolean awakenScrollBars(int startDelay) {
18312         return awakenScrollBars(startDelay, true);
18313     }
18314 
18315     /**
18316      * <p>
18317      * Trigger the scrollbars to draw. When invoked this method starts an
18318      * animation to fade the scrollbars out after a fixed delay. If a subclass
18319      * provides animated scrolling, the start delay should equal the duration of
18320      * the scrolling animation.
18321      * </p>
18322      *
18323      * <p>
18324      * The animation starts only if at least one of the scrollbars is enabled,
18325      * as specified by {@link #isHorizontalScrollBarEnabled()} and
18326      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
18327      * this method returns true, and false otherwise. If the animation is
18328      * started, this method calls {@link #invalidate()} if the invalidate parameter
18329      * is set to true; in that case the caller
18330      * should not call {@link #invalidate()}.
18331      * </p>
18332      *
18333      * <p>
18334      * This method should be invoked every time a subclass directly updates the
18335      * scroll parameters.
18336      * </p>
18337      *
18338      * @param startDelay the delay, in milliseconds, after which the animation
18339      *        should start; when the delay is 0, the animation starts
18340      *        immediately
18341      *
18342      * @param invalidate Whether this method should call invalidate
18343      *
18344      * @return true if the animation is played, false otherwise
18345      *
18346      * @see #scrollBy(int, int)
18347      * @see #scrollTo(int, int)
18348      * @see #isHorizontalScrollBarEnabled()
18349      * @see #isVerticalScrollBarEnabled()
18350      * @see #setHorizontalScrollBarEnabled(boolean)
18351      * @see #setVerticalScrollBarEnabled(boolean)
18352      */
awakenScrollBars(int startDelay, boolean invalidate)18353     protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
18354         final ScrollabilityCache scrollCache = mScrollCache;
18355 
18356         if (scrollCache == null || !scrollCache.fadeScrollBars) {
18357             return false;
18358         }
18359 
18360         if (scrollCache.scrollBar == null) {
18361             scrollCache.scrollBar = new ScrollBarDrawable();
18362             scrollCache.scrollBar.setState(getDrawableState());
18363             scrollCache.scrollBar.setCallback(this);
18364         }
18365 
18366         if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
18367 
18368             if (invalidate) {
18369                 // Invalidate to show the scrollbars
18370                 postInvalidateOnAnimation();
18371             }
18372 
18373             if (scrollCache.state == ScrollabilityCache.OFF) {
18374                 // FIXME: this is copied from WindowManagerService.
18375                 // We should get this value from the system when it
18376                 // is possible to do so.
18377                 final int KEY_REPEAT_FIRST_DELAY = 750;
18378                 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
18379             }
18380 
18381             // Tell mScrollCache when we should start fading. This may
18382             // extend the fade start time if one was already scheduled
18383             long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
18384             scrollCache.fadeStartTime = fadeStartTime;
18385             scrollCache.state = ScrollabilityCache.ON;
18386 
18387             // Schedule our fader to run, unscheduling any old ones first
18388             if (mAttachInfo != null) {
18389                 mAttachInfo.mHandler.removeCallbacks(scrollCache);
18390                 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
18391             }
18392 
18393             return true;
18394         }
18395 
18396         return false;
18397     }
18398 
18399     /**
18400      * Do not invalidate views which are not visible and which are not running an animation. They
18401      * will not get drawn and they should not set dirty flags as if they will be drawn
18402      */
skipInvalidate()18403     private boolean skipInvalidate() {
18404         return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
18405                 (!(mParent instanceof ViewGroup) ||
18406                         !((ViewGroup) mParent).isViewTransitioning(this));
18407     }
18408 
18409     /**
18410      * Mark the area defined by dirty as needing to be drawn. If the view is
18411      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
18412      * point in the future.
18413      * <p>
18414      * This must be called from a UI thread. To call from a non-UI thread, call
18415      * {@link #postInvalidate()}.
18416      * <p>
18417      * <b>WARNING:</b> In API 19 and below, this method may be destructive to
18418      * {@code dirty}.
18419      *
18420      * @param dirty the rectangle representing the bounds of the dirty region
18421      *
18422      * @deprecated The switch to hardware accelerated rendering in API 14 reduced
18423      * the importance of the dirty rectangle. In API 21 the given rectangle is
18424      * ignored entirely in favor of an internally-calculated area instead.
18425      * Because of this, clients are encouraged to just call {@link #invalidate()}.
18426      */
18427     @Deprecated
invalidate(Rect dirty)18428     public void invalidate(Rect dirty) {
18429         final int scrollX = mScrollX;
18430         final int scrollY = mScrollY;
18431         invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
18432                 dirty.right - scrollX, dirty.bottom - scrollY, true, false);
18433     }
18434 
18435     /**
18436      * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
18437      * coordinates of the dirty rect are relative to the view. If the view is
18438      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
18439      * point in the future.
18440      * <p>
18441      * This must be called from a UI thread. To call from a non-UI thread, call
18442      * {@link #postInvalidate()}.
18443      *
18444      * @param l the left position of the dirty region
18445      * @param t the top position of the dirty region
18446      * @param r the right position of the dirty region
18447      * @param b the bottom position of the dirty region
18448      *
18449      * @deprecated The switch to hardware accelerated rendering in API 14 reduced
18450      * the importance of the dirty rectangle. In API 21 the given rectangle is
18451      * ignored entirely in favor of an internally-calculated area instead.
18452      * Because of this, clients are encouraged to just call {@link #invalidate()}.
18453      */
18454     @Deprecated
invalidate(int l, int t, int r, int b)18455     public void invalidate(int l, int t, int r, int b) {
18456         final int scrollX = mScrollX;
18457         final int scrollY = mScrollY;
18458         invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
18459     }
18460 
18461     /**
18462      * Invalidate the whole view. If the view is visible,
18463      * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
18464      * the future.
18465      * <p>
18466      * This must be called from a UI thread. To call from a non-UI thread, call
18467      * {@link #postInvalidate()}.
18468      */
invalidate()18469     public void invalidate() {
18470         invalidate(true);
18471     }
18472 
18473     /**
18474      * This is where the invalidate() work actually happens. A full invalidate()
18475      * causes the drawing cache to be invalidated, but this function can be
18476      * called with invalidateCache set to false to skip that invalidation step
18477      * for cases that do not need it (for example, a component that remains at
18478      * the same dimensions with the same content).
18479      *
18480      * @param invalidateCache Whether the drawing cache for this view should be
18481      *            invalidated as well. This is usually true for a full
18482      *            invalidate, but may be set to false if the View's contents or
18483      *            dimensions have not changed.
18484      * @hide
18485      */
18486     @UnsupportedAppUsage
invalidate(boolean invalidateCache)18487     public void invalidate(boolean invalidateCache) {
18488         invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
18489     }
18490 
invalidateInternal(int l, int t, int r, int b, boolean invalidateCache, boolean fullInvalidate)18491     void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
18492             boolean fullInvalidate) {
18493         if (mGhostView != null) {
18494             mGhostView.invalidate(true);
18495             return;
18496         }
18497 
18498         if (skipInvalidate()) {
18499             return;
18500         }
18501 
18502         // Reset content capture caches
18503         mPrivateFlags4 &= ~PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK;
18504         mContentCaptureSessionCached = false;
18505 
18506         if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
18507                 || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
18508                 || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
18509                 || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
18510             if (fullInvalidate) {
18511                 mLastIsOpaque = isOpaque();
18512                 mPrivateFlags &= ~PFLAG_DRAWN;
18513             }
18514 
18515             mPrivateFlags |= PFLAG_DIRTY;
18516 
18517             if (invalidateCache) {
18518                 mPrivateFlags |= PFLAG_INVALIDATED;
18519                 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
18520             }
18521 
18522             // Propagate the damage rectangle to the parent view.
18523             final AttachInfo ai = mAttachInfo;
18524             final ViewParent p = mParent;
18525             if (p != null && ai != null && l < r && t < b) {
18526                 final Rect damage = ai.mTmpInvalRect;
18527                 damage.set(l, t, r, b);
18528                 p.invalidateChild(this, damage);
18529             }
18530 
18531             // Damage the entire projection receiver, if necessary.
18532             if (mBackground != null && mBackground.isProjected()) {
18533                 final View receiver = getProjectionReceiver();
18534                 if (receiver != null) {
18535                     receiver.damageInParent();
18536                 }
18537             }
18538         }
18539     }
18540 
18541     /**
18542      * @return this view's projection receiver, or {@code null} if none exists
18543      */
getProjectionReceiver()18544     private View getProjectionReceiver() {
18545         ViewParent p = getParent();
18546         while (p != null && p instanceof View) {
18547             final View v = (View) p;
18548             if (v.isProjectionReceiver()) {
18549                 return v;
18550             }
18551             p = p.getParent();
18552         }
18553 
18554         return null;
18555     }
18556 
18557     /**
18558      * @return whether the view is a projection receiver
18559      */
isProjectionReceiver()18560     private boolean isProjectionReceiver() {
18561         return mBackground != null;
18562     }
18563 
18564     /**
18565      * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
18566      * set any flags or handle all of the cases handled by the default invalidation methods.
18567      * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
18568      * dirty rect. This method calls into fast invalidation methods in ViewGroup that
18569      * walk up the hierarchy, transforming the dirty rect as necessary.
18570      *
18571      * The method also handles normal invalidation logic if display list properties are not
18572      * being used in this view. The invalidateParent and forceRedraw flags are used by that
18573      * backup approach, to handle these cases used in the various property-setting methods.
18574      *
18575      * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
18576      * are not being used in this view
18577      * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
18578      * list properties are not being used in this view
18579      */
18580     @UnsupportedAppUsage
invalidateViewProperty(boolean invalidateParent, boolean forceRedraw)18581     void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
18582         if (!isHardwareAccelerated()
18583                 || !mRenderNode.hasDisplayList()
18584                 || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
18585             if (invalidateParent) {
18586                 invalidateParentCaches();
18587             }
18588             if (forceRedraw) {
18589                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
18590             }
18591             invalidate(false);
18592         } else {
18593             damageInParent();
18594         }
18595     }
18596 
18597     /**
18598      * Tells the parent view to damage this view's bounds.
18599      *
18600      * @hide
18601      */
damageInParent()18602     protected void damageInParent() {
18603         if (mParent != null && mAttachInfo != null) {
18604             mParent.onDescendantInvalidated(this, this);
18605         }
18606     }
18607 
18608     /**
18609      * Used to indicate that the parent of this view should clear its caches. This functionality
18610      * is used to force the parent to rebuild its display list (when hardware-accelerated),
18611      * which is necessary when various parent-managed properties of the view change, such as
18612      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
18613      * clears the parent caches and does not causes an invalidate event.
18614      *
18615      * @hide
18616      */
18617     @UnsupportedAppUsage
invalidateParentCaches()18618     protected void invalidateParentCaches() {
18619         if (mParent instanceof View) {
18620             ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
18621         }
18622     }
18623 
18624     /**
18625      * Used to indicate that the parent of this view should be invalidated. This functionality
18626      * is used to force the parent to rebuild its display list (when hardware-accelerated),
18627      * which is necessary when various parent-managed properties of the view change, such as
18628      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
18629      * an invalidation event to the parent.
18630      *
18631      * @hide
18632      */
18633     @UnsupportedAppUsage
invalidateParentIfNeeded()18634     protected void invalidateParentIfNeeded() {
18635         if (isHardwareAccelerated() && mParent instanceof View) {
18636             ((View) mParent).invalidate(true);
18637         }
18638     }
18639 
18640     /**
18641      * @hide
18642      */
invalidateParentIfNeededAndWasQuickRejected()18643     protected void invalidateParentIfNeededAndWasQuickRejected() {
18644         if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
18645             // View was rejected last time it was drawn by its parent; this may have changed
18646             invalidateParentIfNeeded();
18647         }
18648     }
18649 
18650     /**
18651      * Indicates whether this View is opaque. An opaque View guarantees that it will
18652      * draw all the pixels overlapping its bounds using a fully opaque color.
18653      *
18654      * Subclasses of View should override this method whenever possible to indicate
18655      * whether an instance is opaque. Opaque Views are treated in a special way by
18656      * the View hierarchy, possibly allowing it to perform optimizations during
18657      * invalidate/draw passes.
18658      *
18659      * @return True if this View is guaranteed to be fully opaque, false otherwise.
18660      */
18661     @ViewDebug.ExportedProperty(category = "drawing")
isOpaque()18662     public boolean isOpaque() {
18663         return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
18664                 getFinalAlpha() >= 1.0f;
18665     }
18666 
18667     /**
18668      * @hide
18669      */
18670     @UnsupportedAppUsage
computeOpaqueFlags()18671     protected void computeOpaqueFlags() {
18672         // Opaque if:
18673         //   - Has a background
18674         //   - Background is opaque
18675         //   - Doesn't have scrollbars or scrollbars overlay
18676 
18677         if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
18678             mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
18679         } else {
18680             mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
18681         }
18682 
18683         final int flags = mViewFlags;
18684         if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
18685                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
18686                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
18687             mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
18688         } else {
18689             mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
18690         }
18691     }
18692 
18693     /**
18694      * @hide
18695      */
hasOpaqueScrollbars()18696     protected boolean hasOpaqueScrollbars() {
18697         return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
18698     }
18699 
18700     /**
18701      * @return A handler associated with the thread running the View. This
18702      * handler can be used to pump events in the UI events queue.
18703      */
getHandler()18704     public Handler getHandler() {
18705         final AttachInfo attachInfo = mAttachInfo;
18706         if (attachInfo != null) {
18707             return attachInfo.mHandler;
18708         }
18709         return null;
18710     }
18711 
18712     /**
18713      * Returns the queue of runnable for this view.
18714      *
18715      * @return the queue of runnables for this view
18716      */
getRunQueue()18717     private HandlerActionQueue getRunQueue() {
18718         if (mRunQueue == null) {
18719             mRunQueue = new HandlerActionQueue();
18720         }
18721         return mRunQueue;
18722     }
18723 
18724     /**
18725      * Gets the view root associated with the View.
18726      * @return The view root, or null if none.
18727      * @hide
18728      */
18729     @UnsupportedAppUsage
getViewRootImpl()18730     public ViewRootImpl getViewRootImpl() {
18731         if (mAttachInfo != null) {
18732             return mAttachInfo.mViewRootImpl;
18733         }
18734         return null;
18735     }
18736 
18737     /**
18738      * @hide
18739      */
18740     @UnsupportedAppUsage
getThreadedRenderer()18741     public ThreadedRenderer getThreadedRenderer() {
18742         return mAttachInfo != null ? mAttachInfo.mThreadedRenderer : null;
18743     }
18744 
18745     /**
18746      * <p>Causes the Runnable to be added to the message queue.
18747      * The runnable will be run on the user interface thread.</p>
18748      *
18749      * @param action The Runnable that will be executed.
18750      *
18751      * @return Returns true if the Runnable was successfully placed in to the
18752      *         message queue.  Returns false on failure, usually because the
18753      *         looper processing the message queue is exiting.
18754      *
18755      * @see #postDelayed
18756      * @see #removeCallbacks
18757      */
post(Runnable action)18758     public boolean post(Runnable action) {
18759         final AttachInfo attachInfo = mAttachInfo;
18760         if (attachInfo != null) {
18761             return attachInfo.mHandler.post(action);
18762         }
18763 
18764         // Postpone the runnable until we know on which thread it needs to run.
18765         // Assume that the runnable will be successfully placed after attach.
18766         getRunQueue().post(action);
18767         return true;
18768     }
18769 
18770     /**
18771      * <p>Causes the Runnable to be added to the message queue, to be run
18772      * after the specified amount of time elapses.
18773      * The runnable will be run on the user interface thread.</p>
18774      *
18775      * @param action The Runnable that will be executed.
18776      * @param delayMillis The delay (in milliseconds) until the Runnable
18777      *        will be executed.
18778      *
18779      * @return true if the Runnable was successfully placed in to the
18780      *         message queue.  Returns false on failure, usually because the
18781      *         looper processing the message queue is exiting.  Note that a
18782      *         result of true does not mean the Runnable will be processed --
18783      *         if the looper is quit before the delivery time of the message
18784      *         occurs then the message will be dropped.
18785      *
18786      * @see #post
18787      * @see #removeCallbacks
18788      */
postDelayed(Runnable action, long delayMillis)18789     public boolean postDelayed(Runnable action, long delayMillis) {
18790         final AttachInfo attachInfo = mAttachInfo;
18791         if (attachInfo != null) {
18792             return attachInfo.mHandler.postDelayed(action, delayMillis);
18793         }
18794 
18795         // Postpone the runnable until we know on which thread it needs to run.
18796         // Assume that the runnable will be successfully placed after attach.
18797         getRunQueue().postDelayed(action, delayMillis);
18798         return true;
18799     }
18800 
18801     /**
18802      * <p>Causes the Runnable to execute on the next animation time step.
18803      * The runnable will be run on the user interface thread.</p>
18804      *
18805      * @param action The Runnable that will be executed.
18806      *
18807      * @see #postOnAnimationDelayed
18808      * @see #removeCallbacks
18809      */
postOnAnimation(Runnable action)18810     public void postOnAnimation(Runnable action) {
18811         final AttachInfo attachInfo = mAttachInfo;
18812         if (attachInfo != null) {
18813             attachInfo.mViewRootImpl.mChoreographer.postCallback(
18814                     Choreographer.CALLBACK_ANIMATION, action, null);
18815         } else {
18816             // Postpone the runnable until we know
18817             // on which thread it needs to run.
18818             getRunQueue().post(action);
18819         }
18820     }
18821 
18822     /**
18823      * <p>Causes the Runnable to execute on the next animation time step,
18824      * after the specified amount of time elapses.
18825      * The runnable will be run on the user interface thread.</p>
18826      *
18827      * @param action The Runnable that will be executed.
18828      * @param delayMillis The delay (in milliseconds) until the Runnable
18829      *        will be executed.
18830      *
18831      * @see #postOnAnimation
18832      * @see #removeCallbacks
18833      */
postOnAnimationDelayed(Runnable action, long delayMillis)18834     public void postOnAnimationDelayed(Runnable action, long delayMillis) {
18835         final AttachInfo attachInfo = mAttachInfo;
18836         if (attachInfo != null) {
18837             attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
18838                     Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
18839         } else {
18840             // Postpone the runnable until we know
18841             // on which thread it needs to run.
18842             getRunQueue().postDelayed(action, delayMillis);
18843         }
18844     }
18845 
18846     /**
18847      * <p>Removes the specified Runnable from the message queue.</p>
18848      *
18849      * @param action The Runnable to remove from the message handling queue
18850      *
18851      * @return true if this view could ask the Handler to remove the Runnable,
18852      *         false otherwise. When the returned value is true, the Runnable
18853      *         may or may not have been actually removed from the message queue
18854      *         (for instance, if the Runnable was not in the queue already.)
18855      *
18856      * @see #post
18857      * @see #postDelayed
18858      * @see #postOnAnimation
18859      * @see #postOnAnimationDelayed
18860      */
removeCallbacks(Runnable action)18861     public boolean removeCallbacks(Runnable action) {
18862         if (action != null) {
18863             final AttachInfo attachInfo = mAttachInfo;
18864             if (attachInfo != null) {
18865                 attachInfo.mHandler.removeCallbacks(action);
18866                 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
18867                         Choreographer.CALLBACK_ANIMATION, action, null);
18868             }
18869             getRunQueue().removeCallbacks(action);
18870         }
18871         return true;
18872     }
18873 
18874     /**
18875      * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
18876      * Use this to invalidate the View from a non-UI thread.</p>
18877      *
18878      * <p>This method can be invoked from outside of the UI thread
18879      * only when this View is attached to a window.</p>
18880      *
18881      * @see #invalidate()
18882      * @see #postInvalidateDelayed(long)
18883      */
postInvalidate()18884     public void postInvalidate() {
18885         postInvalidateDelayed(0);
18886     }
18887 
18888     /**
18889      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
18890      * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
18891      *
18892      * <p>This method can be invoked from outside of the UI thread
18893      * only when this View is attached to a window.</p>
18894      *
18895      * @param left The left coordinate of the rectangle to invalidate.
18896      * @param top The top coordinate of the rectangle to invalidate.
18897      * @param right The right coordinate of the rectangle to invalidate.
18898      * @param bottom The bottom coordinate of the rectangle to invalidate.
18899      *
18900      * @see #invalidate(int, int, int, int)
18901      * @see #invalidate(Rect)
18902      * @see #postInvalidateDelayed(long, int, int, int, int)
18903      */
postInvalidate(int left, int top, int right, int bottom)18904     public void postInvalidate(int left, int top, int right, int bottom) {
18905         postInvalidateDelayed(0, left, top, right, bottom);
18906     }
18907 
18908     /**
18909      * <p>Cause an invalidate to happen on a subsequent cycle through the event
18910      * loop. Waits for the specified amount of time.</p>
18911      *
18912      * <p>This method can be invoked from outside of the UI thread
18913      * only when this View is attached to a window.</p>
18914      *
18915      * @param delayMilliseconds the duration in milliseconds to delay the
18916      *         invalidation by
18917      *
18918      * @see #invalidate()
18919      * @see #postInvalidate()
18920      */
postInvalidateDelayed(long delayMilliseconds)18921     public void postInvalidateDelayed(long delayMilliseconds) {
18922         // We try only with the AttachInfo because there's no point in invalidating
18923         // if we are not attached to our window
18924         final AttachInfo attachInfo = mAttachInfo;
18925         if (attachInfo != null) {
18926             attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
18927         }
18928     }
18929 
18930     /**
18931      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
18932      * through the event loop. Waits for the specified amount of time.</p>
18933      *
18934      * <p>This method can be invoked from outside of the UI thread
18935      * only when this View is attached to a window.</p>
18936      *
18937      * @param delayMilliseconds the duration in milliseconds to delay the
18938      *         invalidation by
18939      * @param left The left coordinate of the rectangle to invalidate.
18940      * @param top The top coordinate of the rectangle to invalidate.
18941      * @param right The right coordinate of the rectangle to invalidate.
18942      * @param bottom The bottom coordinate of the rectangle to invalidate.
18943      *
18944      * @see #invalidate(int, int, int, int)
18945      * @see #invalidate(Rect)
18946      * @see #postInvalidate(int, int, int, int)
18947      */
postInvalidateDelayed(long delayMilliseconds, int left, int top, int right, int bottom)18948     public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
18949             int right, int bottom) {
18950 
18951         // We try only with the AttachInfo because there's no point in invalidating
18952         // if we are not attached to our window
18953         final AttachInfo attachInfo = mAttachInfo;
18954         if (attachInfo != null) {
18955             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
18956             info.target = this;
18957             info.left = left;
18958             info.top = top;
18959             info.right = right;
18960             info.bottom = bottom;
18961 
18962             attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
18963         }
18964     }
18965 
18966     /**
18967      * <p>Cause an invalidate to happen on the next animation time step, typically the
18968      * next display frame.</p>
18969      *
18970      * <p>This method can be invoked from outside of the UI thread
18971      * only when this View is attached to a window.</p>
18972      *
18973      * @see #invalidate()
18974      */
postInvalidateOnAnimation()18975     public void postInvalidateOnAnimation() {
18976         // We try only with the AttachInfo because there's no point in invalidating
18977         // if we are not attached to our window
18978         final AttachInfo attachInfo = mAttachInfo;
18979         if (attachInfo != null) {
18980             attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
18981         }
18982     }
18983 
18984     /**
18985      * <p>Cause an invalidate of the specified area to happen on the next animation
18986      * time step, typically the next display frame.</p>
18987      *
18988      * <p>This method can be invoked from outside of the UI thread
18989      * only when this View is attached to a window.</p>
18990      *
18991      * @param left The left coordinate of the rectangle to invalidate.
18992      * @param top The top coordinate of the rectangle to invalidate.
18993      * @param right The right coordinate of the rectangle to invalidate.
18994      * @param bottom The bottom coordinate of the rectangle to invalidate.
18995      *
18996      * @see #invalidate(int, int, int, int)
18997      * @see #invalidate(Rect)
18998      */
postInvalidateOnAnimation(int left, int top, int right, int bottom)18999     public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
19000         // We try only with the AttachInfo because there's no point in invalidating
19001         // if we are not attached to our window
19002         final AttachInfo attachInfo = mAttachInfo;
19003         if (attachInfo != null) {
19004             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
19005             info.target = this;
19006             info.left = left;
19007             info.top = top;
19008             info.right = right;
19009             info.bottom = bottom;
19010 
19011             attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
19012         }
19013     }
19014 
19015     /**
19016      * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
19017      * This event is sent at most once every
19018      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
19019      */
postSendViewScrolledAccessibilityEventCallback(int dx, int dy)19020     private void postSendViewScrolledAccessibilityEventCallback(int dx, int dy) {
19021         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
19022             AccessibilityEvent event =
19023                     AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_SCROLLED);
19024             event.setScrollDeltaX(dx);
19025             event.setScrollDeltaY(dy);
19026             sendAccessibilityEventUnchecked(event);
19027         }
19028     }
19029 
19030     /**
19031      * Called by a parent to request that a child update its values for mScrollX
19032      * and mScrollY if necessary. This will typically be done if the child is
19033      * animating a scroll using a {@link android.widget.Scroller Scroller}
19034      * object.
19035      */
computeScroll()19036     public void computeScroll() {
19037     }
19038 
19039     /**
19040      * <p>Indicate whether the horizontal edges are faded when the view is
19041      * scrolled horizontally.</p>
19042      *
19043      * @return true if the horizontal edges should are faded on scroll, false
19044      *         otherwise
19045      *
19046      * @see #setHorizontalFadingEdgeEnabled(boolean)
19047      *
19048      * @attr ref android.R.styleable#View_requiresFadingEdge
19049      */
isHorizontalFadingEdgeEnabled()19050     public boolean isHorizontalFadingEdgeEnabled() {
19051         return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
19052     }
19053 
19054     /**
19055      * <p>Define whether the horizontal edges should be faded when this view
19056      * is scrolled horizontally.</p>
19057      *
19058      * @param horizontalFadingEdgeEnabled true if the horizontal edges should
19059      *                                    be faded when the view is scrolled
19060      *                                    horizontally
19061      *
19062      * @see #isHorizontalFadingEdgeEnabled()
19063      *
19064      * @attr ref android.R.styleable#View_requiresFadingEdge
19065      */
setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled)19066     public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
19067         if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
19068             if (horizontalFadingEdgeEnabled) {
19069                 initScrollCache();
19070             }
19071 
19072             mViewFlags ^= FADING_EDGE_HORIZONTAL;
19073         }
19074     }
19075 
19076     /**
19077      * <p>Indicate whether the vertical edges are faded when the view is
19078      * scrolled horizontally.</p>
19079      *
19080      * @return true if the vertical edges should are faded on scroll, false
19081      *         otherwise
19082      *
19083      * @see #setVerticalFadingEdgeEnabled(boolean)
19084      *
19085      * @attr ref android.R.styleable#View_requiresFadingEdge
19086      */
isVerticalFadingEdgeEnabled()19087     public boolean isVerticalFadingEdgeEnabled() {
19088         return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
19089     }
19090 
19091     /**
19092      * <p>Define whether the vertical edges should be faded when this view
19093      * is scrolled vertically.</p>
19094      *
19095      * @param verticalFadingEdgeEnabled true if the vertical edges should
19096      *                                  be faded when the view is scrolled
19097      *                                  vertically
19098      *
19099      * @see #isVerticalFadingEdgeEnabled()
19100      *
19101      * @attr ref android.R.styleable#View_requiresFadingEdge
19102      */
setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled)19103     public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
19104         if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
19105             if (verticalFadingEdgeEnabled) {
19106                 initScrollCache();
19107             }
19108 
19109             mViewFlags ^= FADING_EDGE_VERTICAL;
19110         }
19111     }
19112 
19113     /**
19114      * Get the fading edge flags, used for inspection.
19115      *
19116      * @return One of {@link #FADING_EDGE_NONE}, {@link #FADING_EDGE_VERTICAL},
19117      *         or {@link #FADING_EDGE_HORIZONTAL}
19118      * @hide
19119      */
19120     @InspectableProperty(name = "requiresFadingEdge", flagMapping = {
19121             @FlagEntry(target = FADING_EDGE_NONE, mask = FADING_EDGE_MASK, name = "none"),
19122             @FlagEntry(target = FADING_EDGE_VERTICAL, name = "vertical"),
19123             @FlagEntry(target = FADING_EDGE_HORIZONTAL, name = "horizontal")
19124     })
getFadingEdge()19125     public int getFadingEdge() {
19126         return mViewFlags & FADING_EDGE_MASK;
19127     }
19128 
19129     /**
19130      * Get the fading edge length, used for inspection
19131      *
19132      * @return The fading edge length or 0
19133      * @hide
19134      */
19135     @InspectableProperty
getFadingEdgeLength()19136     public int getFadingEdgeLength() {
19137         if (mScrollCache != null && (mViewFlags & FADING_EDGE_MASK) != FADING_EDGE_NONE) {
19138             return mScrollCache.fadingEdgeLength;
19139         }
19140         return 0;
19141     }
19142 
19143     /**
19144      * Returns the strength, or intensity, of the top faded edge. The strength is
19145      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
19146      * returns 0.0 or 1.0 but no value in between.
19147      *
19148      * Subclasses should override this method to provide a smoother fade transition
19149      * when scrolling occurs.
19150      *
19151      * @return the intensity of the top fade as a float between 0.0f and 1.0f
19152      */
getTopFadingEdgeStrength()19153     protected float getTopFadingEdgeStrength() {
19154         return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
19155     }
19156 
19157     /**
19158      * Returns the strength, or intensity, of the bottom faded edge. The strength is
19159      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
19160      * returns 0.0 or 1.0 but no value in between.
19161      *
19162      * Subclasses should override this method to provide a smoother fade transition
19163      * when scrolling occurs.
19164      *
19165      * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
19166      */
getBottomFadingEdgeStrength()19167     protected float getBottomFadingEdgeStrength() {
19168         return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
19169                 computeVerticalScrollRange() ? 1.0f : 0.0f;
19170     }
19171 
19172     /**
19173      * Returns the strength, or intensity, of the left faded edge. The strength is
19174      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
19175      * returns 0.0 or 1.0 but no value in between.
19176      *
19177      * Subclasses should override this method to provide a smoother fade transition
19178      * when scrolling occurs.
19179      *
19180      * @return the intensity of the left fade as a float between 0.0f and 1.0f
19181      */
getLeftFadingEdgeStrength()19182     protected float getLeftFadingEdgeStrength() {
19183         return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
19184     }
19185 
19186     /**
19187      * Returns the strength, or intensity, of the right faded edge. The strength is
19188      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
19189      * returns 0.0 or 1.0 but no value in between.
19190      *
19191      * Subclasses should override this method to provide a smoother fade transition
19192      * when scrolling occurs.
19193      *
19194      * @return the intensity of the right fade as a float between 0.0f and 1.0f
19195      */
getRightFadingEdgeStrength()19196     protected float getRightFadingEdgeStrength() {
19197         return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
19198                 computeHorizontalScrollRange() ? 1.0f : 0.0f;
19199     }
19200 
19201     /**
19202      * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
19203      * scrollbar is not drawn by default.</p>
19204      *
19205      * @return true if the horizontal scrollbar should be painted, false
19206      *         otherwise
19207      *
19208      * @see #setHorizontalScrollBarEnabled(boolean)
19209      */
isHorizontalScrollBarEnabled()19210     public boolean isHorizontalScrollBarEnabled() {
19211         return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
19212     }
19213 
19214     /**
19215      * <p>Define whether the horizontal scrollbar should be drawn or not. The
19216      * scrollbar is not drawn by default.</p>
19217      *
19218      * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
19219      *                                   be painted
19220      *
19221      * @see #isHorizontalScrollBarEnabled()
19222      */
setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled)19223     public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
19224         if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
19225             mViewFlags ^= SCROLLBARS_HORIZONTAL;
19226             computeOpaqueFlags();
19227             resolvePadding();
19228         }
19229     }
19230 
19231     /**
19232      * <p>Indicate whether the vertical scrollbar should be drawn or not. The
19233      * scrollbar is not drawn by default.</p>
19234      *
19235      * @return true if the vertical scrollbar should be painted, false
19236      *         otherwise
19237      *
19238      * @see #setVerticalScrollBarEnabled(boolean)
19239      */
isVerticalScrollBarEnabled()19240     public boolean isVerticalScrollBarEnabled() {
19241         return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
19242     }
19243 
19244     /**
19245      * <p>Define whether the vertical scrollbar should be drawn or not. The
19246      * scrollbar is not drawn by default.</p>
19247      *
19248      * @param verticalScrollBarEnabled true if the vertical scrollbar should
19249      *                                 be painted
19250      *
19251      * @see #isVerticalScrollBarEnabled()
19252      */
setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled)19253     public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
19254         if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
19255             mViewFlags ^= SCROLLBARS_VERTICAL;
19256             computeOpaqueFlags();
19257             resolvePadding();
19258         }
19259     }
19260 
19261     /**
19262      * @hide
19263      */
19264     @UnsupportedAppUsage
recomputePadding()19265     protected void recomputePadding() {
19266         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
19267     }
19268 
19269     /**
19270      * Define whether scrollbars will fade when the view is not scrolling.
19271      *
19272      * @param fadeScrollbars whether to enable fading
19273      *
19274      * @attr ref android.R.styleable#View_fadeScrollbars
19275      */
setScrollbarFadingEnabled(boolean fadeScrollbars)19276     public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
19277         initScrollCache();
19278         final ScrollabilityCache scrollabilityCache = mScrollCache;
19279         scrollabilityCache.fadeScrollBars = fadeScrollbars;
19280         if (fadeScrollbars) {
19281             scrollabilityCache.state = ScrollabilityCache.OFF;
19282         } else {
19283             scrollabilityCache.state = ScrollabilityCache.ON;
19284         }
19285     }
19286 
19287     /**
19288      *
19289      * Returns true if scrollbars will fade when this view is not scrolling
19290      *
19291      * @return true if scrollbar fading is enabled
19292      *
19293      * @attr ref android.R.styleable#View_fadeScrollbars
19294      */
isScrollbarFadingEnabled()19295     public boolean isScrollbarFadingEnabled() {
19296         return mScrollCache != null && mScrollCache.fadeScrollBars;
19297     }
19298 
19299     /**
19300      *
19301      * Returns the delay before scrollbars fade.
19302      *
19303      * @return the delay before scrollbars fade
19304      *
19305      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
19306      */
19307     @InspectableProperty(name = "scrollbarDefaultDelayBeforeFade")
getScrollBarDefaultDelayBeforeFade()19308     public int getScrollBarDefaultDelayBeforeFade() {
19309         return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
19310                 mScrollCache.scrollBarDefaultDelayBeforeFade;
19311     }
19312 
19313     /**
19314      * Define the delay before scrollbars fade.
19315      *
19316      * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
19317      *
19318      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
19319      */
setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade)19320     public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
19321         getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
19322     }
19323 
19324     /**
19325      *
19326      * Returns the scrollbar fade duration.
19327      *
19328      * @return the scrollbar fade duration, in milliseconds
19329      *
19330      * @attr ref android.R.styleable#View_scrollbarFadeDuration
19331      */
19332     @InspectableProperty(name = "scrollbarFadeDuration")
getScrollBarFadeDuration()19333     public int getScrollBarFadeDuration() {
19334         return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
19335                 mScrollCache.scrollBarFadeDuration;
19336     }
19337 
19338     /**
19339      * Define the scrollbar fade duration.
19340      *
19341      * @param scrollBarFadeDuration - the scrollbar fade duration, in milliseconds
19342      *
19343      * @attr ref android.R.styleable#View_scrollbarFadeDuration
19344      */
setScrollBarFadeDuration(int scrollBarFadeDuration)19345     public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
19346         getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
19347     }
19348 
19349     /**
19350      *
19351      * Returns the scrollbar size.
19352      *
19353      * @return the scrollbar size
19354      *
19355      * @attr ref android.R.styleable#View_scrollbarSize
19356      */
19357     @InspectableProperty(name = "scrollbarSize")
getScrollBarSize()19358     public int getScrollBarSize() {
19359         return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
19360                 mScrollCache.scrollBarSize;
19361     }
19362 
19363     /**
19364      * Define the scrollbar size.
19365      *
19366      * @param scrollBarSize - the scrollbar size
19367      *
19368      * @attr ref android.R.styleable#View_scrollbarSize
19369      */
setScrollBarSize(int scrollBarSize)19370     public void setScrollBarSize(int scrollBarSize) {
19371         getScrollCache().scrollBarSize = scrollBarSize;
19372     }
19373 
19374     /**
19375      * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
19376      * inset. When inset, they add to the padding of the view. And the scrollbars
19377      * can be drawn inside the padding area or on the edge of the view. For example,
19378      * if a view has a background drawable and you want to draw the scrollbars
19379      * inside the padding specified by the drawable, you can use
19380      * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
19381      * appear at the edge of the view, ignoring the padding, then you can use
19382      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
19383      * @param style the style of the scrollbars. Should be one of
19384      * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
19385      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
19386      * @see #SCROLLBARS_INSIDE_OVERLAY
19387      * @see #SCROLLBARS_INSIDE_INSET
19388      * @see #SCROLLBARS_OUTSIDE_OVERLAY
19389      * @see #SCROLLBARS_OUTSIDE_INSET
19390      *
19391      * @attr ref android.R.styleable#View_scrollbarStyle
19392      */
setScrollBarStyle(@crollBarStyle int style)19393     public void setScrollBarStyle(@ScrollBarStyle int style) {
19394         if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
19395             mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
19396             computeOpaqueFlags();
19397             resolvePadding();
19398         }
19399     }
19400 
19401     /**
19402      * <p>Returns the current scrollbar style.</p>
19403      * @return the current scrollbar style
19404      * @see #SCROLLBARS_INSIDE_OVERLAY
19405      * @see #SCROLLBARS_INSIDE_INSET
19406      * @see #SCROLLBARS_OUTSIDE_OVERLAY
19407      * @see #SCROLLBARS_OUTSIDE_INSET
19408      *
19409      * @attr ref android.R.styleable#View_scrollbarStyle
19410      */
19411     @ViewDebug.ExportedProperty(mapping = {
19412             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
19413             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
19414             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
19415             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
19416     })
19417     @InspectableProperty(name = "scrollbarStyle", enumMapping = {
19418             @EnumEntry(value = SCROLLBARS_INSIDE_OVERLAY, name = "insideOverlay"),
19419             @EnumEntry(value = SCROLLBARS_INSIDE_INSET, name = "insideInset"),
19420             @EnumEntry(value = SCROLLBARS_OUTSIDE_OVERLAY, name = "outsideOverlay"),
19421             @EnumEntry(value = SCROLLBARS_OUTSIDE_INSET, name = "outsideInset")
19422     })
19423     @ScrollBarStyle
getScrollBarStyle()19424     public int getScrollBarStyle() {
19425         return mViewFlags & SCROLLBARS_STYLE_MASK;
19426     }
19427 
19428     /**
19429      * <p>Compute the horizontal range that the horizontal scrollbar
19430      * represents.</p>
19431      *
19432      * <p>The range is expressed in arbitrary units that must be the same as the
19433      * units used by {@link #computeHorizontalScrollExtent()} and
19434      * {@link #computeHorizontalScrollOffset()}.</p>
19435      *
19436      * <p>The default range is the drawing width of this view.</p>
19437      *
19438      * @return the total horizontal range represented by the horizontal
19439      *         scrollbar
19440      *
19441      * @see #computeHorizontalScrollExtent()
19442      * @see #computeHorizontalScrollOffset()
19443      */
computeHorizontalScrollRange()19444     protected int computeHorizontalScrollRange() {
19445         return getWidth();
19446     }
19447 
19448     /**
19449      * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
19450      * within the horizontal range. This value is used to compute the position
19451      * of the thumb within the scrollbar's track.</p>
19452      *
19453      * <p>The range is expressed in arbitrary units that must be the same as the
19454      * units used by {@link #computeHorizontalScrollRange()} and
19455      * {@link #computeHorizontalScrollExtent()}.</p>
19456      *
19457      * <p>The default offset is the scroll offset of this view.</p>
19458      *
19459      * @return the horizontal offset of the scrollbar's thumb
19460      *
19461      * @see #computeHorizontalScrollRange()
19462      * @see #computeHorizontalScrollExtent()
19463      */
computeHorizontalScrollOffset()19464     protected int computeHorizontalScrollOffset() {
19465         return mScrollX;
19466     }
19467 
19468     /**
19469      * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
19470      * within the horizontal range. This value is used to compute the length
19471      * of the thumb within the scrollbar's track.</p>
19472      *
19473      * <p>The range is expressed in arbitrary units that must be the same as the
19474      * units used by {@link #computeHorizontalScrollRange()} and
19475      * {@link #computeHorizontalScrollOffset()}.</p>
19476      *
19477      * <p>The default extent is the drawing width of this view.</p>
19478      *
19479      * @return the horizontal extent of the scrollbar's thumb
19480      *
19481      * @see #computeHorizontalScrollRange()
19482      * @see #computeHorizontalScrollOffset()
19483      */
computeHorizontalScrollExtent()19484     protected int computeHorizontalScrollExtent() {
19485         return getWidth();
19486     }
19487 
19488     /**
19489      * <p>Compute the vertical range that the vertical scrollbar represents.</p>
19490      *
19491      * <p>The range is expressed in arbitrary units that must be the same as the
19492      * units used by {@link #computeVerticalScrollExtent()} and
19493      * {@link #computeVerticalScrollOffset()}.</p>
19494      *
19495      * @return the total vertical range represented by the vertical scrollbar
19496      *
19497      * <p>The default range is the drawing height of this view.</p>
19498      *
19499      * @see #computeVerticalScrollExtent()
19500      * @see #computeVerticalScrollOffset()
19501      */
computeVerticalScrollRange()19502     protected int computeVerticalScrollRange() {
19503         return getHeight();
19504     }
19505 
19506     /**
19507      * <p>Compute the vertical offset of the vertical scrollbar's thumb
19508      * within the horizontal range. This value is used to compute the position
19509      * of the thumb within the scrollbar's track.</p>
19510      *
19511      * <p>The range is expressed in arbitrary units that must be the same as the
19512      * units used by {@link #computeVerticalScrollRange()} and
19513      * {@link #computeVerticalScrollExtent()}.</p>
19514      *
19515      * <p>The default offset is the scroll offset of this view.</p>
19516      *
19517      * @return the vertical offset of the scrollbar's thumb
19518      *
19519      * @see #computeVerticalScrollRange()
19520      * @see #computeVerticalScrollExtent()
19521      */
computeVerticalScrollOffset()19522     protected int computeVerticalScrollOffset() {
19523         return mScrollY;
19524     }
19525 
19526     /**
19527      * <p>Compute the vertical extent of the vertical scrollbar's thumb
19528      * within the vertical range. This value is used to compute the length
19529      * of the thumb within the scrollbar's track.</p>
19530      *
19531      * <p>The range is expressed in arbitrary units that must be the same as the
19532      * units used by {@link #computeVerticalScrollRange()} and
19533      * {@link #computeVerticalScrollOffset()}.</p>
19534      *
19535      * <p>The default extent is the drawing height of this view.</p>
19536      *
19537      * @return the vertical extent of the scrollbar's thumb
19538      *
19539      * @see #computeVerticalScrollRange()
19540      * @see #computeVerticalScrollOffset()
19541      */
computeVerticalScrollExtent()19542     protected int computeVerticalScrollExtent() {
19543         return getHeight();
19544     }
19545 
19546     /**
19547      * Check if this view can be scrolled horizontally in a certain direction.
19548      *
19549      * @param direction Negative to check scrolling left, positive to check scrolling right.
19550      * @return true if this view can be scrolled in the specified direction, false otherwise.
19551      */
canScrollHorizontally(int direction)19552     public boolean canScrollHorizontally(int direction) {
19553         final int offset = computeHorizontalScrollOffset();
19554         final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
19555         if (range == 0) return false;
19556         if (direction < 0) {
19557             return offset > 0;
19558         } else {
19559             return offset < range - 1;
19560         }
19561     }
19562 
19563     /**
19564      * Check if this view can be scrolled vertically in a certain direction.
19565      *
19566      * @param direction Negative to check scrolling up, positive to check scrolling down.
19567      * @return true if this view can be scrolled in the specified direction, false otherwise.
19568      */
canScrollVertically(int direction)19569     public boolean canScrollVertically(int direction) {
19570         final int offset = computeVerticalScrollOffset();
19571         final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
19572         if (range == 0) return false;
19573         if (direction < 0) {
19574             return offset > 0;
19575         } else {
19576             return offset < range - 1;
19577         }
19578     }
19579 
getScrollIndicatorBounds(@onNull Rect out)19580     void getScrollIndicatorBounds(@NonNull Rect out) {
19581         out.left = mScrollX;
19582         out.right = mScrollX + mRight - mLeft;
19583         out.top = mScrollY;
19584         out.bottom = mScrollY + mBottom - mTop;
19585     }
19586 
onDrawScrollIndicators(Canvas c)19587     private void onDrawScrollIndicators(Canvas c) {
19588         if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
19589             // No scroll indicators enabled.
19590             return;
19591         }
19592 
19593         final Drawable dr = mScrollIndicatorDrawable;
19594         if (dr == null) {
19595             // Scroll indicators aren't supported here.
19596             return;
19597         }
19598 
19599         final int h = dr.getIntrinsicHeight();
19600         final int w = dr.getIntrinsicWidth();
19601         final Rect rect = mAttachInfo.mTmpInvalRect;
19602         getScrollIndicatorBounds(rect);
19603 
19604         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
19605             final boolean canScrollUp = canScrollVertically(-1);
19606             if (canScrollUp) {
19607                 dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
19608                 dr.draw(c);
19609             }
19610         }
19611 
19612         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
19613             final boolean canScrollDown = canScrollVertically(1);
19614             if (canScrollDown) {
19615                 dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
19616                 dr.draw(c);
19617             }
19618         }
19619 
19620         final int leftRtl;
19621         final int rightRtl;
19622         if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
19623             leftRtl = PFLAG3_SCROLL_INDICATOR_END;
19624             rightRtl = PFLAG3_SCROLL_INDICATOR_START;
19625         } else {
19626             leftRtl = PFLAG3_SCROLL_INDICATOR_START;
19627             rightRtl = PFLAG3_SCROLL_INDICATOR_END;
19628         }
19629 
19630         final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
19631         if ((mPrivateFlags3 & leftMask) != 0) {
19632             final boolean canScrollLeft = canScrollHorizontally(-1);
19633             if (canScrollLeft) {
19634                 dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
19635                 dr.draw(c);
19636             }
19637         }
19638 
19639         final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
19640         if ((mPrivateFlags3 & rightMask) != 0) {
19641             final boolean canScrollRight = canScrollHorizontally(1);
19642             if (canScrollRight) {
19643                 dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
19644                 dr.draw(c);
19645             }
19646         }
19647     }
19648 
getHorizontalScrollBarBounds(@ullable Rect drawBounds, @Nullable Rect touchBounds)19649     private void getHorizontalScrollBarBounds(@Nullable Rect drawBounds,
19650             @Nullable Rect touchBounds) {
19651         final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
19652         if (bounds == null) {
19653             return;
19654         }
19655         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
19656         final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
19657                 && !isVerticalScrollBarHidden();
19658         final int size = getHorizontalScrollbarHeight();
19659         final int verticalScrollBarGap = drawVerticalScrollBar ?
19660                 getVerticalScrollbarWidth() : 0;
19661         final int width = mRight - mLeft;
19662         final int height = mBottom - mTop;
19663         bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
19664         bounds.left = mScrollX + (mPaddingLeft & inside);
19665         bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
19666         bounds.bottom = bounds.top + size;
19667 
19668         if (touchBounds == null) {
19669             return;
19670         }
19671         if (touchBounds != bounds) {
19672             touchBounds.set(bounds);
19673         }
19674         final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
19675         if (touchBounds.height() < minTouchTarget) {
19676             final int adjust = (minTouchTarget - touchBounds.height()) / 2;
19677             touchBounds.bottom = Math.min(touchBounds.bottom + adjust, mScrollY + height);
19678             touchBounds.top = touchBounds.bottom - minTouchTarget;
19679         }
19680         if (touchBounds.width() < minTouchTarget) {
19681             final int adjust = (minTouchTarget - touchBounds.width()) / 2;
19682             touchBounds.left -= adjust;
19683             touchBounds.right = touchBounds.left + minTouchTarget;
19684         }
19685     }
19686 
getVerticalScrollBarBounds(@ullable Rect bounds, @Nullable Rect touchBounds)19687     private void getVerticalScrollBarBounds(@Nullable Rect bounds, @Nullable Rect touchBounds) {
19688         if (mRoundScrollbarRenderer == null) {
19689             getStraightVerticalScrollBarBounds(bounds, touchBounds);
19690         } else {
19691             getRoundVerticalScrollBarBounds(bounds != null ? bounds : touchBounds);
19692         }
19693     }
19694 
getRoundVerticalScrollBarBounds(Rect bounds)19695     private void getRoundVerticalScrollBarBounds(Rect bounds) {
19696         final int width = mRight - mLeft;
19697         final int height = mBottom - mTop;
19698         // Do not take padding into account as we always want the scrollbars
19699         // to hug the screen for round wearable devices.
19700         bounds.left = mScrollX;
19701         bounds.top = mScrollY;
19702         bounds.right = bounds.left + width;
19703         bounds.bottom = mScrollY + height;
19704     }
19705 
getStraightVerticalScrollBarBounds(@ullable Rect drawBounds, @Nullable Rect touchBounds)19706     private void getStraightVerticalScrollBarBounds(@Nullable Rect drawBounds,
19707             @Nullable Rect touchBounds) {
19708         final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
19709         if (bounds == null) {
19710             return;
19711         }
19712         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
19713         final int size = getVerticalScrollbarWidth();
19714         int verticalScrollbarPosition = mVerticalScrollbarPosition;
19715         if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
19716             verticalScrollbarPosition = isLayoutRtl() ?
19717                     SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
19718         }
19719         final int width = mRight - mLeft;
19720         final int height = mBottom - mTop;
19721         switch (verticalScrollbarPosition) {
19722             default:
19723             case SCROLLBAR_POSITION_RIGHT:
19724                 bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
19725                 break;
19726             case SCROLLBAR_POSITION_LEFT:
19727                 bounds.left = mScrollX + (mUserPaddingLeft & inside);
19728                 break;
19729         }
19730         bounds.top = mScrollY + (mPaddingTop & inside);
19731         bounds.right = bounds.left + size;
19732         bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
19733 
19734         if (touchBounds == null) {
19735             return;
19736         }
19737         if (touchBounds != bounds) {
19738             touchBounds.set(bounds);
19739         }
19740         final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
19741         if (touchBounds.width() < minTouchTarget) {
19742             final int adjust = (minTouchTarget - touchBounds.width()) / 2;
19743             if (verticalScrollbarPosition == SCROLLBAR_POSITION_RIGHT) {
19744                 touchBounds.right = Math.min(touchBounds.right + adjust, mScrollX + width);
19745                 touchBounds.left = touchBounds.right - minTouchTarget;
19746             } else {
19747                 touchBounds.left = Math.max(touchBounds.left + adjust, mScrollX);
19748                 touchBounds.right = touchBounds.left + minTouchTarget;
19749             }
19750         }
19751         if (touchBounds.height() < minTouchTarget) {
19752             final int adjust = (minTouchTarget - touchBounds.height()) / 2;
19753             touchBounds.top -= adjust;
19754             touchBounds.bottom = touchBounds.top + minTouchTarget;
19755         }
19756     }
19757 
19758     /**
19759      * <p>Request the drawing of the horizontal and the vertical scrollbar. The
19760      * scrollbars are painted only if they have been awakened first.</p>
19761      *
19762      * @param canvas the canvas on which to draw the scrollbars
19763      *
19764      * @see #awakenScrollBars(int)
19765      */
onDrawScrollBars(Canvas canvas)19766     protected final void onDrawScrollBars(Canvas canvas) {
19767         // scrollbars are drawn only when the animation is running
19768         final ScrollabilityCache cache = mScrollCache;
19769 
19770         if (cache != null) {
19771 
19772             int state = cache.state;
19773 
19774             if (state == ScrollabilityCache.OFF) {
19775                 return;
19776             }
19777 
19778             boolean invalidate = false;
19779 
19780             if (state == ScrollabilityCache.FADING) {
19781                 // We're fading -- get our fade interpolation
19782                 if (cache.interpolatorValues == null) {
19783                     cache.interpolatorValues = new float[1];
19784                 }
19785 
19786                 float[] values = cache.interpolatorValues;
19787 
19788                 // Stops the animation if we're done
19789                 if (cache.scrollBarInterpolator.timeToValues(values) ==
19790                         Interpolator.Result.FREEZE_END) {
19791                     cache.state = ScrollabilityCache.OFF;
19792                 } else {
19793                     cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
19794                 }
19795 
19796                 // This will make the scroll bars inval themselves after
19797                 // drawing. We only want this when we're fading so that
19798                 // we prevent excessive redraws
19799                 invalidate = true;
19800             } else {
19801                 // We're just on -- but we may have been fading before so
19802                 // reset alpha
19803                 cache.scrollBar.mutate().setAlpha(255);
19804             }
19805 
19806             final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
19807             final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
19808                     && !isVerticalScrollBarHidden();
19809 
19810             // Fork out the scroll bar drawing for round wearable devices.
19811             if (mRoundScrollbarRenderer != null) {
19812                 if (drawVerticalScrollBar) {
19813                     final Rect bounds = cache.mScrollBarBounds;
19814                     getVerticalScrollBarBounds(bounds, null);
19815                     mRoundScrollbarRenderer.drawRoundScrollbars(
19816                             canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
19817                     if (invalidate) {
19818                         invalidate();
19819                     }
19820                 }
19821                 // Do not draw horizontal scroll bars for round wearable devices.
19822             } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
19823                 final ScrollBarDrawable scrollBar = cache.scrollBar;
19824 
19825                 if (drawHorizontalScrollBar) {
19826                     scrollBar.setParameters(computeHorizontalScrollRange(),
19827                             computeHorizontalScrollOffset(),
19828                             computeHorizontalScrollExtent(), false);
19829                     final Rect bounds = cache.mScrollBarBounds;
19830                     getHorizontalScrollBarBounds(bounds, null);
19831                     onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
19832                             bounds.right, bounds.bottom);
19833                     if (invalidate) {
19834                         invalidate(bounds);
19835                     }
19836                 }
19837 
19838                 if (drawVerticalScrollBar) {
19839                     scrollBar.setParameters(computeVerticalScrollRange(),
19840                             computeVerticalScrollOffset(),
19841                             computeVerticalScrollExtent(), true);
19842                     final Rect bounds = cache.mScrollBarBounds;
19843                     getVerticalScrollBarBounds(bounds, null);
19844                     onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
19845                             bounds.right, bounds.bottom);
19846                     if (invalidate) {
19847                         invalidate(bounds);
19848                     }
19849                 }
19850             }
19851         }
19852     }
19853 
19854     /**
19855      * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
19856      * FastScroller is visible.
19857      * @return whether to temporarily hide the vertical scrollbar
19858      * @hide
19859      */
isVerticalScrollBarHidden()19860     protected boolean isVerticalScrollBarHidden() {
19861         return false;
19862     }
19863 
19864     /**
19865      * <p>Draw the horizontal scrollbar if
19866      * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
19867      *
19868      * @param canvas the canvas on which to draw the scrollbar
19869      * @param scrollBar the scrollbar's drawable
19870      *
19871      * @see #isHorizontalScrollBarEnabled()
19872      * @see #computeHorizontalScrollRange()
19873      * @see #computeHorizontalScrollExtent()
19874      * @see #computeHorizontalScrollOffset()
19875      * @hide
19876      */
19877     @UnsupportedAppUsage
onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t, int r, int b)19878     protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
19879             int l, int t, int r, int b) {
19880         scrollBar.setBounds(l, t, r, b);
19881         scrollBar.draw(canvas);
19882     }
19883 
19884     /**
19885      * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
19886      * returns true.</p>
19887      *
19888      * @param canvas the canvas on which to draw the scrollbar
19889      * @param scrollBar the scrollbar's drawable
19890      *
19891      * @see #isVerticalScrollBarEnabled()
19892      * @see #computeVerticalScrollRange()
19893      * @see #computeVerticalScrollExtent()
19894      * @see #computeVerticalScrollOffset()
19895      * @hide
19896      */
19897     @UnsupportedAppUsage
onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t, int r, int b)19898     protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
19899             int l, int t, int r, int b) {
19900         scrollBar.setBounds(l, t, r, b);
19901         scrollBar.draw(canvas);
19902     }
19903 
19904     /**
19905      * Implement this to do your drawing.
19906      *
19907      * @param canvas the canvas on which the background will be drawn
19908      */
onDraw(Canvas canvas)19909     protected void onDraw(Canvas canvas) {
19910     }
19911 
19912     /*
19913      * Caller is responsible for calling requestLayout if necessary.
19914      * (This allows addViewInLayout to not request a new layout.)
19915      */
19916     @UnsupportedAppUsage
assignParent(ViewParent parent)19917     void assignParent(ViewParent parent) {
19918         if (mParent == null) {
19919             mParent = parent;
19920         } else if (parent == null) {
19921             mParent = null;
19922         } else {
19923             throw new RuntimeException("view " + this + " being added, but"
19924                     + " it already has a parent");
19925         }
19926     }
19927 
19928     /**
19929      * This is called when the view is attached to a window.  At this point it
19930      * has a Surface and will start drawing.  Note that this function is
19931      * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
19932      * however it may be called any time before the first onDraw -- including
19933      * before or after {@link #onMeasure(int, int)}.
19934      *
19935      * @see #onDetachedFromWindow()
19936      */
19937     @CallSuper
onAttachedToWindow()19938     protected void onAttachedToWindow() {
19939         if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
19940             mParent.requestTransparentRegion(this);
19941         }
19942 
19943         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
19944 
19945         jumpDrawablesToCurrentState();
19946 
19947         AccessibilityNodeIdManager.getInstance().registerViewWithId(this, getAccessibilityViewId());
19948         resetSubtreeAccessibilityStateChanged();
19949 
19950         // rebuild, since Outline not maintained while View is detached
19951         rebuildOutline();
19952 
19953         if (isFocused()) {
19954             notifyFocusChangeToImeFocusController(true /* hasFocus */);
19955         }
19956     }
19957 
19958     /**
19959      * Resolve all RTL related properties.
19960      *
19961      * @return true if resolution of RTL properties has been done
19962      *
19963      * @hide
19964      */
resolveRtlPropertiesIfNeeded()19965     public boolean resolveRtlPropertiesIfNeeded() {
19966         if (!needRtlPropertiesResolution()) return false;
19967 
19968         // Order is important here: LayoutDirection MUST be resolved first
19969         if (!isLayoutDirectionResolved()) {
19970             resolveLayoutDirection();
19971             resolveLayoutParams();
19972         }
19973         // ... then we can resolve the others properties depending on the resolved LayoutDirection.
19974         if (!isTextDirectionResolved()) {
19975             resolveTextDirection();
19976         }
19977         if (!isTextAlignmentResolved()) {
19978             resolveTextAlignment();
19979         }
19980         // Should resolve Drawables before Padding because we need the layout direction of the
19981         // Drawable to correctly resolve Padding.
19982         if (!areDrawablesResolved()) {
19983             resolveDrawables();
19984         }
19985         if (!isPaddingResolved()) {
19986             resolvePadding();
19987         }
19988         onRtlPropertiesChanged(getLayoutDirection());
19989         return true;
19990     }
19991 
19992     /**
19993      * Reset resolution of all RTL related properties.
19994      *
19995      * @hide
19996      */
19997     @TestApi
resetRtlProperties()19998     public void resetRtlProperties() {
19999         resetResolvedLayoutDirection();
20000         resetResolvedTextDirection();
20001         resetResolvedTextAlignment();
20002         resetResolvedPadding();
20003         resetResolvedDrawables();
20004     }
20005 
20006     /**
20007      * @see #onScreenStateChanged(int)
20008      */
dispatchScreenStateChanged(int screenState)20009     void dispatchScreenStateChanged(int screenState) {
20010         onScreenStateChanged(screenState);
20011     }
20012 
20013     /**
20014      * This method is called whenever the state of the screen this view is
20015      * attached to changes. A state change will usually occurs when the screen
20016      * turns on or off (whether it happens automatically or the user does it
20017      * manually.)
20018      *
20019      * @param screenState The new state of the screen. Can be either
20020      *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
20021      */
onScreenStateChanged(int screenState)20022     public void onScreenStateChanged(int screenState) {
20023     }
20024 
20025     /**
20026      * @see #onMovedToDisplay(int, Configuration)
20027      */
dispatchMovedToDisplay(Display display, Configuration config)20028     void dispatchMovedToDisplay(Display display, Configuration config) {
20029         mAttachInfo.mDisplay = display;
20030         mAttachInfo.mDisplayState = display.getState();
20031         onMovedToDisplay(display.getDisplayId(), config);
20032     }
20033 
20034     /**
20035      * Called by the system when the hosting activity is moved from one display to another without
20036      * recreation. This means that the activity is declared to handle all changes to configuration
20037      * that happened when it was switched to another display, so it wasn't destroyed and created
20038      * again.
20039      *
20040      * <p>This call will be followed by {@link #onConfigurationChanged(Configuration)} if the
20041      * applied configuration actually changed. It is up to app developer to choose whether to handle
20042      * the change in this method or in the following {@link #onConfigurationChanged(Configuration)}
20043      * call.
20044      *
20045      * <p>Use this callback to track changes to the displays if some functionality relies on an
20046      * association with some display properties.
20047      *
20048      * @param displayId The id of the display to which the view was moved.
20049      * @param config Configuration of the resources on new display after move.
20050      *
20051      * @see #onConfigurationChanged(Configuration)
20052      * @hide
20053      */
onMovedToDisplay(int displayId, Configuration config)20054     public void onMovedToDisplay(int displayId, Configuration config) {
20055     }
20056 
20057     /**
20058      * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
20059      */
20060     @UnsupportedAppUsage
hasRtlSupport()20061     private boolean hasRtlSupport() {
20062         return mContext.getApplicationInfo().hasRtlSupport();
20063     }
20064 
20065     /**
20066      * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
20067      * RTL not supported)
20068      */
isRtlCompatibilityMode()20069     private boolean isRtlCompatibilityMode() {
20070         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
20071         return targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1 || !hasRtlSupport();
20072     }
20073 
20074     /**
20075      * @return true if RTL properties need resolution.
20076      *
20077      */
needRtlPropertiesResolution()20078     private boolean needRtlPropertiesResolution() {
20079         return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
20080     }
20081 
20082     /**
20083      * Called when any RTL property (layout direction or text direction or text alignment) has
20084      * been changed.
20085      *
20086      * Subclasses need to override this method to take care of cached information that depends on the
20087      * resolved layout direction, or to inform child views that inherit their layout direction.
20088      *
20089      * The default implementation does nothing.
20090      *
20091      * @param layoutDirection the direction of the layout
20092      *
20093      * @see #LAYOUT_DIRECTION_LTR
20094      * @see #LAYOUT_DIRECTION_RTL
20095      */
onRtlPropertiesChanged(@esolvedLayoutDir int layoutDirection)20096     public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
20097     }
20098 
20099     /**
20100      * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
20101      * that the parent directionality can and will be resolved before its children.
20102      *
20103      * @return true if resolution has been done, false otherwise.
20104      *
20105      * @hide
20106      */
resolveLayoutDirection()20107     public boolean resolveLayoutDirection() {
20108         // Clear any previous layout direction resolution
20109         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
20110 
20111         if (hasRtlSupport()) {
20112             // Set resolved depending on layout direction
20113             switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
20114                     PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
20115                 case LAYOUT_DIRECTION_INHERIT:
20116                     // We cannot resolve yet. LTR is by default and let the resolution happen again
20117                     // later to get the correct resolved value
20118                     if (!canResolveLayoutDirection()) return false;
20119 
20120                     // Parent has not yet resolved, LTR is still the default
20121                     try {
20122                         if (!mParent.isLayoutDirectionResolved()) return false;
20123 
20124                         if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
20125                             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
20126                         }
20127                     } catch (AbstractMethodError e) {
20128                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20129                                 " does not fully implement ViewParent", e);
20130                     }
20131                     break;
20132                 case LAYOUT_DIRECTION_RTL:
20133                     mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
20134                     break;
20135                 case LAYOUT_DIRECTION_LOCALE:
20136                     if((LAYOUT_DIRECTION_RTL ==
20137                             TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
20138                         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
20139                     }
20140                     break;
20141                 default:
20142                     // Nothing to do, LTR by default
20143             }
20144         }
20145 
20146         // Set to resolved
20147         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
20148         return true;
20149     }
20150 
20151     /**
20152      * Check if layout direction resolution can be done.
20153      *
20154      * @return true if layout direction resolution can be done otherwise return false.
20155      */
canResolveLayoutDirection()20156     public boolean canResolveLayoutDirection() {
20157         switch (getRawLayoutDirection()) {
20158             case LAYOUT_DIRECTION_INHERIT:
20159                 if (mParent != null) {
20160                     try {
20161                         return mParent.canResolveLayoutDirection();
20162                     } catch (AbstractMethodError e) {
20163                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20164                                 " does not fully implement ViewParent", e);
20165                     }
20166                 }
20167                 return false;
20168 
20169             default:
20170                 return true;
20171         }
20172     }
20173 
20174     /**
20175      * Reset the resolved layout direction. Layout direction will be resolved during a call to
20176      * {@link #onMeasure(int, int)}.
20177      *
20178      * @hide
20179      */
20180     @TestApi
resetResolvedLayoutDirection()20181     public void resetResolvedLayoutDirection() {
20182         // Reset the current resolved bits
20183         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
20184     }
20185 
20186     /**
20187      * @return true if the layout direction is inherited.
20188      *
20189      * @hide
20190      */
isLayoutDirectionInherited()20191     public boolean isLayoutDirectionInherited() {
20192         return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
20193     }
20194 
20195     /**
20196      * @return true if layout direction has been resolved.
20197      */
isLayoutDirectionResolved()20198     public boolean isLayoutDirectionResolved() {
20199         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
20200     }
20201 
20202     /**
20203      * Return if padding has been resolved
20204      *
20205      * @hide
20206      */
20207     @UnsupportedAppUsage
isPaddingResolved()20208     boolean isPaddingResolved() {
20209         return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
20210     }
20211 
20212     /**
20213      * Resolves padding depending on layout direction, if applicable, and
20214      * recomputes internal padding values to adjust for scroll bars.
20215      *
20216      * @hide
20217      */
20218     @UnsupportedAppUsage
resolvePadding()20219     public void resolvePadding() {
20220         final int resolvedLayoutDirection = getLayoutDirection();
20221 
20222         if (!isRtlCompatibilityMode()) {
20223             // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
20224             // If start / end padding are defined, they will be resolved (hence overriding) to
20225             // left / right or right / left depending on the resolved layout direction.
20226             // If start / end padding are not defined, use the left / right ones.
20227             if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
20228                 Rect padding = sThreadLocal.get();
20229                 if (padding == null) {
20230                     padding = new Rect();
20231                     sThreadLocal.set(padding);
20232                 }
20233                 mBackground.getPadding(padding);
20234                 if (!mLeftPaddingDefined) {
20235                     mUserPaddingLeftInitial = padding.left;
20236                 }
20237                 if (!mRightPaddingDefined) {
20238                     mUserPaddingRightInitial = padding.right;
20239                 }
20240             }
20241             switch (resolvedLayoutDirection) {
20242                 case LAYOUT_DIRECTION_RTL:
20243                     if (mUserPaddingStart != UNDEFINED_PADDING) {
20244                         mUserPaddingRight = mUserPaddingStart;
20245                     } else {
20246                         mUserPaddingRight = mUserPaddingRightInitial;
20247                     }
20248                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
20249                         mUserPaddingLeft = mUserPaddingEnd;
20250                     } else {
20251                         mUserPaddingLeft = mUserPaddingLeftInitial;
20252                     }
20253                     break;
20254                 case LAYOUT_DIRECTION_LTR:
20255                 default:
20256                     if (mUserPaddingStart != UNDEFINED_PADDING) {
20257                         mUserPaddingLeft = mUserPaddingStart;
20258                     } else {
20259                         mUserPaddingLeft = mUserPaddingLeftInitial;
20260                     }
20261                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
20262                         mUserPaddingRight = mUserPaddingEnd;
20263                     } else {
20264                         mUserPaddingRight = mUserPaddingRightInitial;
20265                     }
20266             }
20267 
20268             mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
20269         }
20270 
20271         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
20272         onRtlPropertiesChanged(resolvedLayoutDirection);
20273 
20274         mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
20275     }
20276 
20277     /**
20278      * Reset the resolved layout direction.
20279      *
20280      * @hide
20281      */
20282     @TestApi
resetResolvedPadding()20283     public void resetResolvedPadding() {
20284         resetResolvedPaddingInternal();
20285     }
20286 
20287     /**
20288      * Used when we only want to reset *this* view's padding and not trigger overrides
20289      * in ViewGroup that reset children too.
20290      */
resetResolvedPaddingInternal()20291     void resetResolvedPaddingInternal() {
20292         mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
20293     }
20294 
20295     /**
20296      * This is called when the view is detached from a window.  At this point it
20297      * no longer has a surface for drawing.
20298      *
20299      * @see #onAttachedToWindow()
20300      */
20301     @CallSuper
onDetachedFromWindow()20302     protected void onDetachedFromWindow() {
20303     }
20304 
20305     /**
20306      * This is a framework-internal mirror of onDetachedFromWindow() that's called
20307      * after onDetachedFromWindow().
20308      *
20309      * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
20310      * The super method should be called at the end of the overridden method to ensure
20311      * subclasses are destroyed first
20312      *
20313      * @hide
20314      */
20315     @CallSuper
20316     @UnsupportedAppUsage
onDetachedFromWindowInternal()20317     protected void onDetachedFromWindowInternal() {
20318         mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
20319         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
20320         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
20321 
20322         removeUnsetPressCallback();
20323         removeLongPressCallback();
20324         removePerformClickCallback();
20325         clearAccessibilityThrottles();
20326         stopNestedScroll();
20327 
20328         // Anything that started animating right before detach should already
20329         // be in its final state when re-attached.
20330         jumpDrawablesToCurrentState();
20331 
20332         destroyDrawingCache();
20333 
20334         cleanupDraw();
20335         mCurrentAnimation = null;
20336 
20337         if ((mViewFlags & TOOLTIP) == TOOLTIP) {
20338             hideTooltip();
20339         }
20340 
20341         AccessibilityNodeIdManager.getInstance().unregisterViewWithId(getAccessibilityViewId());
20342     }
20343 
cleanupDraw()20344     private void cleanupDraw() {
20345         resetDisplayList();
20346         if (mAttachInfo != null) {
20347             mAttachInfo.mViewRootImpl.cancelInvalidate(this);
20348         }
20349     }
20350 
invalidateInheritedLayoutMode(int layoutModeOfRoot)20351     void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
20352     }
20353 
20354     /**
20355      * @return The number of times this view has been attached to a window
20356      */
getWindowAttachCount()20357     protected int getWindowAttachCount() {
20358         return mWindowAttachCount;
20359     }
20360 
20361     /**
20362      * Retrieve a unique token identifying the window this view is attached to.
20363      * @return Return the window's token for use in
20364      * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
20365      */
getWindowToken()20366     public IBinder getWindowToken() {
20367         return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
20368     }
20369 
20370     /**
20371      * Retrieve the {@link WindowId} for the window this view is
20372      * currently attached to.
20373      */
getWindowId()20374     public WindowId getWindowId() {
20375         AttachInfo ai = mAttachInfo;
20376         if (ai == null) {
20377             return null;
20378         }
20379         if (ai.mWindowId == null) {
20380             try {
20381                 ai.mIWindowId = ai.mSession.getWindowId(ai.mWindowToken);
20382                 if (ai.mIWindowId != null) {
20383                     ai.mWindowId = new WindowId(ai.mIWindowId);
20384                 }
20385             } catch (RemoteException e) {
20386             }
20387         }
20388         return ai.mWindowId;
20389     }
20390 
20391     /**
20392      * Retrieve a unique token identifying the top-level "real" window of
20393      * the window that this view is attached to.  That is, this is like
20394      * {@link #getWindowToken}, except if the window this view in is a panel
20395      * window (attached to another containing window), then the token of
20396      * the containing window is returned instead.
20397      *
20398      * @return Returns the associated window token, either
20399      * {@link #getWindowToken()} or the containing window's token.
20400      */
getApplicationWindowToken()20401     public IBinder getApplicationWindowToken() {
20402         AttachInfo ai = mAttachInfo;
20403         if (ai != null) {
20404             IBinder appWindowToken = ai.mPanelParentWindowToken;
20405             if (appWindowToken == null) {
20406                 appWindowToken = ai.mWindowToken;
20407             }
20408             return appWindowToken;
20409         }
20410         return null;
20411     }
20412 
20413     /**
20414      * Gets the logical display to which the view's window has been attached.
20415      *
20416      * @return The logical display, or null if the view is not currently attached to a window.
20417      */
getDisplay()20418     public Display getDisplay() {
20419         return mAttachInfo != null ? mAttachInfo.mDisplay : null;
20420     }
20421 
20422     /**
20423      * Retrieve private session object this view hierarchy is using to
20424      * communicate with the window manager.
20425      * @return the session object to communicate with the window manager
20426      */
20427     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
getWindowSession()20428     /*package*/ IWindowSession getWindowSession() {
20429         return mAttachInfo != null ? mAttachInfo.mSession : null;
20430     }
20431 
20432     /**
20433      * Return the window this view is currently attached to. Used in
20434      * {@link android.app.ActivityView} to communicate with WM.
20435      * @hide
20436      */
getWindow()20437     protected IWindow getWindow() {
20438         return mAttachInfo != null ? mAttachInfo.mWindow : null;
20439     }
20440 
20441     /**
20442      * Return the visibility value of the least visible component passed.
20443      */
combineVisibility(int vis1, int vis2)20444     int combineVisibility(int vis1, int vis2) {
20445         // This works because VISIBLE < INVISIBLE < GONE.
20446         return Math.max(vis1, vis2);
20447     }
20448 
20449     /**
20450      * @param info the {@link android.view.View.AttachInfo} to associated with
20451      *        this view
20452      */
20453     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
dispatchAttachedToWindow(AttachInfo info, int visibility)20454     void dispatchAttachedToWindow(AttachInfo info, int visibility) {
20455         mAttachInfo = info;
20456         if (mOverlay != null) {
20457             mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
20458         }
20459         mWindowAttachCount++;
20460         // We will need to evaluate the drawable state at least once.
20461         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
20462         if (mFloatingTreeObserver != null) {
20463             info.mTreeObserver.merge(mFloatingTreeObserver);
20464             mFloatingTreeObserver = null;
20465         }
20466 
20467         registerPendingFrameMetricsObservers();
20468 
20469         if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
20470             mAttachInfo.mScrollContainers.add(this);
20471             mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
20472         }
20473         // Transfer all pending runnables.
20474         if (mRunQueue != null) {
20475             mRunQueue.executeActions(info.mHandler);
20476             mRunQueue = null;
20477         }
20478         performCollectViewAttributes(mAttachInfo, visibility);
20479         onAttachedToWindow();
20480 
20481         ListenerInfo li = mListenerInfo;
20482         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
20483                 li != null ? li.mOnAttachStateChangeListeners : null;
20484         if (listeners != null && listeners.size() > 0) {
20485             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
20486             // perform the dispatching. The iterator is a safe guard against listeners that
20487             // could mutate the list by calling the various add/remove methods. This prevents
20488             // the array from being modified while we iterate it.
20489             for (OnAttachStateChangeListener listener : listeners) {
20490                 listener.onViewAttachedToWindow(this);
20491             }
20492         }
20493 
20494         int vis = info.mWindowVisibility;
20495         if (vis != GONE) {
20496             onWindowVisibilityChanged(vis);
20497             if (isShown()) {
20498                 // Calling onVisibilityAggregated directly here since the subtree will also
20499                 // receive dispatchAttachedToWindow and this same call
20500                 onVisibilityAggregated(vis == VISIBLE);
20501             }
20502         }
20503 
20504         // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
20505         // As all views in the subtree will already receive dispatchAttachedToWindow
20506         // traversing the subtree again here is not desired.
20507         onVisibilityChanged(this, visibility);
20508 
20509         if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
20510             // If nobody has evaluated the drawable state yet, then do it now.
20511             refreshDrawableState();
20512         }
20513         needGlobalAttributesUpdate(false);
20514 
20515         notifyEnterOrExitForAutoFillIfNeeded(true);
20516         notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
20517     }
20518 
20519     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
dispatchDetachedFromWindow()20520     void dispatchDetachedFromWindow() {
20521         AttachInfo info = mAttachInfo;
20522         if (info != null) {
20523             int vis = info.mWindowVisibility;
20524             if (vis != GONE) {
20525                 onWindowVisibilityChanged(GONE);
20526                 if (isShown()) {
20527                     // Invoking onVisibilityAggregated directly here since the subtree
20528                     // will also receive detached from window
20529                     onVisibilityAggregated(false);
20530                 }
20531             }
20532         }
20533 
20534         onDetachedFromWindow();
20535         onDetachedFromWindowInternal();
20536 
20537         if (info != null) {
20538             info.mViewRootImpl.getImeFocusController().onViewDetachedFromWindow(this);
20539         }
20540 
20541         ListenerInfo li = mListenerInfo;
20542         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
20543                 li != null ? li.mOnAttachStateChangeListeners : null;
20544         if (listeners != null && listeners.size() > 0) {
20545             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
20546             // perform the dispatching. The iterator is a safe guard against listeners that
20547             // could mutate the list by calling the various add/remove methods. This prevents
20548             // the array from being modified while we iterate it.
20549             for (OnAttachStateChangeListener listener : listeners) {
20550                 listener.onViewDetachedFromWindow(this);
20551             }
20552         }
20553 
20554         if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
20555             mAttachInfo.mScrollContainers.remove(this);
20556             mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
20557         }
20558 
20559         mAttachInfo = null;
20560         if (mOverlay != null) {
20561             mOverlay.getOverlayView().dispatchDetachedFromWindow();
20562         }
20563 
20564         notifyEnterOrExitForAutoFillIfNeeded(false);
20565         notifyAppearedOrDisappearedForContentCaptureIfNeeded(false);
20566     }
20567 
20568     /**
20569      * Cancel any deferred high-level input events that were previously posted to the event queue.
20570      *
20571      * <p>Many views post high-level events such as click handlers to the event queue
20572      * to run deferred in order to preserve a desired user experience - clearing visible
20573      * pressed states before executing, etc. This method will abort any events of this nature
20574      * that are currently in flight.</p>
20575      *
20576      * <p>Custom views that generate their own high-level deferred input events should override
20577      * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
20578      *
20579      * <p>This will also cancel pending input events for any child views.</p>
20580      *
20581      * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
20582      * This will not impact newer events posted after this call that may occur as a result of
20583      * lower-level input events still waiting in the queue. If you are trying to prevent
20584      * double-submitted  events for the duration of some sort of asynchronous transaction
20585      * you should also take other steps to protect against unexpected double inputs e.g. calling
20586      * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
20587      * the transaction completes, tracking already submitted transaction IDs, etc.</p>
20588      */
cancelPendingInputEvents()20589     public final void cancelPendingInputEvents() {
20590         dispatchCancelPendingInputEvents();
20591     }
20592 
20593     /**
20594      * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
20595      * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
20596      */
dispatchCancelPendingInputEvents()20597     void dispatchCancelPendingInputEvents() {
20598         mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
20599         onCancelPendingInputEvents();
20600         if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
20601             throw new SuperNotCalledException("View " + getClass().getSimpleName() +
20602                     " did not call through to super.onCancelPendingInputEvents()");
20603         }
20604     }
20605 
20606     /**
20607      * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
20608      * a parent view.
20609      *
20610      * <p>This method is responsible for removing any pending high-level input events that were
20611      * posted to the event queue to run later. Custom view classes that post their own deferred
20612      * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
20613      * {@link android.os.Handler} should override this method, call
20614      * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
20615      * </p>
20616      */
onCancelPendingInputEvents()20617     public void onCancelPendingInputEvents() {
20618         removePerformClickCallback();
20619         cancelLongPress();
20620         mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
20621     }
20622 
20623     /**
20624      * Store this view hierarchy's frozen state into the given container.
20625      *
20626      * @param container The SparseArray in which to save the view's state.
20627      *
20628      * @see #restoreHierarchyState(android.util.SparseArray)
20629      * @see #dispatchSaveInstanceState(android.util.SparseArray)
20630      * @see #onSaveInstanceState()
20631      */
saveHierarchyState(SparseArray<Parcelable> container)20632     public void saveHierarchyState(SparseArray<Parcelable> container) {
20633         dispatchSaveInstanceState(container);
20634     }
20635 
20636     /**
20637      * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
20638      * this view and its children. May be overridden to modify how freezing happens to a
20639      * view's children; for example, some views may want to not store state for their children.
20640      *
20641      * @param container The SparseArray in which to save the view's state.
20642      *
20643      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
20644      * @see #saveHierarchyState(android.util.SparseArray)
20645      * @see #onSaveInstanceState()
20646      */
dispatchSaveInstanceState(SparseArray<Parcelable> container)20647     protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
20648         if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
20649             mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
20650             Parcelable state = onSaveInstanceState();
20651             if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
20652                 throw new IllegalStateException(
20653                         "Derived class did not call super.onSaveInstanceState()");
20654             }
20655             if (state != null) {
20656                 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
20657                 // + ": " + state);
20658                 container.put(mID, state);
20659             }
20660         }
20661     }
20662 
20663     /**
20664      * Hook allowing a view to generate a representation of its internal state
20665      * that can later be used to create a new instance with that same state.
20666      * This state should only contain information that is not persistent or can
20667      * not be reconstructed later. For example, you will never store your
20668      * current position on screen because that will be computed again when a
20669      * new instance of the view is placed in its view hierarchy.
20670      * <p>
20671      * Some examples of things you may store here: the current cursor position
20672      * in a text view (but usually not the text itself since that is stored in a
20673      * content provider or other persistent storage), the currently selected
20674      * item in a list view.
20675      *
20676      * @return Returns a Parcelable object containing the view's current dynamic
20677      *         state, or null if there is nothing interesting to save.
20678      * @see #onRestoreInstanceState(Parcelable)
20679      * @see #saveHierarchyState(SparseArray)
20680      * @see #dispatchSaveInstanceState(SparseArray)
20681      * @see #setSaveEnabled(boolean)
20682      */
20683     @CallSuper
onSaveInstanceState()20684     @Nullable protected Parcelable onSaveInstanceState() {
20685         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
20686         if (mStartActivityRequestWho != null || isAutofilled()
20687                 || mAutofillViewId > LAST_APP_AUTOFILL_ID) {
20688             BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
20689 
20690             if (mStartActivityRequestWho != null) {
20691                 state.mSavedData |= BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED;
20692             }
20693 
20694             if (isAutofilled()) {
20695                 state.mSavedData |= BaseSavedState.IS_AUTOFILLED;
20696             }
20697 
20698             if (mAutofillViewId > LAST_APP_AUTOFILL_ID) {
20699                 state.mSavedData |= BaseSavedState.AUTOFILL_ID;
20700             }
20701 
20702             state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
20703             state.mIsAutofilled = isAutofilled();
20704             state.mHideHighlight = hideAutofillHighlight();
20705             state.mAutofillViewId = mAutofillViewId;
20706             return state;
20707         }
20708         return BaseSavedState.EMPTY_STATE;
20709     }
20710 
20711     /**
20712      * Restore this view hierarchy's frozen state from the given container.
20713      *
20714      * @param container The SparseArray which holds previously frozen states.
20715      *
20716      * @see #saveHierarchyState(android.util.SparseArray)
20717      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
20718      * @see #onRestoreInstanceState(android.os.Parcelable)
20719      */
restoreHierarchyState(SparseArray<Parcelable> container)20720     public void restoreHierarchyState(SparseArray<Parcelable> container) {
20721         dispatchRestoreInstanceState(container);
20722     }
20723 
20724     /**
20725      * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
20726      * state for this view and its children. May be overridden to modify how restoring
20727      * happens to a view's children; for example, some views may want to not store state
20728      * for their children.
20729      *
20730      * @param container The SparseArray which holds previously saved state.
20731      *
20732      * @see #dispatchSaveInstanceState(android.util.SparseArray)
20733      * @see #restoreHierarchyState(android.util.SparseArray)
20734      * @see #onRestoreInstanceState(android.os.Parcelable)
20735      */
dispatchRestoreInstanceState(SparseArray<Parcelable> container)20736     protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
20737         if (mID != NO_ID) {
20738             Parcelable state = container.get(mID);
20739             if (state != null) {
20740                 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
20741                 // + ": " + state);
20742                 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
20743                 onRestoreInstanceState(state);
20744                 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
20745                     throw new IllegalStateException(
20746                             "Derived class did not call super.onRestoreInstanceState()");
20747                 }
20748             }
20749         }
20750     }
20751 
20752     /**
20753      * Hook allowing a view to re-apply a representation of its internal state that had previously
20754      * been generated by {@link #onSaveInstanceState}. This function will never be called with a
20755      * null state.
20756      *
20757      * @param state The frozen state that had previously been returned by
20758      *        {@link #onSaveInstanceState}.
20759      *
20760      * @see #onSaveInstanceState()
20761      * @see #restoreHierarchyState(android.util.SparseArray)
20762      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
20763      */
20764     @CallSuper
onRestoreInstanceState(Parcelable state)20765     protected void onRestoreInstanceState(Parcelable state) {
20766         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
20767         if (state != null && !(state instanceof AbsSavedState)) {
20768             throw new IllegalArgumentException("Wrong state class, expecting View State but "
20769                     + "received " + state.getClass().toString() + " instead. This usually happens "
20770                     + "when two views of different type have the same id in the same hierarchy. "
20771                     + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
20772                     + "other views do not use the same id.");
20773         }
20774         if (state != null && state instanceof BaseSavedState) {
20775             BaseSavedState baseState = (BaseSavedState) state;
20776 
20777             if ((baseState.mSavedData & BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED) != 0) {
20778                 mStartActivityRequestWho = baseState.mStartActivityRequestWhoSaved;
20779             }
20780             if ((baseState.mSavedData & BaseSavedState.IS_AUTOFILLED) != 0) {
20781                 setAutofilled(baseState.mIsAutofilled, baseState.mHideHighlight);
20782             }
20783             if ((baseState.mSavedData & BaseSavedState.AUTOFILL_ID) != 0) {
20784                 // It can happen that views have the same view id and the restoration path will not
20785                 // be able to distinguish between them. The autofill id needs to be unique though.
20786                 // Hence prevent the same autofill view id from being restored multiple times.
20787                 ((BaseSavedState) state).mSavedData &= ~BaseSavedState.AUTOFILL_ID;
20788 
20789                 if ((mPrivateFlags3 & PFLAG3_AUTOFILLID_EXPLICITLY_SET) != 0) {
20790                     // Ignore when view already set it through setAutofillId();
20791                     if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.DEBUG)) {
20792                         Log.d(AUTOFILL_LOG_TAG, "onRestoreInstanceState(): not setting autofillId "
20793                                 + "to " + baseState.mAutofillViewId + " because view explicitly set"
20794                                 + " it to " + mAutofillId);
20795                     }
20796                 } else {
20797                     mAutofillViewId = baseState.mAutofillViewId;
20798                     mAutofillId = null; // will be set on demand by getAutofillId()
20799                 }
20800             }
20801         }
20802     }
20803 
20804     /**
20805      * <p>Return the time at which the drawing of the view hierarchy started.</p>
20806      *
20807      * @return the drawing start time in milliseconds
20808      */
getDrawingTime()20809     public long getDrawingTime() {
20810         return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
20811     }
20812 
20813     /**
20814      * <p>Enables or disables the duplication of the parent's state into this view. When
20815      * duplication is enabled, this view gets its drawable state from its parent rather
20816      * than from its own internal properties.</p>
20817      *
20818      * <p>Note: in the current implementation, setting this property to true after the
20819      * view was added to a ViewGroup might have no effect at all. This property should
20820      * always be used from XML or set to true before adding this view to a ViewGroup.</p>
20821      *
20822      * <p>Note: if this view's parent addStateFromChildren property is enabled and this
20823      * property is enabled, an exception will be thrown.</p>
20824      *
20825      * <p>Note: if the child view uses and updates additional states which are unknown to the
20826      * parent, these states should not be affected by this method.</p>
20827      *
20828      * @param enabled True to enable duplication of the parent's drawable state, false
20829      *                to disable it.
20830      *
20831      * @see #getDrawableState()
20832      * @see #isDuplicateParentStateEnabled()
20833      */
setDuplicateParentStateEnabled(boolean enabled)20834     public void setDuplicateParentStateEnabled(boolean enabled) {
20835         setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
20836     }
20837 
20838     /**
20839      * <p>Indicates whether this duplicates its drawable state from its parent.</p>
20840      *
20841      * @return True if this view's drawable state is duplicated from the parent,
20842      *         false otherwise
20843      *
20844      * @see #getDrawableState()
20845      * @see #setDuplicateParentStateEnabled(boolean)
20846      */
20847     @InspectableProperty(name = "duplicateParentState")
isDuplicateParentStateEnabled()20848     public boolean isDuplicateParentStateEnabled() {
20849         return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
20850     }
20851 
20852     /**
20853      * <p>Specifies the type of layer backing this view. The layer can be
20854      * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
20855      * {@link #LAYER_TYPE_HARDWARE}.</p>
20856      *
20857      * <p>A layer is associated with an optional {@link android.graphics.Paint}
20858      * instance that controls how the layer is composed on screen. The following
20859      * properties of the paint are taken into account when composing the layer:</p>
20860      * <ul>
20861      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
20862      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
20863      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
20864      * </ul>
20865      *
20866      * <p>If this view has an alpha value set to < 1.0 by calling
20867      * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
20868      * by this view's alpha value.</p>
20869      *
20870      * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
20871      * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
20872      * for more information on when and how to use layers.</p>
20873      *
20874      * @param layerType The type of layer to use with this view, must be one of
20875      *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
20876      *        {@link #LAYER_TYPE_HARDWARE}
20877      * @param paint The paint used to compose the layer. This argument is optional
20878      *        and can be null. It is ignored when the layer type is
20879      *        {@link #LAYER_TYPE_NONE}
20880      *
20881      * @see #getLayerType()
20882      * @see #LAYER_TYPE_NONE
20883      * @see #LAYER_TYPE_SOFTWARE
20884      * @see #LAYER_TYPE_HARDWARE
20885      * @see #setAlpha(float)
20886      *
20887      * @attr ref android.R.styleable#View_layerType
20888      */
setLayerType(@ayerType int layerType, @Nullable Paint paint)20889     public void setLayerType(@LayerType int layerType, @Nullable Paint paint) {
20890         if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
20891             throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
20892                     + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
20893         }
20894 
20895         boolean typeChanged = mRenderNode.setLayerType(layerType);
20896 
20897         if (!typeChanged) {
20898             setLayerPaint(paint);
20899             return;
20900         }
20901 
20902         if (layerType != LAYER_TYPE_SOFTWARE) {
20903             // Destroy any previous software drawing cache if present
20904             // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
20905             // drawing cache created in View#draw when drawing to a SW canvas.
20906             destroyDrawingCache();
20907         }
20908 
20909         mLayerType = layerType;
20910         mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
20911         mRenderNode.setLayerPaint(mLayerPaint);
20912 
20913         // draw() behaves differently if we are on a layer, so we need to
20914         // invalidate() here
20915         invalidateParentCaches();
20916         invalidate(true);
20917     }
20918 
20919     /**
20920      * Updates the {@link Paint} object used with the current layer (used only if the current
20921      * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
20922      * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
20923      * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
20924      * ensure that the view gets redrawn immediately.
20925      *
20926      * <p>A layer is associated with an optional {@link android.graphics.Paint}
20927      * instance that controls how the layer is composed on screen. The following
20928      * properties of the paint are taken into account when composing the layer:</p>
20929      * <ul>
20930      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
20931      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
20932      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
20933      * </ul>
20934      *
20935      * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
20936      * alpha value of the layer's paint is superseded by this view's alpha value.</p>
20937      *
20938      * @param paint The paint used to compose the layer. This argument is optional
20939      *        and can be null. It is ignored when the layer type is
20940      *        {@link #LAYER_TYPE_NONE}
20941      *
20942      * @see #setLayerType(int, android.graphics.Paint)
20943      */
setLayerPaint(@ullable Paint paint)20944     public void setLayerPaint(@Nullable Paint paint) {
20945         int layerType = getLayerType();
20946         if (layerType != LAYER_TYPE_NONE) {
20947             mLayerPaint = paint;
20948             if (layerType == LAYER_TYPE_HARDWARE) {
20949                 if (mRenderNode.setLayerPaint(paint)) {
20950                     invalidateViewProperty(false, false);
20951                 }
20952             } else {
20953                 invalidate();
20954             }
20955         }
20956     }
20957 
20958     /**
20959      * Indicates what type of layer is currently associated with this view. By default
20960      * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
20961      * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
20962      * for more information on the different types of layers.
20963      *
20964      * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
20965      *         {@link #LAYER_TYPE_HARDWARE}
20966      *
20967      * @see #setLayerType(int, android.graphics.Paint)
20968      * @see #buildLayer()
20969      * @see #LAYER_TYPE_NONE
20970      * @see #LAYER_TYPE_SOFTWARE
20971      * @see #LAYER_TYPE_HARDWARE
20972      */
20973     @InspectableProperty(enumMapping = {
20974             @EnumEntry(value = LAYER_TYPE_NONE, name = "none"),
20975             @EnumEntry(value = LAYER_TYPE_SOFTWARE, name = "software"),
20976             @EnumEntry(value = LAYER_TYPE_HARDWARE, name = "hardware")
20977     })
20978     @LayerType
getLayerType()20979     public int getLayerType() {
20980         return mLayerType;
20981     }
20982 
20983     /**
20984      * Forces this view's layer to be created and this view to be rendered
20985      * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
20986      * invoking this method will have no effect.
20987      *
20988      * This method can for instance be used to render a view into its layer before
20989      * starting an animation. If this view is complex, rendering into the layer
20990      * before starting the animation will avoid skipping frames.
20991      *
20992      * @throws IllegalStateException If this view is not attached to a window
20993      *
20994      * @see #setLayerType(int, android.graphics.Paint)
20995      */
buildLayer()20996     public void buildLayer() {
20997         if (mLayerType == LAYER_TYPE_NONE) return;
20998 
20999         final AttachInfo attachInfo = mAttachInfo;
21000         if (attachInfo == null) {
21001             throw new IllegalStateException("This view must be attached to a window first");
21002         }
21003 
21004         if (getWidth() == 0 || getHeight() == 0) {
21005             return;
21006         }
21007 
21008         switch (mLayerType) {
21009             case LAYER_TYPE_HARDWARE:
21010                 updateDisplayListIfDirty();
21011                 if (attachInfo.mThreadedRenderer != null && mRenderNode.hasDisplayList()) {
21012                     attachInfo.mThreadedRenderer.buildLayer(mRenderNode);
21013                 }
21014                 break;
21015             case LAYER_TYPE_SOFTWARE:
21016                 buildDrawingCache(true);
21017                 break;
21018         }
21019     }
21020 
21021     /**
21022      * Destroys all hardware rendering resources. This method is invoked
21023      * when the system needs to reclaim resources. Upon execution of this
21024      * method, you should free any OpenGL resources created by the view.
21025      *
21026      * Note: you <strong>must</strong> call
21027      * <code>super.destroyHardwareResources()</code> when overriding
21028      * this method.
21029      *
21030      * @hide
21031      */
21032     @CallSuper
21033     @UnsupportedAppUsage
destroyHardwareResources()21034     protected void destroyHardwareResources() {
21035         if (mOverlay != null) {
21036             mOverlay.getOverlayView().destroyHardwareResources();
21037         }
21038         if (mGhostView != null) {
21039             mGhostView.destroyHardwareResources();
21040         }
21041     }
21042 
21043     /**
21044      * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
21045      * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
21046      * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
21047      * the cache is enabled. To benefit from the cache, you must request the drawing cache by
21048      * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
21049      * null.</p>
21050      *
21051      * <p>Enabling the drawing cache is similar to
21052      * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
21053      * acceleration is turned off. When hardware acceleration is turned on, enabling the
21054      * drawing cache has no effect on rendering because the system uses a different mechanism
21055      * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
21056      * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
21057      * for information on how to enable software and hardware layers.</p>
21058      *
21059      * <p>This API can be used to manually generate
21060      * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
21061      * {@link #getDrawingCache()}.</p>
21062      *
21063      * @param enabled true to enable the drawing cache, false otherwise
21064      *
21065      * @see #isDrawingCacheEnabled()
21066      * @see #getDrawingCache()
21067      * @see #buildDrawingCache()
21068      * @see #setLayerType(int, android.graphics.Paint)
21069      *
21070      * @deprecated The view drawing cache was largely made obsolete with the introduction of
21071      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
21072      * layers are largely unnecessary and can easily result in a net loss in performance due to the
21073      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
21074      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
21075      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
21076      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
21077      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
21078      * software-rendered usages are discouraged and have compatibility issues with hardware-only
21079      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
21080      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
21081      * reports or unit testing the {@link PixelCopy} API is recommended.
21082      */
21083     @Deprecated
setDrawingCacheEnabled(boolean enabled)21084     public void setDrawingCacheEnabled(boolean enabled) {
21085         mCachingFailed = false;
21086         setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
21087     }
21088 
21089     /**
21090      * <p>Indicates whether the drawing cache is enabled for this view.</p>
21091      *
21092      * @return true if the drawing cache is enabled
21093      *
21094      * @see #setDrawingCacheEnabled(boolean)
21095      * @see #getDrawingCache()
21096      *
21097      * @deprecated The view drawing cache was largely made obsolete with the introduction of
21098      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
21099      * layers are largely unnecessary and can easily result in a net loss in performance due to the
21100      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
21101      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
21102      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
21103      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
21104      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
21105      * software-rendered usages are discouraged and have compatibility issues with hardware-only
21106      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
21107      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
21108      * reports or unit testing the {@link PixelCopy} API is recommended.
21109      */
21110     @Deprecated
21111     @ViewDebug.ExportedProperty(category = "drawing")
isDrawingCacheEnabled()21112     public boolean isDrawingCacheEnabled() {
21113         return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
21114     }
21115 
21116     /**
21117      * Debugging utility which recursively outputs the dirty state of a view and its
21118      * descendants.
21119      *
21120      * @hide
21121      */
21122     @SuppressWarnings({"UnusedDeclaration"})
outputDirtyFlags(String indent, boolean clear, int clearMask)21123     public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
21124         Log.d(VIEW_LOG_TAG, indent + this + "             DIRTY("
21125                 + (mPrivateFlags & View.PFLAG_DIRTY_MASK)
21126                 + ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID("
21127                 + (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID)
21128                 + ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
21129         if (clear) {
21130             mPrivateFlags &= clearMask;
21131         }
21132         if (this instanceof ViewGroup) {
21133             ViewGroup parent = (ViewGroup) this;
21134             final int count = parent.getChildCount();
21135             for (int i = 0; i < count; i++) {
21136                 final View child = parent.getChildAt(i);
21137                 child.outputDirtyFlags(indent + "  ", clear, clearMask);
21138             }
21139         }
21140     }
21141 
21142     /**
21143      * This method is used by ViewGroup to cause its children to restore or recreate their
21144      * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
21145      * to recreate its own display list, which would happen if it went through the normal
21146      * draw/dispatchDraw mechanisms.
21147      *
21148      * @hide
21149      */
dispatchGetDisplayList()21150     protected void dispatchGetDisplayList() {}
21151 
21152     /**
21153      * A view that is not attached or hardware accelerated cannot create a display list.
21154      * This method checks these conditions and returns the appropriate result.
21155      *
21156      * @return true if view has the ability to create a display list, false otherwise.
21157      *
21158      * @hide
21159      */
canHaveDisplayList()21160     public boolean canHaveDisplayList() {
21161         return !(mAttachInfo == null || mAttachInfo.mThreadedRenderer == null);
21162     }
21163 
21164     /**
21165      * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
21166      * @hide
21167      */
21168     @NonNull
21169     @UnsupportedAppUsage
updateDisplayListIfDirty()21170     public RenderNode updateDisplayListIfDirty() {
21171         final RenderNode renderNode = mRenderNode;
21172         if (!canHaveDisplayList()) {
21173             // can't populate RenderNode, don't try
21174             return renderNode;
21175         }
21176 
21177         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
21178                 || !renderNode.hasDisplayList()
21179                 || (mRecreateDisplayList)) {
21180             // Don't need to recreate the display list, just need to tell our
21181             // children to restore/recreate theirs
21182             if (renderNode.hasDisplayList()
21183                     && !mRecreateDisplayList) {
21184                 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
21185                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
21186                 dispatchGetDisplayList();
21187 
21188                 return renderNode; // no work needed
21189             }
21190 
21191             // If we got here, we're recreating it. Mark it as such to ensure that
21192             // we copy in child display lists into ours in drawChild()
21193             mRecreateDisplayList = true;
21194 
21195             int width = mRight - mLeft;
21196             int height = mBottom - mTop;
21197             int layerType = getLayerType();
21198 
21199             final RecordingCanvas canvas = renderNode.beginRecording(width, height);
21200 
21201             try {
21202                 if (layerType == LAYER_TYPE_SOFTWARE) {
21203                     buildDrawingCache(true);
21204                     Bitmap cache = getDrawingCache(true);
21205                     if (cache != null) {
21206                         canvas.drawBitmap(cache, 0, 0, mLayerPaint);
21207                     }
21208                 } else {
21209                     computeScroll();
21210 
21211                     canvas.translate(-mScrollX, -mScrollY);
21212                     mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
21213                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
21214 
21215                     // Fast path for layouts with no backgrounds
21216                     if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
21217                         dispatchDraw(canvas);
21218                         drawAutofilledHighlight(canvas);
21219                         if (mOverlay != null && !mOverlay.isEmpty()) {
21220                             mOverlay.getOverlayView().draw(canvas);
21221                         }
21222                         if (isShowingLayoutBounds()) {
21223                             debugDrawFocus(canvas);
21224                         }
21225                     } else {
21226                         draw(canvas);
21227                     }
21228                 }
21229             } finally {
21230                 renderNode.endRecording();
21231                 setDisplayListProperties(renderNode);
21232             }
21233         } else {
21234             mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
21235             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
21236         }
21237         return renderNode;
21238     }
21239 
21240     @UnsupportedAppUsage
resetDisplayList()21241     private void resetDisplayList() {
21242         mRenderNode.discardDisplayList();
21243         if (mBackgroundRenderNode != null) {
21244             mBackgroundRenderNode.discardDisplayList();
21245         }
21246     }
21247 
21248     /**
21249      * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
21250      *
21251      * @return A non-scaled bitmap representing this view or null if cache is disabled.
21252      *
21253      * @see #getDrawingCache(boolean)
21254      *
21255      * @deprecated The view drawing cache was largely made obsolete with the introduction of
21256      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
21257      * layers are largely unnecessary and can easily result in a net loss in performance due to the
21258      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
21259      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
21260      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
21261      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
21262      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
21263      * software-rendered usages are discouraged and have compatibility issues with hardware-only
21264      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
21265      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
21266      * reports or unit testing the {@link PixelCopy} API is recommended.
21267      */
21268     @Deprecated
getDrawingCache()21269     public Bitmap getDrawingCache() {
21270         return getDrawingCache(false);
21271     }
21272 
21273     /**
21274      * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
21275      * is null when caching is disabled. If caching is enabled and the cache is not ready,
21276      * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
21277      * draw from the cache when the cache is enabled. To benefit from the cache, you must
21278      * request the drawing cache by calling this method and draw it on screen if the
21279      * returned bitmap is not null.</p>
21280      *
21281      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
21282      * this method will create a bitmap of the same size as this view. Because this bitmap
21283      * will be drawn scaled by the parent ViewGroup, the result on screen might show
21284      * scaling artifacts. To avoid such artifacts, you should call this method by setting
21285      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
21286      * size than the view. This implies that your application must be able to handle this
21287      * size.</p>
21288      *
21289      * @param autoScale Indicates whether the generated bitmap should be scaled based on
21290      *        the current density of the screen when the application is in compatibility
21291      *        mode.
21292      *
21293      * @return A bitmap representing this view or null if cache is disabled.
21294      *
21295      * @see #setDrawingCacheEnabled(boolean)
21296      * @see #isDrawingCacheEnabled()
21297      * @see #buildDrawingCache(boolean)
21298      * @see #destroyDrawingCache()
21299      *
21300      * @deprecated The view drawing cache was largely made obsolete with the introduction of
21301      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
21302      * layers are largely unnecessary and can easily result in a net loss in performance due to the
21303      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
21304      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
21305      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
21306      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
21307      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
21308      * software-rendered usages are discouraged and have compatibility issues with hardware-only
21309      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
21310      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
21311      * reports or unit testing the {@link PixelCopy} API is recommended.
21312      */
21313     @Deprecated
getDrawingCache(boolean autoScale)21314     public Bitmap getDrawingCache(boolean autoScale) {
21315         if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
21316             return null;
21317         }
21318         if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
21319             buildDrawingCache(autoScale);
21320         }
21321         return autoScale ? mDrawingCache : mUnscaledDrawingCache;
21322     }
21323 
21324     /**
21325      * <p>Frees the resources used by the drawing cache. If you call
21326      * {@link #buildDrawingCache()} manually without calling
21327      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
21328      * should cleanup the cache with this method afterwards.</p>
21329      *
21330      * @see #setDrawingCacheEnabled(boolean)
21331      * @see #buildDrawingCache()
21332      * @see #getDrawingCache()
21333      *
21334      * @deprecated The view drawing cache was largely made obsolete with the introduction of
21335      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
21336      * layers are largely unnecessary and can easily result in a net loss in performance due to the
21337      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
21338      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
21339      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
21340      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
21341      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
21342      * software-rendered usages are discouraged and have compatibility issues with hardware-only
21343      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
21344      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
21345      * reports or unit testing the {@link PixelCopy} API is recommended.
21346      */
21347     @Deprecated
destroyDrawingCache()21348     public void destroyDrawingCache() {
21349         if (mDrawingCache != null) {
21350             mDrawingCache.recycle();
21351             mDrawingCache = null;
21352         }
21353         if (mUnscaledDrawingCache != null) {
21354             mUnscaledDrawingCache.recycle();
21355             mUnscaledDrawingCache = null;
21356         }
21357     }
21358 
21359     /**
21360      * Setting a solid background color for the drawing cache's bitmaps will improve
21361      * performance and memory usage. Note, though that this should only be used if this
21362      * view will always be drawn on top of a solid color.
21363      *
21364      * @param color The background color to use for the drawing cache's bitmap
21365      *
21366      * @see #setDrawingCacheEnabled(boolean)
21367      * @see #buildDrawingCache()
21368      * @see #getDrawingCache()
21369      *
21370      * @deprecated The view drawing cache was largely made obsolete with the introduction of
21371      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
21372      * layers are largely unnecessary and can easily result in a net loss in performance due to the
21373      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
21374      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
21375      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
21376      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
21377      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
21378      * software-rendered usages are discouraged and have compatibility issues with hardware-only
21379      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
21380      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
21381      * reports or unit testing the {@link PixelCopy} API is recommended.
21382      */
21383     @Deprecated
setDrawingCacheBackgroundColor(@olorInt int color)21384     public void setDrawingCacheBackgroundColor(@ColorInt int color) {
21385         if (color != mDrawingCacheBackgroundColor) {
21386             mDrawingCacheBackgroundColor = color;
21387             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
21388         }
21389     }
21390 
21391     /**
21392      * @see #setDrawingCacheBackgroundColor(int)
21393      *
21394      * @return The background color to used for the drawing cache's bitmap
21395      *
21396      * @deprecated The view drawing cache was largely made obsolete with the introduction of
21397      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
21398      * layers are largely unnecessary and can easily result in a net loss in performance due to the
21399      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
21400      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
21401      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
21402      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
21403      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
21404      * software-rendered usages are discouraged and have compatibility issues with hardware-only
21405      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
21406      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
21407      * reports or unit testing the {@link PixelCopy} API is recommended.
21408      */
21409     @Deprecated
21410     @ColorInt
getDrawingCacheBackgroundColor()21411     public int getDrawingCacheBackgroundColor() {
21412         return mDrawingCacheBackgroundColor;
21413     }
21414 
21415     /**
21416      * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
21417      *
21418      * @see #buildDrawingCache(boolean)
21419      *
21420      * @deprecated The view drawing cache was largely made obsolete with the introduction of
21421      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
21422      * layers are largely unnecessary and can easily result in a net loss in performance due to the
21423      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
21424      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
21425      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
21426      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
21427      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
21428      * software-rendered usages are discouraged and have compatibility issues with hardware-only
21429      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
21430      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
21431      * reports or unit testing the {@link PixelCopy} API is recommended.
21432      */
21433     @Deprecated
buildDrawingCache()21434     public void buildDrawingCache() {
21435         buildDrawingCache(false);
21436     }
21437 
21438     /**
21439      * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
21440      *
21441      * <p>If you call {@link #buildDrawingCache()} manually without calling
21442      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
21443      * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
21444      *
21445      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
21446      * this method will create a bitmap of the same size as this view. Because this bitmap
21447      * will be drawn scaled by the parent ViewGroup, the result on screen might show
21448      * scaling artifacts. To avoid such artifacts, you should call this method by setting
21449      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
21450      * size than the view. This implies that your application must be able to handle this
21451      * size.</p>
21452      *
21453      * <p>You should avoid calling this method when hardware acceleration is enabled. If
21454      * you do not need the drawing cache bitmap, calling this method will increase memory
21455      * usage and cause the view to be rendered in software once, thus negatively impacting
21456      * performance.</p>
21457      *
21458      * @see #getDrawingCache()
21459      * @see #destroyDrawingCache()
21460      *
21461      * @deprecated The view drawing cache was largely made obsolete with the introduction of
21462      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
21463      * layers are largely unnecessary and can easily result in a net loss in performance due to the
21464      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
21465      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
21466      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
21467      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
21468      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
21469      * software-rendered usages are discouraged and have compatibility issues with hardware-only
21470      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
21471      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
21472      * reports or unit testing the {@link PixelCopy} API is recommended.
21473      */
21474     @Deprecated
buildDrawingCache(boolean autoScale)21475     public void buildDrawingCache(boolean autoScale) {
21476         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
21477                 mDrawingCache == null : mUnscaledDrawingCache == null)) {
21478             if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
21479                 Trace.traceBegin(Trace.TRACE_TAG_VIEW,
21480                         "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
21481             }
21482             try {
21483                 buildDrawingCacheImpl(autoScale);
21484             } finally {
21485                 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
21486             }
21487         }
21488     }
21489 
21490     /**
21491      * private, internal implementation of buildDrawingCache, used to enable tracing
21492      */
buildDrawingCacheImpl(boolean autoScale)21493     private void buildDrawingCacheImpl(boolean autoScale) {
21494         mCachingFailed = false;
21495 
21496         int width = mRight - mLeft;
21497         int height = mBottom - mTop;
21498 
21499         final AttachInfo attachInfo = mAttachInfo;
21500         final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
21501 
21502         if (autoScale && scalingRequired) {
21503             width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
21504             height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
21505         }
21506 
21507         final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
21508         final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
21509         final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
21510 
21511         final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
21512         final long drawingCacheSize =
21513                 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
21514         if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
21515             if (width > 0 && height > 0) {
21516                 Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
21517                         + " too large to fit into a software layer (or drawing cache), needs "
21518                         + projectedBitmapSize + " bytes, only "
21519                         + drawingCacheSize + " available");
21520             }
21521             destroyDrawingCache();
21522             mCachingFailed = true;
21523             return;
21524         }
21525 
21526         boolean clear = true;
21527         Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
21528 
21529         if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
21530             Bitmap.Config quality;
21531             if (!opaque) {
21532                 // Never pick ARGB_4444 because it looks awful
21533                 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
21534                 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
21535                     case DRAWING_CACHE_QUALITY_AUTO:
21536                     case DRAWING_CACHE_QUALITY_LOW:
21537                     case DRAWING_CACHE_QUALITY_HIGH:
21538                     default:
21539                         quality = Bitmap.Config.ARGB_8888;
21540                         break;
21541                 }
21542             } else {
21543                 // Optimization for translucent windows
21544                 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
21545                 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
21546             }
21547 
21548             // Try to cleanup memory
21549             if (bitmap != null) bitmap.recycle();
21550 
21551             try {
21552                 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
21553                         width, height, quality);
21554                 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
21555                 if (autoScale) {
21556                     mDrawingCache = bitmap;
21557                 } else {
21558                     mUnscaledDrawingCache = bitmap;
21559                 }
21560                 if (opaque && use32BitCache) bitmap.setHasAlpha(false);
21561             } catch (OutOfMemoryError e) {
21562                 // If there is not enough memory to create the bitmap cache, just
21563                 // ignore the issue as bitmap caches are not required to draw the
21564                 // view hierarchy
21565                 if (autoScale) {
21566                     mDrawingCache = null;
21567                 } else {
21568                     mUnscaledDrawingCache = null;
21569                 }
21570                 mCachingFailed = true;
21571                 return;
21572             }
21573 
21574             clear = drawingCacheBackgroundColor != 0;
21575         }
21576 
21577         Canvas canvas;
21578         if (attachInfo != null) {
21579             canvas = attachInfo.mCanvas;
21580             if (canvas == null) {
21581                 canvas = new Canvas();
21582             }
21583             canvas.setBitmap(bitmap);
21584             // Temporarily clobber the cached Canvas in case one of our children
21585             // is also using a drawing cache. Without this, the children would
21586             // steal the canvas by attaching their own bitmap to it and bad, bad
21587             // thing would happen (invisible views, corrupted drawings, etc.)
21588             attachInfo.mCanvas = null;
21589         } else {
21590             // This case should hopefully never or seldom happen
21591             canvas = new Canvas(bitmap);
21592         }
21593 
21594         if (clear) {
21595             bitmap.eraseColor(drawingCacheBackgroundColor);
21596         }
21597 
21598         computeScroll();
21599         final int restoreCount = canvas.save();
21600 
21601         if (autoScale && scalingRequired) {
21602             final float scale = attachInfo.mApplicationScale;
21603             canvas.scale(scale, scale);
21604         }
21605 
21606         canvas.translate(-mScrollX, -mScrollY);
21607 
21608         mPrivateFlags |= PFLAG_DRAWN;
21609         if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
21610                 mLayerType != LAYER_TYPE_NONE) {
21611             mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
21612         }
21613 
21614         // Fast path for layouts with no backgrounds
21615         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
21616             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
21617             dispatchDraw(canvas);
21618             drawAutofilledHighlight(canvas);
21619             if (mOverlay != null && !mOverlay.isEmpty()) {
21620                 mOverlay.getOverlayView().draw(canvas);
21621             }
21622         } else {
21623             draw(canvas);
21624         }
21625 
21626         canvas.restoreToCount(restoreCount);
21627         canvas.setBitmap(null);
21628 
21629         if (attachInfo != null) {
21630             // Restore the cached Canvas for our siblings
21631             attachInfo.mCanvas = canvas;
21632         }
21633     }
21634 
21635     /**
21636      * Create a snapshot of the view into a bitmap.  We should probably make
21637      * some form of this public, but should think about the API.
21638      *
21639      * @hide
21640      */
21641     @UnsupportedAppUsage
createSnapshot(ViewDebug.CanvasProvider canvasProvider, boolean skipChildren)21642     public Bitmap createSnapshot(ViewDebug.CanvasProvider canvasProvider, boolean skipChildren) {
21643         int width = mRight - mLeft;
21644         int height = mBottom - mTop;
21645 
21646         final AttachInfo attachInfo = mAttachInfo;
21647         final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
21648         width = (int) ((width * scale) + 0.5f);
21649         height = (int) ((height * scale) + 0.5f);
21650 
21651         Canvas oldCanvas = null;
21652         try {
21653             Canvas canvas = canvasProvider.getCanvas(this,
21654                     width > 0 ? width : 1, height > 0 ? height : 1);
21655 
21656             if (attachInfo != null) {
21657                 oldCanvas = attachInfo.mCanvas;
21658                 // Temporarily clobber the cached Canvas in case one of our children
21659                 // is also using a drawing cache. Without this, the children would
21660                 // steal the canvas by attaching their own bitmap to it and bad, bad
21661                 // things would happen (invisible views, corrupted drawings, etc.)
21662                 attachInfo.mCanvas = null;
21663             }
21664 
21665             computeScroll();
21666             final int restoreCount = canvas.save();
21667             canvas.scale(scale, scale);
21668             canvas.translate(-mScrollX, -mScrollY);
21669 
21670             // Temporarily remove the dirty mask
21671             int flags = mPrivateFlags;
21672             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
21673 
21674             // Fast path for layouts with no backgrounds
21675             if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
21676                 dispatchDraw(canvas);
21677                 drawAutofilledHighlight(canvas);
21678                 if (mOverlay != null && !mOverlay.isEmpty()) {
21679                     mOverlay.getOverlayView().draw(canvas);
21680                 }
21681             } else {
21682                 draw(canvas);
21683             }
21684 
21685             mPrivateFlags = flags;
21686             canvas.restoreToCount(restoreCount);
21687             return canvasProvider.createBitmap();
21688         } finally {
21689             if (oldCanvas != null) {
21690                 attachInfo.mCanvas = oldCanvas;
21691             }
21692         }
21693     }
21694 
21695     /**
21696      * Indicates whether this View is currently in edit mode. A View is usually
21697      * in edit mode when displayed within a developer tool. For instance, if
21698      * this View is being drawn by a visual user interface builder, this method
21699      * should return true.
21700      *
21701      * Subclasses should check the return value of this method to provide
21702      * different behaviors if their normal behavior might interfere with the
21703      * host environment. For instance: the class spawns a thread in its
21704      * constructor, the drawing code relies on device-specific features, etc.
21705      *
21706      * This method is usually checked in the drawing code of custom widgets.
21707      *
21708      * @return True if this View is in edit mode, false otherwise.
21709      */
isInEditMode()21710     public boolean isInEditMode() {
21711         return false;
21712     }
21713 
21714     /**
21715      * If the View draws content inside its padding and enables fading edges,
21716      * it needs to support padding offsets. Padding offsets are added to the
21717      * fading edges to extend the length of the fade so that it covers pixels
21718      * drawn inside the padding.
21719      *
21720      * Subclasses of this class should override this method if they need
21721      * to draw content inside the padding.
21722      *
21723      * @return True if padding offset must be applied, false otherwise.
21724      *
21725      * @see #getLeftPaddingOffset()
21726      * @see #getRightPaddingOffset()
21727      * @see #getTopPaddingOffset()
21728      * @see #getBottomPaddingOffset()
21729      *
21730      * @since CURRENT
21731      */
isPaddingOffsetRequired()21732     protected boolean isPaddingOffsetRequired() {
21733         return false;
21734     }
21735 
21736     /**
21737      * Amount by which to extend the left fading region. Called only when
21738      * {@link #isPaddingOffsetRequired()} returns true.
21739      *
21740      * @return The left padding offset in pixels.
21741      *
21742      * @see #isPaddingOffsetRequired()
21743      *
21744      * @since CURRENT
21745      */
getLeftPaddingOffset()21746     protected int getLeftPaddingOffset() {
21747         return 0;
21748     }
21749 
21750     /**
21751      * Amount by which to extend the right fading region. Called only when
21752      * {@link #isPaddingOffsetRequired()} returns true.
21753      *
21754      * @return The right padding offset in pixels.
21755      *
21756      * @see #isPaddingOffsetRequired()
21757      *
21758      * @since CURRENT
21759      */
getRightPaddingOffset()21760     protected int getRightPaddingOffset() {
21761         return 0;
21762     }
21763 
21764     /**
21765      * Amount by which to extend the top fading region. Called only when
21766      * {@link #isPaddingOffsetRequired()} returns true.
21767      *
21768      * @return The top padding offset in pixels.
21769      *
21770      * @see #isPaddingOffsetRequired()
21771      *
21772      * @since CURRENT
21773      */
getTopPaddingOffset()21774     protected int getTopPaddingOffset() {
21775         return 0;
21776     }
21777 
21778     /**
21779      * Amount by which to extend the bottom fading region. Called only when
21780      * {@link #isPaddingOffsetRequired()} returns true.
21781      *
21782      * @return The bottom padding offset in pixels.
21783      *
21784      * @see #isPaddingOffsetRequired()
21785      *
21786      * @since CURRENT
21787      */
getBottomPaddingOffset()21788     protected int getBottomPaddingOffset() {
21789         return 0;
21790     }
21791 
21792     /**
21793      * @hide
21794      * @param offsetRequired
21795      */
getFadeTop(boolean offsetRequired)21796     protected int getFadeTop(boolean offsetRequired) {
21797         int top = mPaddingTop;
21798         if (offsetRequired) top += getTopPaddingOffset();
21799         return top;
21800     }
21801 
21802     /**
21803      * @hide
21804      * @param offsetRequired
21805      */
getFadeHeight(boolean offsetRequired)21806     protected int getFadeHeight(boolean offsetRequired) {
21807         int padding = mPaddingTop;
21808         if (offsetRequired) padding += getTopPaddingOffset();
21809         return mBottom - mTop - mPaddingBottom - padding;
21810     }
21811 
21812     /**
21813      * <p>Indicates whether this view is attached to a hardware accelerated
21814      * window or not.</p>
21815      *
21816      * <p>Even if this method returns true, it does not mean that every call
21817      * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
21818      * accelerated {@link android.graphics.Canvas}. For instance, if this view
21819      * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
21820      * window is hardware accelerated,
21821      * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
21822      * return false, and this method will return true.</p>
21823      *
21824      * @return True if the view is attached to a window and the window is
21825      *         hardware accelerated; false in any other case.
21826      */
21827     @ViewDebug.ExportedProperty(category = "drawing")
isHardwareAccelerated()21828     public boolean isHardwareAccelerated() {
21829         return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
21830     }
21831 
21832     /**
21833      * Sets a rectangular area on this view to which the view will be clipped
21834      * when it is drawn. Setting the value to null will remove the clip bounds
21835      * and the view will draw normally, using its full bounds.
21836      *
21837      * @param clipBounds The rectangular area, in the local coordinates of
21838      * this view, to which future drawing operations will be clipped.
21839      */
setClipBounds(Rect clipBounds)21840     public void setClipBounds(Rect clipBounds) {
21841         if (clipBounds == mClipBounds
21842                 || (clipBounds != null && clipBounds.equals(mClipBounds))) {
21843             return;
21844         }
21845         if (clipBounds != null) {
21846             if (mClipBounds == null) {
21847                 mClipBounds = new Rect(clipBounds);
21848             } else {
21849                 mClipBounds.set(clipBounds);
21850             }
21851         } else {
21852             mClipBounds = null;
21853         }
21854         mRenderNode.setClipRect(mClipBounds);
21855         invalidateViewProperty(false, false);
21856     }
21857 
21858     /**
21859      * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
21860      *
21861      * @return A copy of the current clip bounds if clip bounds are set,
21862      * otherwise null.
21863      */
getClipBounds()21864     public Rect getClipBounds() {
21865         return (mClipBounds != null) ? new Rect(mClipBounds) : null;
21866     }
21867 
21868 
21869     /**
21870      * Populates an output rectangle with the clip bounds of the view,
21871      * returning {@code true} if successful or {@code false} if the view's
21872      * clip bounds are {@code null}.
21873      *
21874      * @param outRect rectangle in which to place the clip bounds of the view
21875      * @return {@code true} if successful or {@code false} if the view's
21876      *         clip bounds are {@code null}
21877      */
getClipBounds(Rect outRect)21878     public boolean getClipBounds(Rect outRect) {
21879         if (mClipBounds != null) {
21880             outRect.set(mClipBounds);
21881             return true;
21882         }
21883         return false;
21884     }
21885 
21886     /**
21887      * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
21888      * case of an active Animation being run on the view.
21889      */
applyLegacyAnimation(ViewGroup parent, long drawingTime, Animation a, boolean scalingRequired)21890     private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
21891             Animation a, boolean scalingRequired) {
21892         Transformation invalidationTransform;
21893         final int flags = parent.mGroupFlags;
21894         final boolean initialized = a.isInitialized();
21895         if (!initialized) {
21896             a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
21897             a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
21898             if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
21899             onAnimationStart();
21900         }
21901 
21902         final Transformation t = parent.getChildTransformation();
21903         boolean more = a.getTransformation(drawingTime, t, 1f);
21904         if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
21905             if (parent.mInvalidationTransformation == null) {
21906                 parent.mInvalidationTransformation = new Transformation();
21907             }
21908             invalidationTransform = parent.mInvalidationTransformation;
21909             a.getTransformation(drawingTime, invalidationTransform, 1f);
21910         } else {
21911             invalidationTransform = t;
21912         }
21913 
21914         if (more) {
21915             if (!a.willChangeBounds()) {
21916                 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
21917                         ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
21918                     parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
21919                 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
21920                     // The child need to draw an animation, potentially offscreen, so
21921                     // make sure we do not cancel invalidate requests
21922                     parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
21923                     parent.invalidate(mLeft, mTop, mRight, mBottom);
21924                 }
21925             } else {
21926                 if (parent.mInvalidateRegion == null) {
21927                     parent.mInvalidateRegion = new RectF();
21928                 }
21929                 final RectF region = parent.mInvalidateRegion;
21930                 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
21931                         invalidationTransform);
21932 
21933                 // The child need to draw an animation, potentially offscreen, so
21934                 // make sure we do not cancel invalidate requests
21935                 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
21936 
21937                 final int left = mLeft + (int) region.left;
21938                 final int top = mTop + (int) region.top;
21939                 parent.invalidate(left, top, left + (int) (region.width() + .5f),
21940                         top + (int) (region.height() + .5f));
21941             }
21942         }
21943         return more;
21944     }
21945 
21946     /**
21947      * This method is called by getDisplayList() when a display list is recorded for a View.
21948      * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
21949      */
setDisplayListProperties(RenderNode renderNode)21950     void setDisplayListProperties(RenderNode renderNode) {
21951         if (renderNode != null) {
21952             renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
21953             renderNode.setClipToBounds(mParent instanceof ViewGroup
21954                     && ((ViewGroup) mParent).getClipChildren());
21955 
21956             float alpha = 1;
21957             if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
21958                     ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
21959                 ViewGroup parentVG = (ViewGroup) mParent;
21960                 final Transformation t = parentVG.getChildTransformation();
21961                 if (parentVG.getChildStaticTransformation(this, t)) {
21962                     final int transformType = t.getTransformationType();
21963                     if (transformType != Transformation.TYPE_IDENTITY) {
21964                         if ((transformType & Transformation.TYPE_ALPHA) != 0) {
21965                             alpha = t.getAlpha();
21966                         }
21967                         if ((transformType & Transformation.TYPE_MATRIX) != 0) {
21968                             renderNode.setStaticMatrix(t.getMatrix());
21969                         }
21970                     }
21971                 }
21972             }
21973             if (mTransformationInfo != null) {
21974                 alpha *= getFinalAlpha();
21975                 if (alpha < 1) {
21976                     final int multipliedAlpha = (int) (255 * alpha);
21977                     if (onSetAlpha(multipliedAlpha)) {
21978                         alpha = 1;
21979                     }
21980                 }
21981                 renderNode.setAlpha(alpha);
21982             } else if (alpha < 1) {
21983                 renderNode.setAlpha(alpha);
21984             }
21985         }
21986     }
21987 
21988     /**
21989      * This method is called by ViewGroup.drawChild() to have each child view draw itself.
21990      *
21991      * This is where the View specializes rendering behavior based on layer type,
21992      * and hardware acceleration.
21993      */
draw(Canvas canvas, ViewGroup parent, long drawingTime)21994     boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
21995         final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
21996         /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
21997          *
21998          * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
21999          * HW accelerated, it can't handle drawing RenderNodes.
22000          */
22001         boolean drawingWithRenderNode = mAttachInfo != null
22002                 && mAttachInfo.mHardwareAccelerated
22003                 && hardwareAcceleratedCanvas;
22004 
22005         boolean more = false;
22006         final boolean childHasIdentityMatrix = hasIdentityMatrix();
22007         final int parentFlags = parent.mGroupFlags;
22008 
22009         if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
22010             parent.getChildTransformation().clear();
22011             parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
22012         }
22013 
22014         Transformation transformToApply = null;
22015         boolean concatMatrix = false;
22016         final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
22017         final Animation a = getAnimation();
22018         if (a != null) {
22019             more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
22020             concatMatrix = a.willChangeTransformationMatrix();
22021             if (concatMatrix) {
22022                 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
22023             }
22024             transformToApply = parent.getChildTransformation();
22025         } else {
22026             if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
22027                 // No longer animating: clear out old animation matrix
22028                 mRenderNode.setAnimationMatrix(null);
22029                 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
22030             }
22031             if (!drawingWithRenderNode
22032                     && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
22033                 final Transformation t = parent.getChildTransformation();
22034                 final boolean hasTransform = parent.getChildStaticTransformation(this, t);
22035                 if (hasTransform) {
22036                     final int transformType = t.getTransformationType();
22037                     transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
22038                     concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
22039                 }
22040             }
22041         }
22042 
22043         concatMatrix |= !childHasIdentityMatrix;
22044 
22045         // Sets the flag as early as possible to allow draw() implementations
22046         // to call invalidate() successfully when doing animations
22047         mPrivateFlags |= PFLAG_DRAWN;
22048 
22049         if (!concatMatrix &&
22050                 (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
22051                         ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
22052                 canvas.quickReject(mLeft, mTop, mRight, mBottom) &&
22053                 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
22054             mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
22055             return more;
22056         }
22057         mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
22058 
22059         if (hardwareAcceleratedCanvas) {
22060             // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
22061             // retain the flag's value temporarily in the mRecreateDisplayList flag
22062             mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
22063             mPrivateFlags &= ~PFLAG_INVALIDATED;
22064         }
22065 
22066         RenderNode renderNode = null;
22067         Bitmap cache = null;
22068         int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
22069         if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
22070              if (layerType != LAYER_TYPE_NONE) {
22071                  // If not drawing with RenderNode, treat HW layers as SW
22072                  layerType = LAYER_TYPE_SOFTWARE;
22073                  buildDrawingCache(true);
22074             }
22075             cache = getDrawingCache(true);
22076         }
22077 
22078         if (drawingWithRenderNode) {
22079             // Delay getting the display list until animation-driven alpha values are
22080             // set up and possibly passed on to the view
22081             renderNode = updateDisplayListIfDirty();
22082             if (!renderNode.hasDisplayList()) {
22083                 // Uncommon, but possible. If a view is removed from the hierarchy during the call
22084                 // to getDisplayList(), the display list will be marked invalid and we should not
22085                 // try to use it again.
22086                 renderNode = null;
22087                 drawingWithRenderNode = false;
22088             }
22089         }
22090 
22091         int sx = 0;
22092         int sy = 0;
22093         if (!drawingWithRenderNode) {
22094             computeScroll();
22095             sx = mScrollX;
22096             sy = mScrollY;
22097         }
22098 
22099         final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
22100         final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
22101 
22102         int restoreTo = -1;
22103         if (!drawingWithRenderNode || transformToApply != null) {
22104             restoreTo = canvas.save();
22105         }
22106         if (offsetForScroll) {
22107             canvas.translate(mLeft - sx, mTop - sy);
22108         } else {
22109             if (!drawingWithRenderNode) {
22110                 canvas.translate(mLeft, mTop);
22111             }
22112             if (scalingRequired) {
22113                 if (drawingWithRenderNode) {
22114                     // TODO: Might not need this if we put everything inside the DL
22115                     restoreTo = canvas.save();
22116                 }
22117                 // mAttachInfo cannot be null, otherwise scalingRequired == false
22118                 final float scale = 1.0f / mAttachInfo.mApplicationScale;
22119                 canvas.scale(scale, scale);
22120             }
22121         }
22122 
22123         float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
22124         if (transformToApply != null
22125                 || alpha < 1
22126                 || !hasIdentityMatrix()
22127                 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
22128             if (transformToApply != null || !childHasIdentityMatrix) {
22129                 int transX = 0;
22130                 int transY = 0;
22131 
22132                 if (offsetForScroll) {
22133                     transX = -sx;
22134                     transY = -sy;
22135                 }
22136 
22137                 if (transformToApply != null) {
22138                     if (concatMatrix) {
22139                         if (drawingWithRenderNode) {
22140                             renderNode.setAnimationMatrix(transformToApply.getMatrix());
22141                         } else {
22142                             // Undo the scroll translation, apply the transformation matrix,
22143                             // then redo the scroll translate to get the correct result.
22144                             canvas.translate(-transX, -transY);
22145                             canvas.concat(transformToApply.getMatrix());
22146                             canvas.translate(transX, transY);
22147                         }
22148                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
22149                     }
22150 
22151                     float transformAlpha = transformToApply.getAlpha();
22152                     if (transformAlpha < 1) {
22153                         alpha *= transformAlpha;
22154                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
22155                     }
22156                 }
22157 
22158                 if (!childHasIdentityMatrix && !drawingWithRenderNode) {
22159                     canvas.translate(-transX, -transY);
22160                     canvas.concat(getMatrix());
22161                     canvas.translate(transX, transY);
22162                 }
22163             }
22164 
22165             // Deal with alpha if it is or used to be <1
22166             if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
22167                 if (alpha < 1) {
22168                     mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
22169                 } else {
22170                     mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
22171                 }
22172                 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
22173                 if (!drawingWithDrawingCache) {
22174                     final int multipliedAlpha = (int) (255 * alpha);
22175                     if (!onSetAlpha(multipliedAlpha)) {
22176                         if (drawingWithRenderNode) {
22177                             renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
22178                         } else if (layerType == LAYER_TYPE_NONE) {
22179                             canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
22180                                     multipliedAlpha);
22181                         }
22182                     } else {
22183                         // Alpha is handled by the child directly, clobber the layer's alpha
22184                         mPrivateFlags |= PFLAG_ALPHA_SET;
22185                     }
22186                 }
22187             }
22188         } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
22189             onSetAlpha(255);
22190             mPrivateFlags &= ~PFLAG_ALPHA_SET;
22191         }
22192 
22193         if (!drawingWithRenderNode) {
22194             // apply clips directly, since RenderNode won't do it for this draw
22195             if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
22196                 if (offsetForScroll) {
22197                     canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
22198                 } else {
22199                     if (!scalingRequired || cache == null) {
22200                         canvas.clipRect(0, 0, getWidth(), getHeight());
22201                     } else {
22202                         canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
22203                     }
22204                 }
22205             }
22206 
22207             if (mClipBounds != null) {
22208                 // clip bounds ignore scroll
22209                 canvas.clipRect(mClipBounds);
22210             }
22211         }
22212 
22213         if (!drawingWithDrawingCache) {
22214             if (drawingWithRenderNode) {
22215                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
22216                 ((RecordingCanvas) canvas).drawRenderNode(renderNode);
22217             } else {
22218                 // Fast path for layouts with no backgrounds
22219                 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
22220                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
22221                     dispatchDraw(canvas);
22222                 } else {
22223                     draw(canvas);
22224                 }
22225             }
22226         } else if (cache != null) {
22227             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
22228             if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
22229                 // no layer paint, use temporary paint to draw bitmap
22230                 Paint cachePaint = parent.mCachePaint;
22231                 if (cachePaint == null) {
22232                     cachePaint = new Paint();
22233                     cachePaint.setDither(false);
22234                     parent.mCachePaint = cachePaint;
22235                 }
22236                 cachePaint.setAlpha((int) (alpha * 255));
22237                 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
22238             } else {
22239                 // use layer paint to draw the bitmap, merging the two alphas, but also restore
22240                 int layerPaintAlpha = mLayerPaint.getAlpha();
22241                 if (alpha < 1) {
22242                     mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
22243                 }
22244                 canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
22245                 if (alpha < 1) {
22246                     mLayerPaint.setAlpha(layerPaintAlpha);
22247                 }
22248             }
22249         }
22250 
22251         if (restoreTo >= 0) {
22252             canvas.restoreToCount(restoreTo);
22253         }
22254 
22255         if (a != null && !more) {
22256             if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
22257                 onSetAlpha(255);
22258             }
22259             parent.finishAnimatingView(this, a);
22260         }
22261 
22262         if (more && hardwareAcceleratedCanvas) {
22263             if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
22264                 // alpha animations should cause the child to recreate its display list
22265                 invalidate(true);
22266             }
22267         }
22268 
22269         mRecreateDisplayList = false;
22270 
22271         return more;
22272     }
22273 
getDebugPaint()22274     static Paint getDebugPaint() {
22275         if (sDebugPaint == null) {
22276             sDebugPaint = new Paint();
22277             sDebugPaint.setAntiAlias(false);
22278         }
22279         return sDebugPaint;
22280     }
22281 
dipsToPixels(int dips)22282     final int dipsToPixels(int dips) {
22283         float scale = getContext().getResources().getDisplayMetrics().density;
22284         return (int) (dips * scale + 0.5f);
22285     }
22286 
debugDrawFocus(Canvas canvas)22287     final private void debugDrawFocus(Canvas canvas) {
22288         if (isFocused()) {
22289             final int cornerSquareSize = dipsToPixels(DEBUG_CORNERS_SIZE_DIP);
22290             final int l = mScrollX;
22291             final int r = l + mRight - mLeft;
22292             final int t = mScrollY;
22293             final int b = t + mBottom - mTop;
22294 
22295             final Paint paint = getDebugPaint();
22296             paint.setColor(DEBUG_CORNERS_COLOR);
22297 
22298             // Draw squares in corners.
22299             paint.setStyle(Paint.Style.FILL);
22300             canvas.drawRect(l, t, l + cornerSquareSize, t + cornerSquareSize, paint);
22301             canvas.drawRect(r - cornerSquareSize, t, r, t + cornerSquareSize, paint);
22302             canvas.drawRect(l, b - cornerSquareSize, l + cornerSquareSize, b, paint);
22303             canvas.drawRect(r - cornerSquareSize, b - cornerSquareSize, r, b, paint);
22304 
22305             // Draw big X across the view.
22306             paint.setStyle(Paint.Style.STROKE);
22307             canvas.drawLine(l, t, r, b, paint);
22308             canvas.drawLine(l, b, r, t, paint);
22309         }
22310     }
22311 
22312     /**
22313      * Manually render this view (and all of its children) to the given Canvas.
22314      * The view must have already done a full layout before this function is
22315      * called.  When implementing a view, implement
22316      * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
22317      * If you do need to override this method, call the superclass version.
22318      *
22319      * @param canvas The Canvas to which the View is rendered.
22320      */
22321     @CallSuper
draw(Canvas canvas)22322     public void draw(Canvas canvas) {
22323         final int privateFlags = mPrivateFlags;
22324         mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
22325 
22326         /*
22327          * Draw traversal performs several drawing steps which must be executed
22328          * in the appropriate order:
22329          *
22330          *      1. Draw the background
22331          *      2. If necessary, save the canvas' layers to prepare for fading
22332          *      3. Draw view's content
22333          *      4. Draw children
22334          *      5. If necessary, draw the fading edges and restore layers
22335          *      6. Draw decorations (scrollbars for instance)
22336          *      7. If necessary, draw the default focus highlight
22337          */
22338 
22339         // Step 1, draw the background, if needed
22340         int saveCount;
22341 
22342         drawBackground(canvas);
22343 
22344         // skip step 2 & 5 if possible (common case)
22345         final int viewFlags = mViewFlags;
22346         boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
22347         boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
22348         if (!verticalEdges && !horizontalEdges) {
22349             // Step 3, draw the content
22350             onDraw(canvas);
22351 
22352             // Step 4, draw the children
22353             dispatchDraw(canvas);
22354 
22355             drawAutofilledHighlight(canvas);
22356 
22357             // Overlay is part of the content and draws beneath Foreground
22358             if (mOverlay != null && !mOverlay.isEmpty()) {
22359                 mOverlay.getOverlayView().dispatchDraw(canvas);
22360             }
22361 
22362             // Step 6, draw decorations (foreground, scrollbars)
22363             onDrawForeground(canvas);
22364 
22365             // Step 7, draw the default focus highlight
22366             drawDefaultFocusHighlight(canvas);
22367 
22368             if (isShowingLayoutBounds()) {
22369                 debugDrawFocus(canvas);
22370             }
22371 
22372             // we're done...
22373             return;
22374         }
22375 
22376         /*
22377          * Here we do the full fledged routine...
22378          * (this is an uncommon case where speed matters less,
22379          * this is why we repeat some of the tests that have been
22380          * done above)
22381          */
22382 
22383         boolean drawTop = false;
22384         boolean drawBottom = false;
22385         boolean drawLeft = false;
22386         boolean drawRight = false;
22387 
22388         float topFadeStrength = 0.0f;
22389         float bottomFadeStrength = 0.0f;
22390         float leftFadeStrength = 0.0f;
22391         float rightFadeStrength = 0.0f;
22392 
22393         // Step 2, save the canvas' layers
22394         int paddingLeft = mPaddingLeft;
22395 
22396         final boolean offsetRequired = isPaddingOffsetRequired();
22397         if (offsetRequired) {
22398             paddingLeft += getLeftPaddingOffset();
22399         }
22400 
22401         int left = mScrollX + paddingLeft;
22402         int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
22403         int top = mScrollY + getFadeTop(offsetRequired);
22404         int bottom = top + getFadeHeight(offsetRequired);
22405 
22406         if (offsetRequired) {
22407             right += getRightPaddingOffset();
22408             bottom += getBottomPaddingOffset();
22409         }
22410 
22411         final ScrollabilityCache scrollabilityCache = mScrollCache;
22412         final float fadeHeight = scrollabilityCache.fadingEdgeLength;
22413         int length = (int) fadeHeight;
22414 
22415         // clip the fade length if top and bottom fades overlap
22416         // overlapping fades produce odd-looking artifacts
22417         if (verticalEdges && (top + length > bottom - length)) {
22418             length = (bottom - top) / 2;
22419         }
22420 
22421         // also clip horizontal fades if necessary
22422         if (horizontalEdges && (left + length > right - length)) {
22423             length = (right - left) / 2;
22424         }
22425 
22426         if (verticalEdges) {
22427             topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
22428             drawTop = topFadeStrength * fadeHeight > 1.0f;
22429             bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
22430             drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
22431         }
22432 
22433         if (horizontalEdges) {
22434             leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
22435             drawLeft = leftFadeStrength * fadeHeight > 1.0f;
22436             rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
22437             drawRight = rightFadeStrength * fadeHeight > 1.0f;
22438         }
22439 
22440         saveCount = canvas.getSaveCount();
22441         int topSaveCount = -1;
22442         int bottomSaveCount = -1;
22443         int leftSaveCount = -1;
22444         int rightSaveCount = -1;
22445 
22446         int solidColor = getSolidColor();
22447         if (solidColor == 0) {
22448             if (drawTop) {
22449                 topSaveCount = canvas.saveUnclippedLayer(left, top, right, top + length);
22450             }
22451 
22452             if (drawBottom) {
22453                 bottomSaveCount = canvas.saveUnclippedLayer(left, bottom - length, right, bottom);
22454             }
22455 
22456             if (drawLeft) {
22457                 leftSaveCount = canvas.saveUnclippedLayer(left, top, left + length, bottom);
22458             }
22459 
22460             if (drawRight) {
22461                 rightSaveCount = canvas.saveUnclippedLayer(right - length, top, right, bottom);
22462             }
22463         } else {
22464             scrollabilityCache.setFadeColor(solidColor);
22465         }
22466 
22467         // Step 3, draw the content
22468         onDraw(canvas);
22469 
22470         // Step 4, draw the children
22471         dispatchDraw(canvas);
22472 
22473         // Step 5, draw the fade effect and restore layers
22474         final Paint p = scrollabilityCache.paint;
22475         final Matrix matrix = scrollabilityCache.matrix;
22476         final Shader fade = scrollabilityCache.shader;
22477 
22478         // must be restored in the reverse order that they were saved
22479         if (drawRight) {
22480             matrix.setScale(1, fadeHeight * rightFadeStrength);
22481             matrix.postRotate(90);
22482             matrix.postTranslate(right, top);
22483             fade.setLocalMatrix(matrix);
22484             p.setShader(fade);
22485             if (solidColor == 0) {
22486                 canvas.restoreUnclippedLayer(rightSaveCount, p);
22487 
22488             } else {
22489                 canvas.drawRect(right - length, top, right, bottom, p);
22490             }
22491         }
22492 
22493         if (drawLeft) {
22494             matrix.setScale(1, fadeHeight * leftFadeStrength);
22495             matrix.postRotate(-90);
22496             matrix.postTranslate(left, top);
22497             fade.setLocalMatrix(matrix);
22498             p.setShader(fade);
22499             if (solidColor == 0) {
22500                 canvas.restoreUnclippedLayer(leftSaveCount, p);
22501             } else {
22502                 canvas.drawRect(left, top, left + length, bottom, p);
22503             }
22504         }
22505 
22506         if (drawBottom) {
22507             matrix.setScale(1, fadeHeight * bottomFadeStrength);
22508             matrix.postRotate(180);
22509             matrix.postTranslate(left, bottom);
22510             fade.setLocalMatrix(matrix);
22511             p.setShader(fade);
22512             if (solidColor == 0) {
22513                 canvas.restoreUnclippedLayer(bottomSaveCount, p);
22514             } else {
22515                 canvas.drawRect(left, bottom - length, right, bottom, p);
22516             }
22517         }
22518 
22519         if (drawTop) {
22520             matrix.setScale(1, fadeHeight * topFadeStrength);
22521             matrix.postTranslate(left, top);
22522             fade.setLocalMatrix(matrix);
22523             p.setShader(fade);
22524             if (solidColor == 0) {
22525                 canvas.restoreUnclippedLayer(topSaveCount, p);
22526             } else {
22527                 canvas.drawRect(left, top, right, top + length, p);
22528             }
22529         }
22530 
22531         canvas.restoreToCount(saveCount);
22532 
22533         drawAutofilledHighlight(canvas);
22534 
22535         // Overlay is part of the content and draws beneath Foreground
22536         if (mOverlay != null && !mOverlay.isEmpty()) {
22537             mOverlay.getOverlayView().dispatchDraw(canvas);
22538         }
22539 
22540         // Step 6, draw decorations (foreground, scrollbars)
22541         onDrawForeground(canvas);
22542 
22543         // Step 7, draw the default focus highlight
22544         drawDefaultFocusHighlight(canvas);
22545 
22546         if (isShowingLayoutBounds()) {
22547             debugDrawFocus(canvas);
22548         }
22549     }
22550 
22551     /**
22552      * Draws the background onto the specified canvas.
22553      *
22554      * @param canvas Canvas on which to draw the background
22555      */
22556     @UnsupportedAppUsage
drawBackground(Canvas canvas)22557     private void drawBackground(Canvas canvas) {
22558         final Drawable background = mBackground;
22559         if (background == null) {
22560             return;
22561         }
22562 
22563         setBackgroundBounds();
22564 
22565         // Attempt to use a display list if requested.
22566         if (canvas.isHardwareAccelerated() && mAttachInfo != null
22567                 && mAttachInfo.mThreadedRenderer != null) {
22568             mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
22569 
22570             final RenderNode renderNode = mBackgroundRenderNode;
22571             if (renderNode != null && renderNode.hasDisplayList()) {
22572                 setBackgroundRenderNodeProperties(renderNode);
22573                 ((RecordingCanvas) canvas).drawRenderNode(renderNode);
22574                 return;
22575             }
22576         }
22577 
22578         final int scrollX = mScrollX;
22579         final int scrollY = mScrollY;
22580         if ((scrollX | scrollY) == 0) {
22581             background.draw(canvas);
22582         } else {
22583             canvas.translate(scrollX, scrollY);
22584             background.draw(canvas);
22585             canvas.translate(-scrollX, -scrollY);
22586         }
22587     }
22588 
22589     /**
22590      * Sets the correct background bounds and rebuilds the outline, if needed.
22591      * <p/>
22592      * This is called by LayoutLib.
22593      */
setBackgroundBounds()22594     void setBackgroundBounds() {
22595         if (mBackgroundSizeChanged && mBackground != null) {
22596             mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
22597             mBackgroundSizeChanged = false;
22598             rebuildOutline();
22599         }
22600     }
22601 
setBackgroundRenderNodeProperties(RenderNode renderNode)22602     private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
22603         renderNode.setTranslationX(mScrollX);
22604         renderNode.setTranslationY(mScrollY);
22605     }
22606 
22607     /**
22608      * Creates a new display list or updates the existing display list for the
22609      * specified Drawable.
22610      *
22611      * @param drawable Drawable for which to create a display list
22612      * @param renderNode Existing RenderNode, or {@code null}
22613      * @return A valid display list for the specified drawable
22614      */
getDrawableRenderNode(Drawable drawable, RenderNode renderNode)22615     private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
22616         if (renderNode == null) {
22617             renderNode = RenderNode.create(drawable.getClass().getName(),
22618                     new ViewAnimationHostBridge(this));
22619             renderNode.setUsageHint(RenderNode.USAGE_BACKGROUND);
22620         }
22621 
22622         final Rect bounds = drawable.getBounds();
22623         final int width = bounds.width();
22624         final int height = bounds.height();
22625         final RecordingCanvas canvas = renderNode.beginRecording(width, height);
22626 
22627         // Reverse left/top translation done by drawable canvas, which will
22628         // instead be applied by rendernode's LTRB bounds below. This way, the
22629         // drawable's bounds match with its rendernode bounds and its content
22630         // will lie within those bounds in the rendernode tree.
22631         canvas.translate(-bounds.left, -bounds.top);
22632 
22633         try {
22634             drawable.draw(canvas);
22635         } finally {
22636             renderNode.endRecording();
22637         }
22638 
22639         // Set up drawable properties that are view-independent.
22640         renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
22641         renderNode.setProjectBackwards(drawable.isProjected());
22642         renderNode.setProjectionReceiver(true);
22643         renderNode.setClipToBounds(false);
22644         return renderNode;
22645     }
22646 
22647     /**
22648      * Returns the overlay for this view, creating it if it does not yet exist.
22649      * Adding drawables to the overlay will cause them to be displayed whenever
22650      * the view itself is redrawn. Objects in the overlay should be actively
22651      * managed: remove them when they should not be displayed anymore. The
22652      * overlay will always have the same size as its host view.
22653      *
22654      * <p>Note: Overlays do not currently work correctly with {@link
22655      * SurfaceView} or {@link TextureView}; contents in overlays for these
22656      * types of views may not display correctly.</p>
22657      *
22658      * @return The ViewOverlay object for this view.
22659      * @see ViewOverlay
22660      */
getOverlay()22661     public ViewOverlay getOverlay() {
22662         if (mOverlay == null) {
22663             mOverlay = new ViewOverlay(mContext, this);
22664         }
22665         return mOverlay;
22666     }
22667 
22668     /**
22669      * Override this if your view is known to always be drawn on top of a solid color background,
22670      * and needs to draw fading edges. Returning a non-zero color enables the view system to
22671      * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
22672      * should be set to 0xFF.
22673      *
22674      * @see #setVerticalFadingEdgeEnabled(boolean)
22675      * @see #setHorizontalFadingEdgeEnabled(boolean)
22676      *
22677      * @return The known solid color background for this view, or 0 if the color may vary
22678      */
22679     @ViewDebug.ExportedProperty(category = "drawing")
22680     @InspectableProperty
22681     @ColorInt
getSolidColor()22682     public int getSolidColor() {
22683         return 0;
22684     }
22685 
22686     /**
22687      * Build a human readable string representation of the specified view flags.
22688      *
22689      * @param flags the view flags to convert to a string
22690      * @return a String representing the supplied flags
22691      */
printFlags(int flags)22692     private static String printFlags(int flags) {
22693         String output = "";
22694         int numFlags = 0;
22695         if ((flags & FOCUSABLE) == FOCUSABLE) {
22696             output += "TAKES_FOCUS";
22697             numFlags++;
22698         }
22699 
22700         switch (flags & VISIBILITY_MASK) {
22701         case INVISIBLE:
22702             if (numFlags > 0) {
22703                 output += " ";
22704             }
22705             output += "INVISIBLE";
22706             // USELESS HERE numFlags++;
22707             break;
22708         case GONE:
22709             if (numFlags > 0) {
22710                 output += " ";
22711             }
22712             output += "GONE";
22713             // USELESS HERE numFlags++;
22714             break;
22715         default:
22716             break;
22717         }
22718         return output;
22719     }
22720 
22721     /**
22722      * Build a human readable string representation of the specified private
22723      * view flags.
22724      *
22725      * @param privateFlags the private view flags to convert to a string
22726      * @return a String representing the supplied flags
22727      */
printPrivateFlags(int privateFlags)22728     private static String printPrivateFlags(int privateFlags) {
22729         String output = "";
22730         int numFlags = 0;
22731 
22732         if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
22733             output += "WANTS_FOCUS";
22734             numFlags++;
22735         }
22736 
22737         if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
22738             if (numFlags > 0) {
22739                 output += " ";
22740             }
22741             output += "FOCUSED";
22742             numFlags++;
22743         }
22744 
22745         if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
22746             if (numFlags > 0) {
22747                 output += " ";
22748             }
22749             output += "SELECTED";
22750             numFlags++;
22751         }
22752 
22753         if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
22754             if (numFlags > 0) {
22755                 output += " ";
22756             }
22757             output += "IS_ROOT_NAMESPACE";
22758             numFlags++;
22759         }
22760 
22761         if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
22762             if (numFlags > 0) {
22763                 output += " ";
22764             }
22765             output += "HAS_BOUNDS";
22766             numFlags++;
22767         }
22768 
22769         if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
22770             if (numFlags > 0) {
22771                 output += " ";
22772             }
22773             output += "DRAWN";
22774             // USELESS HERE numFlags++;
22775         }
22776         return output;
22777     }
22778 
22779     /**
22780      * <p>Indicates whether or not this view's layout will be requested during
22781      * the next hierarchy layout pass.</p>
22782      *
22783      * @return true if the layout will be forced during next layout pass
22784      */
isLayoutRequested()22785     public boolean isLayoutRequested() {
22786         return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
22787     }
22788 
22789     /**
22790      * Return true if o is a ViewGroup that is laying out using optical bounds.
22791      * @hide
22792      */
isLayoutModeOptical(Object o)22793     public static boolean isLayoutModeOptical(Object o) {
22794         return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
22795     }
22796 
setOpticalFrame(int left, int top, int right, int bottom)22797     private boolean setOpticalFrame(int left, int top, int right, int bottom) {
22798         Insets parentInsets = mParent instanceof View ?
22799                 ((View) mParent).getOpticalInsets() : Insets.NONE;
22800         Insets childInsets = getOpticalInsets();
22801         return setFrame(
22802                 left   + parentInsets.left - childInsets.left,
22803                 top    + parentInsets.top  - childInsets.top,
22804                 right  + parentInsets.left + childInsets.right,
22805                 bottom + parentInsets.top  + childInsets.bottom);
22806     }
22807 
22808     /**
22809      * Assign a size and position to a view and all of its
22810      * descendants
22811      *
22812      * <p>This is the second phase of the layout mechanism.
22813      * (The first is measuring). In this phase, each parent calls
22814      * layout on all of its children to position them.
22815      * This is typically done using the child measurements
22816      * that were stored in the measure pass().</p>
22817      *
22818      * <p>Derived classes should not override this method.
22819      * Derived classes with children should override
22820      * onLayout. In that method, they should
22821      * call layout on each of their children.</p>
22822      *
22823      * @param l Left position, relative to parent
22824      * @param t Top position, relative to parent
22825      * @param r Right position, relative to parent
22826      * @param b Bottom position, relative to parent
22827      */
22828     @SuppressWarnings({"unchecked"})
layout(int l, int t, int r, int b)22829     public void layout(int l, int t, int r, int b) {
22830         if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
22831             onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
22832             mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
22833         }
22834 
22835         int oldL = mLeft;
22836         int oldT = mTop;
22837         int oldB = mBottom;
22838         int oldR = mRight;
22839 
22840         boolean changed = isLayoutModeOptical(mParent) ?
22841                 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
22842 
22843         if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
22844             onLayout(changed, l, t, r, b);
22845 
22846             if (shouldDrawRoundScrollbar()) {
22847                 if(mRoundScrollbarRenderer == null) {
22848                     mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
22849                 }
22850             } else {
22851                 mRoundScrollbarRenderer = null;
22852             }
22853 
22854             mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
22855 
22856             ListenerInfo li = mListenerInfo;
22857             if (li != null && li.mOnLayoutChangeListeners != null) {
22858                 ArrayList<OnLayoutChangeListener> listenersCopy =
22859                         (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
22860                 int numListeners = listenersCopy.size();
22861                 for (int i = 0; i < numListeners; ++i) {
22862                     listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
22863                 }
22864             }
22865         }
22866 
22867         final boolean wasLayoutValid = isLayoutValid();
22868 
22869         mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
22870         mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
22871 
22872         if (!wasLayoutValid && isFocused()) {
22873             mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
22874             if (canTakeFocus()) {
22875                 // We have a robust focus, so parents should no longer be wanting focus.
22876                 clearParentsWantFocus();
22877             } else if (getViewRootImpl() == null || !getViewRootImpl().isInLayout()) {
22878                 // This is a weird case. Most-likely the user, rather than ViewRootImpl, called
22879                 // layout. In this case, there's no guarantee that parent layouts will be evaluated
22880                 // and thus the safest action is to clear focus here.
22881                 clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
22882                 clearParentsWantFocus();
22883             } else if (!hasParentWantsFocus()) {
22884                 // original requestFocus was likely on this view directly, so just clear focus
22885                 clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
22886             }
22887             // otherwise, we let parents handle re-assigning focus during their layout passes.
22888         } else if ((mPrivateFlags & PFLAG_WANTS_FOCUS) != 0) {
22889             mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
22890             View focused = findFocus();
22891             if (focused != null) {
22892                 // Try to restore focus as close as possible to our starting focus.
22893                 if (!restoreDefaultFocus() && !hasParentWantsFocus()) {
22894                     // Give up and clear focus once we've reached the top-most parent which wants
22895                     // focus.
22896                     focused.clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
22897                 }
22898             }
22899         }
22900 
22901         if ((mPrivateFlags3 & PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT) != 0) {
22902             mPrivateFlags3 &= ~PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
22903             notifyEnterOrExitForAutoFillIfNeeded(true);
22904         }
22905 
22906         notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
22907     }
22908 
hasParentWantsFocus()22909     private boolean hasParentWantsFocus() {
22910         ViewParent parent = mParent;
22911         while (parent instanceof ViewGroup) {
22912             ViewGroup pv = (ViewGroup) parent;
22913             if ((pv.mPrivateFlags & PFLAG_WANTS_FOCUS) != 0) {
22914                 return true;
22915             }
22916             parent = pv.mParent;
22917         }
22918         return false;
22919     }
22920 
22921     /**
22922      * Called from layout when this view should
22923      * assign a size and position to each of its children.
22924      *
22925      * Derived classes with children should override
22926      * this method and call layout on each of
22927      * their children.
22928      * @param changed This is a new size or position for this view
22929      * @param left Left position, relative to parent
22930      * @param top Top position, relative to parent
22931      * @param right Right position, relative to parent
22932      * @param bottom Bottom position, relative to parent
22933      */
onLayout(boolean changed, int left, int top, int right, int bottom)22934     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
22935     }
22936 
22937     /**
22938      * Assign a size and position to this view.
22939      *
22940      * This is called from layout.
22941      *
22942      * @param left Left position, relative to parent
22943      * @param top Top position, relative to parent
22944      * @param right Right position, relative to parent
22945      * @param bottom Bottom position, relative to parent
22946      * @return true if the new size and position are different than the
22947      *         previous ones
22948      * {@hide}
22949      */
22950     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
setFrame(int left, int top, int right, int bottom)22951     protected boolean setFrame(int left, int top, int right, int bottom) {
22952         boolean changed = false;
22953 
22954         if (DBG) {
22955             Log.d(VIEW_LOG_TAG, this + " View.setFrame(" + left + "," + top + ","
22956                     + right + "," + bottom + ")");
22957         }
22958 
22959         if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
22960             changed = true;
22961 
22962             // Remember our drawn bit
22963             int drawn = mPrivateFlags & PFLAG_DRAWN;
22964 
22965             int oldWidth = mRight - mLeft;
22966             int oldHeight = mBottom - mTop;
22967             int newWidth = right - left;
22968             int newHeight = bottom - top;
22969             boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
22970 
22971             // Invalidate our old position
22972             invalidate(sizeChanged);
22973 
22974             mLeft = left;
22975             mTop = top;
22976             mRight = right;
22977             mBottom = bottom;
22978             mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
22979 
22980             mPrivateFlags |= PFLAG_HAS_BOUNDS;
22981 
22982 
22983             if (sizeChanged) {
22984                 sizeChange(newWidth, newHeight, oldWidth, oldHeight);
22985             }
22986 
22987             if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
22988                 // If we are visible, force the DRAWN bit to on so that
22989                 // this invalidate will go through (at least to our parent).
22990                 // This is because someone may have invalidated this view
22991                 // before this call to setFrame came in, thereby clearing
22992                 // the DRAWN bit.
22993                 mPrivateFlags |= PFLAG_DRAWN;
22994                 invalidate(sizeChanged);
22995                 // parent display list may need to be recreated based on a change in the bounds
22996                 // of any child
22997                 invalidateParentCaches();
22998             }
22999 
23000             // Reset drawn bit to original value (invalidate turns it off)
23001             mPrivateFlags |= drawn;
23002 
23003             mBackgroundSizeChanged = true;
23004             mDefaultFocusHighlightSizeChanged = true;
23005             if (mForegroundInfo != null) {
23006                 mForegroundInfo.mBoundsChanged = true;
23007             }
23008 
23009             notifySubtreeAccessibilityStateChangedIfNeeded();
23010         }
23011         return changed;
23012     }
23013 
23014     /**
23015      * Assign a size and position to this view.
23016      *
23017      * This method is meant to be used in animations only as it applies this position and size
23018      * for the view only temporary and it can be changed back at any time by the layout.
23019      *
23020      * @param left Left position, relative to parent
23021      * @param top Top position, relative to parent
23022      * @param right Right position, relative to parent
23023      * @param bottom Bottom position, relative to parent
23024      *
23025      * @see #setLeft(int), #setRight(int), #setTop(int), #setBottom(int)
23026      */
setLeftTopRightBottom(int left, int top, int right, int bottom)23027     public final void setLeftTopRightBottom(int left, int top, int right, int bottom) {
23028         setFrame(left, top, right, bottom);
23029     }
23030 
sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight)23031     private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
23032         onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
23033         if (mOverlay != null) {
23034             mOverlay.getOverlayView().setRight(newWidth);
23035             mOverlay.getOverlayView().setBottom(newHeight);
23036         }
23037         // If this isn't laid out yet, focus assignment will be handled during the "deferment/
23038         // backtracking" of requestFocus during layout, so don't touch focus here.
23039         if (!sCanFocusZeroSized && isLayoutValid()
23040                 // Don't touch focus if animating
23041                 && !(mParent instanceof ViewGroup && ((ViewGroup) mParent).isLayoutSuppressed())) {
23042             if (newWidth <= 0 || newHeight <= 0) {
23043                 if (hasFocus()) {
23044                     clearFocus();
23045                     if (mParent instanceof ViewGroup) {
23046                         ((ViewGroup) mParent).clearFocusedInCluster();
23047                     }
23048                 }
23049                 clearAccessibilityFocus();
23050             } else if (oldWidth <= 0 || oldHeight <= 0) {
23051                 if (mParent != null && canTakeFocus()) {
23052                     mParent.focusableViewAvailable(this);
23053                 }
23054             }
23055         }
23056         rebuildOutline();
23057     }
23058 
23059     /**
23060      * Finalize inflating a view from XML.  This is called as the last phase
23061      * of inflation, after all child views have been added.
23062      *
23063      * <p>Even if the subclass overrides onFinishInflate, they should always be
23064      * sure to call the super method, so that we get called.
23065      */
23066     @CallSuper
onFinishInflate()23067     protected void onFinishInflate() {
23068     }
23069 
23070     /**
23071      * Returns the resources associated with this view.
23072      *
23073      * @return Resources object.
23074      */
getResources()23075     public Resources getResources() {
23076         return mResources;
23077     }
23078 
23079     /**
23080      * Invalidates the specified Drawable.
23081      *
23082      * @param drawable the drawable to invalidate
23083      */
23084     @Override
invalidateDrawable(@onNull Drawable drawable)23085     public void invalidateDrawable(@NonNull Drawable drawable) {
23086         if (verifyDrawable(drawable)) {
23087             final Rect dirty = drawable.getDirtyBounds();
23088             final int scrollX = mScrollX;
23089             final int scrollY = mScrollY;
23090 
23091             invalidate(dirty.left + scrollX, dirty.top + scrollY,
23092                     dirty.right + scrollX, dirty.bottom + scrollY);
23093             rebuildOutline();
23094         }
23095     }
23096 
23097     /**
23098      * Schedules an action on a drawable to occur at a specified time.
23099      *
23100      * @param who the recipient of the action
23101      * @param what the action to run on the drawable
23102      * @param when the time at which the action must occur. Uses the
23103      *        {@link SystemClock#uptimeMillis} timebase.
23104      */
23105     @Override
scheduleDrawable(@onNull Drawable who, @NonNull Runnable what, long when)23106     public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
23107         if (verifyDrawable(who) && what != null) {
23108             final long delay = when - SystemClock.uptimeMillis();
23109             if (mAttachInfo != null) {
23110                 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
23111                         Choreographer.CALLBACK_ANIMATION, what, who,
23112                         Choreographer.subtractFrameDelay(delay));
23113             } else {
23114                 // Postpone the runnable until we know
23115                 // on which thread it needs to run.
23116                 getRunQueue().postDelayed(what, delay);
23117             }
23118         }
23119     }
23120 
23121     /**
23122      * Cancels a scheduled action on a drawable.
23123      *
23124      * @param who the recipient of the action
23125      * @param what the action to cancel
23126      */
23127     @Override
unscheduleDrawable(@onNull Drawable who, @NonNull Runnable what)23128     public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
23129         if (verifyDrawable(who) && what != null) {
23130             if (mAttachInfo != null) {
23131                 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
23132                         Choreographer.CALLBACK_ANIMATION, what, who);
23133             }
23134             getRunQueue().removeCallbacks(what);
23135         }
23136     }
23137 
23138     /**
23139      * Unschedule any events associated with the given Drawable.  This can be
23140      * used when selecting a new Drawable into a view, so that the previous
23141      * one is completely unscheduled.
23142      *
23143      * @param who The Drawable to unschedule.
23144      *
23145      * @see #drawableStateChanged
23146      */
unscheduleDrawable(Drawable who)23147     public void unscheduleDrawable(Drawable who) {
23148         if (mAttachInfo != null && who != null) {
23149             mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
23150                     Choreographer.CALLBACK_ANIMATION, null, who);
23151         }
23152     }
23153 
23154     /**
23155      * Resolve the Drawables depending on the layout direction. This is implicitly supposing
23156      * that the View directionality can and will be resolved before its Drawables.
23157      *
23158      * Will call {@link View#onResolveDrawables} when resolution is done.
23159      *
23160      * @hide
23161      */
resolveDrawables()23162     protected void resolveDrawables() {
23163         // Drawables resolution may need to happen before resolving the layout direction (which is
23164         // done only during the measure() call).
23165         // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
23166         // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
23167         // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
23168         // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
23169         // direction to be resolved as its resolved value will be the same as its raw value.
23170         if (!isLayoutDirectionResolved() &&
23171                 getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
23172             return;
23173         }
23174 
23175         final int layoutDirection = isLayoutDirectionResolved() ?
23176                 getLayoutDirection() : getRawLayoutDirection();
23177 
23178         if (mBackground != null) {
23179             mBackground.setLayoutDirection(layoutDirection);
23180         }
23181         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
23182             mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
23183         }
23184         if (mDefaultFocusHighlight != null) {
23185             mDefaultFocusHighlight.setLayoutDirection(layoutDirection);
23186         }
23187         mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
23188         onResolveDrawables(layoutDirection);
23189     }
23190 
areDrawablesResolved()23191     boolean areDrawablesResolved() {
23192         return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
23193     }
23194 
23195     /**
23196      * Called when layout direction has been resolved.
23197      *
23198      * The default implementation does nothing.
23199      *
23200      * @param layoutDirection The resolved layout direction.
23201      *
23202      * @see #LAYOUT_DIRECTION_LTR
23203      * @see #LAYOUT_DIRECTION_RTL
23204      *
23205      * @hide
23206      */
onResolveDrawables(@esolvedLayoutDir int layoutDirection)23207     public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
23208     }
23209 
23210     /**
23211      * @hide
23212      */
23213     @TestApi
resetResolvedDrawables()23214     protected void resetResolvedDrawables() {
23215         resetResolvedDrawablesInternal();
23216     }
23217 
resetResolvedDrawablesInternal()23218     void resetResolvedDrawablesInternal() {
23219         mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
23220     }
23221 
23222     /**
23223      * If your view subclass is displaying its own Drawable objects, it should
23224      * override this function and return true for any Drawable it is
23225      * displaying.  This allows animations for those drawables to be
23226      * scheduled.
23227      *
23228      * <p>Be sure to call through to the super class when overriding this
23229      * function.
23230      *
23231      * @param who The Drawable to verify.  Return true if it is one you are
23232      *            displaying, else return the result of calling through to the
23233      *            super class.
23234      *
23235      * @return boolean If true than the Drawable is being displayed in the
23236      *         view; else false and it is not allowed to animate.
23237      *
23238      * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
23239      * @see #drawableStateChanged()
23240      */
23241     @CallSuper
verifyDrawable(@onNull Drawable who)23242     protected boolean verifyDrawable(@NonNull Drawable who) {
23243         // Avoid verifying the scroll bar drawable so that we don't end up in
23244         // an invalidation loop. This effectively prevents the scroll bar
23245         // drawable from triggering invalidations and scheduling runnables.
23246         return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who)
23247                 || (mDefaultFocusHighlight == who);
23248     }
23249 
23250     /**
23251      * This function is called whenever the state of the view changes in such
23252      * a way that it impacts the state of drawables being shown.
23253      * <p>
23254      * If the View has a StateListAnimator, it will also be called to run necessary state
23255      * change animations.
23256      * <p>
23257      * Be sure to call through to the superclass when overriding this function.
23258      *
23259      * @see Drawable#setState(int[])
23260      */
23261     @CallSuper
drawableStateChanged()23262     protected void drawableStateChanged() {
23263         final int[] state = getDrawableState();
23264         boolean changed = false;
23265 
23266         final Drawable bg = mBackground;
23267         if (bg != null && bg.isStateful()) {
23268             changed |= bg.setState(state);
23269         }
23270 
23271         final Drawable hl = mDefaultFocusHighlight;
23272         if (hl != null && hl.isStateful()) {
23273             changed |= hl.setState(state);
23274         }
23275 
23276         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
23277         if (fg != null && fg.isStateful()) {
23278             changed |= fg.setState(state);
23279         }
23280 
23281         if (mScrollCache != null) {
23282             final Drawable scrollBar = mScrollCache.scrollBar;
23283             if (scrollBar != null && scrollBar.isStateful()) {
23284                 changed |= scrollBar.setState(state)
23285                         && mScrollCache.state != ScrollabilityCache.OFF;
23286             }
23287         }
23288 
23289         if (mStateListAnimator != null) {
23290             mStateListAnimator.setState(state);
23291         }
23292 
23293         if (changed) {
23294             invalidate();
23295         }
23296     }
23297 
23298     /**
23299      * This function is called whenever the view hotspot changes and needs to
23300      * be propagated to drawables or child views managed by the view.
23301      * <p>
23302      * Dispatching to child views is handled by
23303      * {@link #dispatchDrawableHotspotChanged(float, float)}.
23304      * <p>
23305      * Be sure to call through to the superclass when overriding this function.
23306      *
23307      * @param x hotspot x coordinate
23308      * @param y hotspot y coordinate
23309      */
23310     @CallSuper
drawableHotspotChanged(float x, float y)23311     public void drawableHotspotChanged(float x, float y) {
23312         if (mBackground != null) {
23313             mBackground.setHotspot(x, y);
23314         }
23315         if (mDefaultFocusHighlight != null) {
23316             mDefaultFocusHighlight.setHotspot(x, y);
23317         }
23318         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
23319             mForegroundInfo.mDrawable.setHotspot(x, y);
23320         }
23321 
23322         dispatchDrawableHotspotChanged(x, y);
23323     }
23324 
23325     /**
23326      * Dispatches drawableHotspotChanged to all of this View's children.
23327      *
23328      * @param x hotspot x coordinate
23329      * @param y hotspot y coordinate
23330      * @see #drawableHotspotChanged(float, float)
23331      */
dispatchDrawableHotspotChanged(float x, float y)23332     public void dispatchDrawableHotspotChanged(float x, float y) {
23333     }
23334 
23335     /**
23336      * Call this to force a view to update its drawable state. This will cause
23337      * drawableStateChanged to be called on this view. Views that are interested
23338      * in the new state should call getDrawableState.
23339      *
23340      * @see #drawableStateChanged
23341      * @see #getDrawableState
23342      */
refreshDrawableState()23343     public void refreshDrawableState() {
23344         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
23345         drawableStateChanged();
23346 
23347         ViewParent parent = mParent;
23348         if (parent != null) {
23349             parent.childDrawableStateChanged(this);
23350         }
23351     }
23352 
23353     /**
23354      * Create a default focus highlight if it doesn't exist.
23355      * @return a default focus highlight.
23356      */
getDefaultFocusHighlightDrawable()23357     private Drawable getDefaultFocusHighlightDrawable() {
23358         if (mDefaultFocusHighlightCache == null) {
23359             if (mContext != null) {
23360                 final int[] attrs = new int[] { android.R.attr.selectableItemBackground };
23361                 final TypedArray ta = mContext.obtainStyledAttributes(attrs);
23362                 mDefaultFocusHighlightCache = ta.getDrawable(0);
23363                 ta.recycle();
23364             }
23365         }
23366         return mDefaultFocusHighlightCache;
23367     }
23368 
23369     /**
23370      * Set the current default focus highlight.
23371      * @param highlight the highlight drawable, or {@code null} if it's no longer needed.
23372      */
setDefaultFocusHighlight(Drawable highlight)23373     private void setDefaultFocusHighlight(Drawable highlight) {
23374         mDefaultFocusHighlight = highlight;
23375         mDefaultFocusHighlightSizeChanged = true;
23376         if (highlight != null) {
23377             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
23378                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
23379             }
23380             highlight.setLayoutDirection(getLayoutDirection());
23381             if (highlight.isStateful()) {
23382                 highlight.setState(getDrawableState());
23383             }
23384             if (isAttachedToWindow()) {
23385                 highlight.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
23386             }
23387             // Set callback last, since the view may still be initializing.
23388             highlight.setCallback(this);
23389         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
23390                 && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
23391             mPrivateFlags |= PFLAG_SKIP_DRAW;
23392         }
23393         invalidate();
23394     }
23395 
23396     /**
23397      * Check whether we need to draw a default focus highlight when this view gets focused,
23398      * which requires:
23399      * <ul>
23400      *     <li>In both background and foreground, {@link android.R.attr#state_focused}
23401      *         is not defined.</li>
23402      *     <li>This view is not in touch mode.</li>
23403      *     <li>This view doesn't opt out for a default focus highlight, via
23404      *         {@link #setDefaultFocusHighlightEnabled(boolean)}.</li>
23405      *     <li>This view is attached to window.</li>
23406      * </ul>
23407      * @return {@code true} if a default focus highlight is needed.
23408      * @hide
23409      */
23410     @TestApi
isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground)23411     public boolean isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground) {
23412         final boolean lackFocusState = (background == null || !background.isStateful()
23413                 || !background.hasFocusStateSpecified())
23414                 && (foreground == null || !foreground.isStateful()
23415                 || !foreground.hasFocusStateSpecified());
23416         return !isInTouchMode() && getDefaultFocusHighlightEnabled() && lackFocusState
23417                 && isAttachedToWindow() && sUseDefaultFocusHighlight;
23418     }
23419 
23420     /**
23421      * When this view is focused, switches on/off the default focused highlight.
23422      * <p>
23423      * This always happens when this view is focused, and only at this moment the default focus
23424      * highlight can be visible.
23425      */
switchDefaultFocusHighlight()23426     private void switchDefaultFocusHighlight() {
23427         if (isFocused()) {
23428             final boolean needed = isDefaultFocusHighlightNeeded(mBackground,
23429                     mForegroundInfo == null ? null : mForegroundInfo.mDrawable);
23430             final boolean active = mDefaultFocusHighlight != null;
23431             if (needed && !active) {
23432                 setDefaultFocusHighlight(getDefaultFocusHighlightDrawable());
23433             } else if (!needed && active) {
23434                 // The highlight is no longer needed, so tear it down.
23435                 setDefaultFocusHighlight(null);
23436             }
23437         }
23438     }
23439 
23440     /**
23441      * Draw the default focus highlight onto the canvas if there is one and this view is focused.
23442      * @param canvas the canvas where we're drawing the highlight.
23443      */
drawDefaultFocusHighlight(Canvas canvas)23444     private void drawDefaultFocusHighlight(Canvas canvas) {
23445         if (mDefaultFocusHighlight != null && isFocused()) {
23446             if (mDefaultFocusHighlightSizeChanged) {
23447                 mDefaultFocusHighlightSizeChanged = false;
23448                 final int l = mScrollX;
23449                 final int r = l + mRight - mLeft;
23450                 final int t = mScrollY;
23451                 final int b = t + mBottom - mTop;
23452                 mDefaultFocusHighlight.setBounds(l, t, r, b);
23453             }
23454             mDefaultFocusHighlight.draw(canvas);
23455         }
23456     }
23457 
23458     /**
23459      * Return an array of resource IDs of the drawable states representing the
23460      * current state of the view.
23461      *
23462      * @return The current drawable state
23463      *
23464      * @see Drawable#setState(int[])
23465      * @see #drawableStateChanged()
23466      * @see #onCreateDrawableState(int)
23467      */
getDrawableState()23468     public final int[] getDrawableState() {
23469         if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
23470             return mDrawableState;
23471         } else {
23472             mDrawableState = onCreateDrawableState(0);
23473             mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
23474             return mDrawableState;
23475         }
23476     }
23477 
23478     /**
23479      * Generate the new {@link android.graphics.drawable.Drawable} state for
23480      * this view. This is called by the view
23481      * system when the cached Drawable state is determined to be invalid.  To
23482      * retrieve the current state, you should use {@link #getDrawableState}.
23483      *
23484      * @param extraSpace if non-zero, this is the number of extra entries you
23485      * would like in the returned array in which you can place your own
23486      * states.
23487      *
23488      * @return Returns an array holding the current {@link Drawable} state of
23489      * the view.
23490      *
23491      * @see #mergeDrawableStates(int[], int[])
23492      */
onCreateDrawableState(int extraSpace)23493     protected int[] onCreateDrawableState(int extraSpace) {
23494         if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
23495                 mParent instanceof View) {
23496             return ((View) mParent).onCreateDrawableState(extraSpace);
23497         }
23498 
23499         int[] drawableState;
23500 
23501         int privateFlags = mPrivateFlags;
23502 
23503         int viewStateIndex = 0;
23504         if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
23505         if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
23506         if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
23507         if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
23508         if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
23509         if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
23510         if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
23511                 ThreadedRenderer.isAvailable()) {
23512             // This is set if HW acceleration is requested, even if the current
23513             // process doesn't allow it.  This is just to allow app preview
23514             // windows to better match their app.
23515             viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
23516         }
23517         if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
23518 
23519         final int privateFlags2 = mPrivateFlags2;
23520         if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
23521             viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
23522         }
23523         if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
23524             viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
23525         }
23526 
23527         drawableState = StateSet.get(viewStateIndex);
23528 
23529         //noinspection ConstantIfStatement
23530         if (false) {
23531             Log.i("View", "drawableStateIndex=" + viewStateIndex);
23532             Log.i("View", toString()
23533                     + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
23534                     + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
23535                     + " fo=" + hasFocus()
23536                     + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
23537                     + " wf=" + hasWindowFocus()
23538                     + ": " + Arrays.toString(drawableState));
23539         }
23540 
23541         if (extraSpace == 0) {
23542             return drawableState;
23543         }
23544 
23545         final int[] fullState;
23546         if (drawableState != null) {
23547             fullState = new int[drawableState.length + extraSpace];
23548             System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
23549         } else {
23550             fullState = new int[extraSpace];
23551         }
23552 
23553         return fullState;
23554     }
23555 
23556     /**
23557      * Merge your own state values in <var>additionalState</var> into the base
23558      * state values <var>baseState</var> that were returned by
23559      * {@link #onCreateDrawableState(int)}.
23560      *
23561      * @param baseState The base state values returned by
23562      * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
23563      * own additional state values.
23564      *
23565      * @param additionalState The additional state values you would like
23566      * added to <var>baseState</var>; this array is not modified.
23567      *
23568      * @return As a convenience, the <var>baseState</var> array you originally
23569      * passed into the function is returned.
23570      *
23571      * @see #onCreateDrawableState(int)
23572      */
mergeDrawableStates(int[] baseState, int[] additionalState)23573     protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
23574         final int N = baseState.length;
23575         int i = N - 1;
23576         while (i >= 0 && baseState[i] == 0) {
23577             i--;
23578         }
23579         System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
23580         return baseState;
23581     }
23582 
23583     /**
23584      * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
23585      * on all Drawable objects associated with this view.
23586      * <p>
23587      * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
23588      * attached to this view.
23589      */
23590     @CallSuper
jumpDrawablesToCurrentState()23591     public void jumpDrawablesToCurrentState() {
23592         if (mBackground != null) {
23593             mBackground.jumpToCurrentState();
23594         }
23595         if (mStateListAnimator != null) {
23596             mStateListAnimator.jumpToCurrentState();
23597         }
23598         if (mDefaultFocusHighlight != null) {
23599             mDefaultFocusHighlight.jumpToCurrentState();
23600         }
23601         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
23602             mForegroundInfo.mDrawable.jumpToCurrentState();
23603         }
23604     }
23605 
23606     /**
23607      * Sets the background color for this view.
23608      * @param color the color of the background
23609      */
23610     @RemotableViewMethod
setBackgroundColor(@olorInt int color)23611     public void setBackgroundColor(@ColorInt int color) {
23612         if (mBackground instanceof ColorDrawable) {
23613             ((ColorDrawable) mBackground.mutate()).setColor(color);
23614             computeOpaqueFlags();
23615             mBackgroundResource = 0;
23616         } else {
23617             setBackground(new ColorDrawable(color));
23618         }
23619     }
23620 
23621     /**
23622      * Set the background to a given resource. The resource should refer to
23623      * a Drawable object or 0 to remove the background.
23624      * @param resid The identifier of the resource.
23625      *
23626      * @attr ref android.R.styleable#View_background
23627      */
23628     @RemotableViewMethod
setBackgroundResource(@rawableRes int resid)23629     public void setBackgroundResource(@DrawableRes int resid) {
23630         if (resid != 0 && resid == mBackgroundResource) {
23631             return;
23632         }
23633 
23634         Drawable d = null;
23635         if (resid != 0) {
23636             d = mContext.getDrawable(resid);
23637         }
23638         setBackground(d);
23639 
23640         mBackgroundResource = resid;
23641     }
23642 
23643     /**
23644      * Set the background to a given Drawable, or remove the background. If the
23645      * background has padding, this View's padding is set to the background's
23646      * padding. However, when a background is removed, this View's padding isn't
23647      * touched. If setting the padding is desired, please use
23648      * {@link #setPadding(int, int, int, int)}.
23649      *
23650      * @param background The Drawable to use as the background, or null to remove the
23651      *        background
23652      */
setBackground(Drawable background)23653     public void setBackground(Drawable background) {
23654         //noinspection deprecation
23655         setBackgroundDrawable(background);
23656     }
23657 
23658     /**
23659      * @deprecated use {@link #setBackground(Drawable)} instead
23660      */
23661     @Deprecated
setBackgroundDrawable(Drawable background)23662     public void setBackgroundDrawable(Drawable background) {
23663         computeOpaqueFlags();
23664 
23665         if (background == mBackground) {
23666             return;
23667         }
23668 
23669         boolean requestLayout = false;
23670 
23671         mBackgroundResource = 0;
23672 
23673         /*
23674          * Regardless of whether we're setting a new background or not, we want
23675          * to clear the previous drawable. setVisible first while we still have the callback set.
23676          */
23677         if (mBackground != null) {
23678             if (isAttachedToWindow()) {
23679                 mBackground.setVisible(false, false);
23680             }
23681             mBackground.setCallback(null);
23682             unscheduleDrawable(mBackground);
23683         }
23684 
23685         if (background != null) {
23686             Rect padding = sThreadLocal.get();
23687             if (padding == null) {
23688                 padding = new Rect();
23689                 sThreadLocal.set(padding);
23690             }
23691             resetResolvedDrawablesInternal();
23692             background.setLayoutDirection(getLayoutDirection());
23693             if (background.getPadding(padding)) {
23694                 resetResolvedPaddingInternal();
23695                 switch (background.getLayoutDirection()) {
23696                     case LAYOUT_DIRECTION_RTL:
23697                         mUserPaddingLeftInitial = padding.right;
23698                         mUserPaddingRightInitial = padding.left;
23699                         internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
23700                         break;
23701                     case LAYOUT_DIRECTION_LTR:
23702                     default:
23703                         mUserPaddingLeftInitial = padding.left;
23704                         mUserPaddingRightInitial = padding.right;
23705                         internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
23706                 }
23707                 mLeftPaddingDefined = false;
23708                 mRightPaddingDefined = false;
23709             }
23710 
23711             // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
23712             // if it has a different minimum size, we should layout again
23713             if (mBackground == null
23714                     || mBackground.getMinimumHeight() != background.getMinimumHeight()
23715                     || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
23716                 requestLayout = true;
23717             }
23718 
23719             // Set mBackground before we set this as the callback and start making other
23720             // background drawable state change calls. In particular, the setVisible call below
23721             // can result in drawables attempting to start animations or otherwise invalidate,
23722             // which requires the view set as the callback (us) to recognize the drawable as
23723             // belonging to it as per verifyDrawable.
23724             mBackground = background;
23725             if (background.isStateful()) {
23726                 background.setState(getDrawableState());
23727             }
23728             if (isAttachedToWindow()) {
23729                 background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
23730             }
23731 
23732             applyBackgroundTint();
23733 
23734             // Set callback last, since the view may still be initializing.
23735             background.setCallback(this);
23736 
23737             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
23738                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
23739                 requestLayout = true;
23740             }
23741         } else {
23742             /* Remove the background */
23743             mBackground = null;
23744             if ((mViewFlags & WILL_NOT_DRAW) != 0
23745                     && (mDefaultFocusHighlight == null)
23746                     && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
23747                 mPrivateFlags |= PFLAG_SKIP_DRAW;
23748             }
23749 
23750             /*
23751              * When the background is set, we try to apply its padding to this
23752              * View. When the background is removed, we don't touch this View's
23753              * padding. This is noted in the Javadocs. Hence, we don't need to
23754              * requestLayout(), the invalidate() below is sufficient.
23755              */
23756 
23757             // The old background's minimum size could have affected this
23758             // View's layout, so let's requestLayout
23759             requestLayout = true;
23760         }
23761 
23762         computeOpaqueFlags();
23763 
23764         if (requestLayout) {
23765             requestLayout();
23766         }
23767 
23768         mBackgroundSizeChanged = true;
23769         invalidate(true);
23770         invalidateOutline();
23771     }
23772 
23773     /**
23774      * Gets the background drawable
23775      *
23776      * @return The drawable used as the background for this view, if any.
23777      *
23778      * @see #setBackground(Drawable)
23779      *
23780      * @attr ref android.R.styleable#View_background
23781      */
23782     @InspectableProperty
getBackground()23783     public Drawable getBackground() {
23784         return mBackground;
23785     }
23786 
23787     /**
23788      * Applies a tint to the background drawable. Does not modify the current tint
23789      * mode, which is {@link BlendMode#SRC_IN} by default.
23790      * <p>
23791      * Subsequent calls to {@link #setBackground(Drawable)} will automatically
23792      * mutate the drawable and apply the specified tint and tint mode using
23793      * {@link Drawable#setTintList(ColorStateList)}.
23794      *
23795      * @param tint the tint to apply, may be {@code null} to clear tint
23796      *
23797      * @attr ref android.R.styleable#View_backgroundTint
23798      * @see #getBackgroundTintList()
23799      * @see Drawable#setTintList(ColorStateList)
23800      */
setBackgroundTintList(@ullable ColorStateList tint)23801     public void setBackgroundTintList(@Nullable ColorStateList tint) {
23802         if (mBackgroundTint == null) {
23803             mBackgroundTint = new TintInfo();
23804         }
23805         mBackgroundTint.mTintList = tint;
23806         mBackgroundTint.mHasTintList = true;
23807 
23808         applyBackgroundTint();
23809     }
23810 
23811     /**
23812      * Return the tint applied to the background drawable, if specified.
23813      *
23814      * @return the tint applied to the background drawable
23815      * @attr ref android.R.styleable#View_backgroundTint
23816      * @see #setBackgroundTintList(ColorStateList)
23817      */
23818     @InspectableProperty(name = "backgroundTint")
23819     @Nullable
getBackgroundTintList()23820     public ColorStateList getBackgroundTintList() {
23821         return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
23822     }
23823 
23824     /**
23825      * Specifies the blending mode used to apply the tint specified by
23826      * {@link #setBackgroundTintList(ColorStateList)}} to the background
23827      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
23828      *
23829      * @param tintMode the blending mode used to apply the tint, may be
23830      *                 {@code null} to clear tint
23831      * @attr ref android.R.styleable#View_backgroundTintMode
23832      * @see #getBackgroundTintMode()
23833      * @see Drawable#setTintMode(PorterDuff.Mode)
23834      */
setBackgroundTintMode(@ullable PorterDuff.Mode tintMode)23835     public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
23836         BlendMode mode = null;
23837         if (tintMode != null) {
23838             mode = BlendMode.fromValue(tintMode.nativeInt);
23839         }
23840 
23841         setBackgroundTintBlendMode(mode);
23842     }
23843 
23844     /**
23845      * Specifies the blending mode used to apply the tint specified by
23846      * {@link #setBackgroundTintList(ColorStateList)}} to the background
23847      * drawable. The default mode is {@link BlendMode#SRC_IN}.
23848      *
23849      * @param blendMode the blending mode used to apply the tint, may be
23850      *                 {@code null} to clear tint
23851      * @attr ref android.R.styleable#View_backgroundTintMode
23852      * @see #getBackgroundTintMode()
23853      * @see Drawable#setTintBlendMode(BlendMode)
23854      */
setBackgroundTintBlendMode(@ullable BlendMode blendMode)23855     public void setBackgroundTintBlendMode(@Nullable BlendMode blendMode) {
23856         if (mBackgroundTint == null) {
23857             mBackgroundTint = new TintInfo();
23858         }
23859 
23860         mBackgroundTint.mBlendMode = blendMode;
23861         mBackgroundTint.mHasTintMode = true;
23862 
23863         applyBackgroundTint();
23864     }
23865 
23866     /**
23867      * Return the blending mode used to apply the tint to the background
23868      * drawable, if specified.
23869      *
23870      * @return the blending mode used to apply the tint to the background
23871      *         drawable
23872      * @attr ref android.R.styleable#View_backgroundTintMode
23873      * @see #setBackgroundTintBlendMode(BlendMode)
23874      *
23875      */
23876     @Nullable
23877     @InspectableProperty
getBackgroundTintMode()23878     public PorterDuff.Mode getBackgroundTintMode() {
23879         PorterDuff.Mode porterDuffMode;
23880         if (mBackgroundTint != null && mBackgroundTint.mBlendMode != null) {
23881             porterDuffMode = BlendMode.blendModeToPorterDuffMode(mBackgroundTint.mBlendMode);
23882         } else {
23883             porterDuffMode = null;
23884         }
23885         return porterDuffMode;
23886     }
23887 
23888     /**
23889      * Return the blending mode used to apply the tint to the background
23890      * drawable, if specified.
23891      *
23892      * @return the blending mode used to apply the tint to the background
23893      *         drawable, null if no blend has previously been configured
23894      * @attr ref android.R.styleable#View_backgroundTintMode
23895      * @see #setBackgroundTintBlendMode(BlendMode)
23896      */
getBackgroundTintBlendMode()23897     public @Nullable BlendMode getBackgroundTintBlendMode() {
23898         return mBackgroundTint != null ? mBackgroundTint.mBlendMode : null;
23899     }
23900 
applyBackgroundTint()23901     private void applyBackgroundTint() {
23902         if (mBackground != null && mBackgroundTint != null) {
23903             final TintInfo tintInfo = mBackgroundTint;
23904             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
23905                 mBackground = mBackground.mutate();
23906 
23907                 if (tintInfo.mHasTintList) {
23908                     mBackground.setTintList(tintInfo.mTintList);
23909                 }
23910 
23911                 if (tintInfo.mHasTintMode) {
23912                     mBackground.setTintBlendMode(tintInfo.mBlendMode);
23913                 }
23914 
23915                 // The drawable (or one of its children) may not have been
23916                 // stateful before applying the tint, so let's try again.
23917                 if (mBackground.isStateful()) {
23918                     mBackground.setState(getDrawableState());
23919                 }
23920             }
23921         }
23922     }
23923 
23924     /**
23925      * Returns the drawable used as the foreground of this View. The
23926      * foreground drawable, if non-null, is always drawn on top of the view's content.
23927      *
23928      * @return a Drawable or null if no foreground was set
23929      *
23930      * @see #onDrawForeground(Canvas)
23931      */
23932     @InspectableProperty
getForeground()23933     public Drawable getForeground() {
23934         return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
23935     }
23936 
23937     /**
23938      * Supply a Drawable that is to be rendered on top of all of the content in the view.
23939      *
23940      * @param foreground the Drawable to be drawn on top of the children
23941      *
23942      * @attr ref android.R.styleable#View_foreground
23943      */
setForeground(Drawable foreground)23944     public void setForeground(Drawable foreground) {
23945         if (mForegroundInfo == null) {
23946             if (foreground == null) {
23947                 // Nothing to do.
23948                 return;
23949             }
23950             mForegroundInfo = new ForegroundInfo();
23951         }
23952 
23953         if (foreground == mForegroundInfo.mDrawable) {
23954             // Nothing to do
23955             return;
23956         }
23957 
23958         if (mForegroundInfo.mDrawable != null) {
23959             if (isAttachedToWindow()) {
23960                 mForegroundInfo.mDrawable.setVisible(false, false);
23961             }
23962             mForegroundInfo.mDrawable.setCallback(null);
23963             unscheduleDrawable(mForegroundInfo.mDrawable);
23964         }
23965 
23966         mForegroundInfo.mDrawable = foreground;
23967         mForegroundInfo.mBoundsChanged = true;
23968         if (foreground != null) {
23969             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
23970                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
23971             }
23972             foreground.setLayoutDirection(getLayoutDirection());
23973             if (foreground.isStateful()) {
23974                 foreground.setState(getDrawableState());
23975             }
23976             applyForegroundTint();
23977             if (isAttachedToWindow()) {
23978                 foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
23979             }
23980             // Set callback last, since the view may still be initializing.
23981             foreground.setCallback(this);
23982         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
23983                 && (mDefaultFocusHighlight == null)) {
23984             mPrivateFlags |= PFLAG_SKIP_DRAW;
23985         }
23986         requestLayout();
23987         invalidate();
23988     }
23989 
23990     /**
23991      * Magic bit used to support features of framework-internal window decor implementation details.
23992      * This used to live exclusively in FrameLayout.
23993      *
23994      * @return true if the foreground should draw inside the padding region or false
23995      *         if it should draw inset by the view's padding
23996      * @hide internal use only; only used by FrameLayout and internal screen layouts.
23997      */
isForegroundInsidePadding()23998     public boolean isForegroundInsidePadding() {
23999         return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
24000     }
24001 
24002     /**
24003      * Describes how the foreground is positioned.
24004      *
24005      * @return foreground gravity.
24006      *
24007      * @see #setForegroundGravity(int)
24008      *
24009      * @attr ref android.R.styleable#View_foregroundGravity
24010      */
24011     @InspectableProperty(valueType = InspectableProperty.ValueType.GRAVITY)
getForegroundGravity()24012     public int getForegroundGravity() {
24013         return mForegroundInfo != null ? mForegroundInfo.mGravity
24014                 : Gravity.START | Gravity.TOP;
24015     }
24016 
24017     /**
24018      * Describes how the foreground is positioned. Defaults to START and TOP.
24019      *
24020      * @param gravity see {@link android.view.Gravity}
24021      *
24022      * @see #getForegroundGravity()
24023      *
24024      * @attr ref android.R.styleable#View_foregroundGravity
24025      */
setForegroundGravity(int gravity)24026     public void setForegroundGravity(int gravity) {
24027         if (mForegroundInfo == null) {
24028             mForegroundInfo = new ForegroundInfo();
24029         }
24030 
24031         if (mForegroundInfo.mGravity != gravity) {
24032             if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
24033                 gravity |= Gravity.START;
24034             }
24035 
24036             if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
24037                 gravity |= Gravity.TOP;
24038             }
24039 
24040             mForegroundInfo.mGravity = gravity;
24041             requestLayout();
24042         }
24043     }
24044 
24045     /**
24046      * Applies a tint to the foreground drawable. Does not modify the current tint
24047      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
24048      * <p>
24049      * Subsequent calls to {@link #setForeground(Drawable)} will automatically
24050      * mutate the drawable and apply the specified tint and tint mode using
24051      * {@link Drawable#setTintList(ColorStateList)}.
24052      *
24053      * @param tint the tint to apply, may be {@code null} to clear tint
24054      *
24055      * @attr ref android.R.styleable#View_foregroundTint
24056      * @see #getForegroundTintList()
24057      * @see Drawable#setTintList(ColorStateList)
24058      */
setForegroundTintList(@ullable ColorStateList tint)24059     public void setForegroundTintList(@Nullable ColorStateList tint) {
24060         if (mForegroundInfo == null) {
24061             mForegroundInfo = new ForegroundInfo();
24062         }
24063         if (mForegroundInfo.mTintInfo == null) {
24064             mForegroundInfo.mTintInfo = new TintInfo();
24065         }
24066         mForegroundInfo.mTintInfo.mTintList = tint;
24067         mForegroundInfo.mTintInfo.mHasTintList = true;
24068 
24069         applyForegroundTint();
24070     }
24071 
24072     /**
24073      * Return the tint applied to the foreground drawable, if specified.
24074      *
24075      * @return the tint applied to the foreground drawable
24076      * @attr ref android.R.styleable#View_foregroundTint
24077      * @see #setForegroundTintList(ColorStateList)
24078      */
24079     @InspectableProperty(name = "foregroundTint")
24080     @Nullable
getForegroundTintList()24081     public ColorStateList getForegroundTintList() {
24082         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
24083                 ? mForegroundInfo.mTintInfo.mTintList : null;
24084     }
24085 
24086     /**
24087      * Specifies the blending mode used to apply the tint specified by
24088      * {@link #setForegroundTintList(ColorStateList)}} to the background
24089      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
24090      *
24091      * @param tintMode the blending mode used to apply the tint, may be
24092      *                 {@code null} to clear tint
24093      * @attr ref android.R.styleable#View_foregroundTintMode
24094      * @see #getForegroundTintMode()
24095      * @see Drawable#setTintMode(PorterDuff.Mode)
24096      *
24097      */
setForegroundTintMode(@ullable PorterDuff.Mode tintMode)24098     public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
24099         BlendMode mode = null;
24100         if (tintMode != null) {
24101             mode = BlendMode.fromValue(tintMode.nativeInt);
24102         }
24103         setForegroundTintBlendMode(mode);
24104     }
24105 
24106     /**
24107      * Specifies the blending mode used to apply the tint specified by
24108      * {@link #setForegroundTintList(ColorStateList)}} to the background
24109      * drawable. The default mode is {@link BlendMode#SRC_IN}.
24110      *
24111      * @param blendMode the blending mode used to apply the tint, may be
24112      *                 {@code null} to clear tint
24113      * @attr ref android.R.styleable#View_foregroundTintMode
24114      * @see #getForegroundTintMode()
24115      * @see Drawable#setTintBlendMode(BlendMode)
24116      */
setForegroundTintBlendMode(@ullable BlendMode blendMode)24117     public void setForegroundTintBlendMode(@Nullable BlendMode blendMode) {
24118         if (mForegroundInfo == null) {
24119             mForegroundInfo = new ForegroundInfo();
24120         }
24121         if (mForegroundInfo.mTintInfo == null) {
24122             mForegroundInfo.mTintInfo = new TintInfo();
24123         }
24124         mForegroundInfo.mTintInfo.mBlendMode = blendMode;
24125         mForegroundInfo.mTintInfo.mHasTintMode = true;
24126 
24127         applyForegroundTint();
24128     }
24129 
24130     /**
24131      * Return the blending mode used to apply the tint to the foreground
24132      * drawable, if specified.
24133      *
24134      * @return the blending mode used to apply the tint to the foreground
24135      *         drawable
24136      * @attr ref android.R.styleable#View_foregroundTintMode
24137      * @see #setForegroundTintMode(PorterDuff.Mode)
24138      */
24139     @InspectableProperty
24140     @Nullable
getForegroundTintMode()24141     public PorterDuff.Mode getForegroundTintMode() {
24142         BlendMode blendMode = mForegroundInfo != null && mForegroundInfo.mTintInfo != null
24143                 ? mForegroundInfo.mTintInfo.mBlendMode : null;
24144         if (blendMode != null) {
24145             return BlendMode.blendModeToPorterDuffMode(blendMode);
24146         } else {
24147             return null;
24148         }
24149     }
24150 
24151     /**
24152      * Return the blending mode used to apply the tint to the foreground
24153      * drawable, if specified.
24154      *
24155      * @return the blending mode used to apply the tint to the foreground
24156      *         drawable
24157      * @attr ref android.R.styleable#View_foregroundTintMode
24158      * @see #setForegroundTintBlendMode(BlendMode)
24159      *
24160      */
getForegroundTintBlendMode()24161     public @Nullable BlendMode getForegroundTintBlendMode() {
24162         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
24163                 ? mForegroundInfo.mTintInfo.mBlendMode : null;
24164     }
24165 
applyForegroundTint()24166     private void applyForegroundTint() {
24167         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
24168                 && mForegroundInfo.mTintInfo != null) {
24169             final TintInfo tintInfo = mForegroundInfo.mTintInfo;
24170             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
24171                 mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
24172 
24173                 if (tintInfo.mHasTintList) {
24174                     mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
24175                 }
24176 
24177                 if (tintInfo.mHasTintMode) {
24178                     mForegroundInfo.mDrawable.setTintBlendMode(tintInfo.mBlendMode);
24179                 }
24180 
24181                 // The drawable (or one of its children) may not have been
24182                 // stateful before applying the tint, so let's try again.
24183                 if (mForegroundInfo.mDrawable.isStateful()) {
24184                     mForegroundInfo.mDrawable.setState(getDrawableState());
24185                 }
24186             }
24187         }
24188     }
24189 
24190     /**
24191      * Get the drawable to be overlayed when a view is autofilled
24192      *
24193      * @return The drawable
24194      *
24195      * @throws IllegalStateException if the drawable could not be found.
24196      */
getAutofilledDrawable()24197     @Nullable private Drawable getAutofilledDrawable() {
24198         if (mAttachInfo == null) {
24199             return null;
24200         }
24201         // Lazily load the isAutofilled drawable.
24202         if (mAttachInfo.mAutofilledDrawable == null) {
24203             Context rootContext = getRootView().getContext();
24204             TypedArray a = rootContext.getTheme().obtainStyledAttributes(AUTOFILL_HIGHLIGHT_ATTR);
24205             int attributeResourceId = a.getResourceId(0, 0);
24206             mAttachInfo.mAutofilledDrawable = rootContext.getDrawable(attributeResourceId);
24207             a.recycle();
24208         }
24209 
24210         return mAttachInfo.mAutofilledDrawable;
24211     }
24212 
24213     /**
24214      * Draw {@link View#isAutofilled()} highlight over view if the view is autofilled, unless
24215      * {@link #PFLAG4_AUTOFILL_HIDE_HIGHLIGHT} is enabled.
24216      *
24217      * @param canvas The canvas to draw on
24218      */
drawAutofilledHighlight(@onNull Canvas canvas)24219     private void drawAutofilledHighlight(@NonNull Canvas canvas) {
24220         if (isAutofilled() && !hideAutofillHighlight()) {
24221             Drawable autofilledHighlight = getAutofilledDrawable();
24222 
24223             if (autofilledHighlight != null) {
24224                 autofilledHighlight.setBounds(0, 0, getWidth(), getHeight());
24225                 autofilledHighlight.draw(canvas);
24226             }
24227         }
24228     }
24229 
24230     /**
24231      * Draw any foreground content for this view.
24232      *
24233      * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
24234      * drawable or other view-specific decorations. The foreground is drawn on top of the
24235      * primary view content.</p>
24236      *
24237      * @param canvas canvas to draw into
24238      */
onDrawForeground(Canvas canvas)24239     public void onDrawForeground(Canvas canvas) {
24240         onDrawScrollIndicators(canvas);
24241         onDrawScrollBars(canvas);
24242 
24243         final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
24244         if (foreground != null) {
24245             if (mForegroundInfo.mBoundsChanged) {
24246                 mForegroundInfo.mBoundsChanged = false;
24247                 final Rect selfBounds = mForegroundInfo.mSelfBounds;
24248                 final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
24249 
24250                 if (mForegroundInfo.mInsidePadding) {
24251                     selfBounds.set(0, 0, getWidth(), getHeight());
24252                 } else {
24253                     selfBounds.set(getPaddingLeft(), getPaddingTop(),
24254                             getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
24255                 }
24256 
24257                 final int ld = getLayoutDirection();
24258                 Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
24259                         foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
24260                 foreground.setBounds(overlayBounds);
24261             }
24262 
24263             foreground.draw(canvas);
24264         }
24265     }
24266 
24267     /**
24268      * Sets the padding. The view may add on the space required to display
24269      * the scrollbars, depending on the style and visibility of the scrollbars.
24270      * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
24271      * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
24272      * from the values set in this call.
24273      *
24274      * @attr ref android.R.styleable#View_padding
24275      * @attr ref android.R.styleable#View_paddingBottom
24276      * @attr ref android.R.styleable#View_paddingLeft
24277      * @attr ref android.R.styleable#View_paddingRight
24278      * @attr ref android.R.styleable#View_paddingTop
24279      * @param left the left padding in pixels
24280      * @param top the top padding in pixels
24281      * @param right the right padding in pixels
24282      * @param bottom the bottom padding in pixels
24283      */
setPadding(int left, int top, int right, int bottom)24284     public void setPadding(int left, int top, int right, int bottom) {
24285         resetResolvedPaddingInternal();
24286 
24287         mUserPaddingStart = UNDEFINED_PADDING;
24288         mUserPaddingEnd = UNDEFINED_PADDING;
24289 
24290         mUserPaddingLeftInitial = left;
24291         mUserPaddingRightInitial = right;
24292 
24293         mLeftPaddingDefined = true;
24294         mRightPaddingDefined = true;
24295 
24296         internalSetPadding(left, top, right, bottom);
24297     }
24298 
24299     /**
24300      * @hide
24301      */
24302     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768420)
internalSetPadding(int left, int top, int right, int bottom)24303     protected void internalSetPadding(int left, int top, int right, int bottom) {
24304         mUserPaddingLeft = left;
24305         mUserPaddingRight = right;
24306         mUserPaddingBottom = bottom;
24307 
24308         final int viewFlags = mViewFlags;
24309         boolean changed = false;
24310 
24311         // Common case is there are no scroll bars.
24312         if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
24313             if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
24314                 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
24315                         ? 0 : getVerticalScrollbarWidth();
24316                 switch (mVerticalScrollbarPosition) {
24317                     case SCROLLBAR_POSITION_DEFAULT:
24318                         if (isLayoutRtl()) {
24319                             left += offset;
24320                         } else {
24321                             right += offset;
24322                         }
24323                         break;
24324                     case SCROLLBAR_POSITION_RIGHT:
24325                         right += offset;
24326                         break;
24327                     case SCROLLBAR_POSITION_LEFT:
24328                         left += offset;
24329                         break;
24330                 }
24331             }
24332             if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
24333                 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
24334                         ? 0 : getHorizontalScrollbarHeight();
24335             }
24336         }
24337 
24338         if (mPaddingLeft != left) {
24339             changed = true;
24340             mPaddingLeft = left;
24341         }
24342         if (mPaddingTop != top) {
24343             changed = true;
24344             mPaddingTop = top;
24345         }
24346         if (mPaddingRight != right) {
24347             changed = true;
24348             mPaddingRight = right;
24349         }
24350         if (mPaddingBottom != bottom) {
24351             changed = true;
24352             mPaddingBottom = bottom;
24353         }
24354 
24355         if (changed) {
24356             requestLayout();
24357             invalidateOutline();
24358         }
24359     }
24360 
24361     /**
24362      * Sets the relative padding. The view may add on the space required to display
24363      * the scrollbars, depending on the style and visibility of the scrollbars.
24364      * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
24365      * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
24366      * from the values set in this call.
24367      *
24368      * @attr ref android.R.styleable#View_padding
24369      * @attr ref android.R.styleable#View_paddingBottom
24370      * @attr ref android.R.styleable#View_paddingStart
24371      * @attr ref android.R.styleable#View_paddingEnd
24372      * @attr ref android.R.styleable#View_paddingTop
24373      * @param start the start padding in pixels
24374      * @param top the top padding in pixels
24375      * @param end the end padding in pixels
24376      * @param bottom the bottom padding in pixels
24377      */
setPaddingRelative(int start, int top, int end, int bottom)24378     public void setPaddingRelative(int start, int top, int end, int bottom) {
24379         resetResolvedPaddingInternal();
24380 
24381         mUserPaddingStart = start;
24382         mUserPaddingEnd = end;
24383         mLeftPaddingDefined = true;
24384         mRightPaddingDefined = true;
24385 
24386         switch(getLayoutDirection()) {
24387             case LAYOUT_DIRECTION_RTL:
24388                 mUserPaddingLeftInitial = end;
24389                 mUserPaddingRightInitial = start;
24390                 internalSetPadding(end, top, start, bottom);
24391                 break;
24392             case LAYOUT_DIRECTION_LTR:
24393             default:
24394                 mUserPaddingLeftInitial = start;
24395                 mUserPaddingRightInitial = end;
24396                 internalSetPadding(start, top, end, bottom);
24397         }
24398     }
24399 
24400     /**
24401      * A {@link View} can be inflated from an XML layout. For such Views this method returns the
24402      * resource ID of the source layout.
24403      *
24404      * @return The layout resource id if this view was inflated from XML, otherwise
24405      * {@link Resources#ID_NULL}.
24406      */
24407     @LayoutRes
getSourceLayoutResId()24408     public int getSourceLayoutResId() {
24409         return mSourceLayoutId;
24410     }
24411 
24412     /**
24413      * Returns the top padding of this view.
24414      *
24415      * @return the top padding in pixels
24416      */
24417     @InspectableProperty
getPaddingTop()24418     public int getPaddingTop() {
24419         return mPaddingTop;
24420     }
24421 
24422     /**
24423      * Returns the bottom padding of this view. If there are inset and enabled
24424      * scrollbars, this value may include the space required to display the
24425      * scrollbars as well.
24426      *
24427      * @return the bottom padding in pixels
24428      */
24429     @InspectableProperty
getPaddingBottom()24430     public int getPaddingBottom() {
24431         return mPaddingBottom;
24432     }
24433 
24434     /**
24435      * Returns the left padding of this view. If there are inset and enabled
24436      * scrollbars, this value may include the space required to display the
24437      * scrollbars as well.
24438      *
24439      * @return the left padding in pixels
24440      */
24441     @InspectableProperty
getPaddingLeft()24442     public int getPaddingLeft() {
24443         if (!isPaddingResolved()) {
24444             resolvePadding();
24445         }
24446         return mPaddingLeft;
24447     }
24448 
24449     /**
24450      * Returns the start padding of this view depending on its resolved layout direction.
24451      * If there are inset and enabled scrollbars, this value may include the space
24452      * required to display the scrollbars as well.
24453      *
24454      * @return the start padding in pixels
24455      */
getPaddingStart()24456     public int getPaddingStart() {
24457         if (!isPaddingResolved()) {
24458             resolvePadding();
24459         }
24460         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
24461                 mPaddingRight : mPaddingLeft;
24462     }
24463 
24464     /**
24465      * Returns the right padding of this view. If there are inset and enabled
24466      * scrollbars, this value may include the space required to display the
24467      * scrollbars as well.
24468      *
24469      * @return the right padding in pixels
24470      */
24471     @InspectableProperty
getPaddingRight()24472     public int getPaddingRight() {
24473         if (!isPaddingResolved()) {
24474             resolvePadding();
24475         }
24476         return mPaddingRight;
24477     }
24478 
24479     /**
24480      * Returns the end padding of this view depending on its resolved layout direction.
24481      * If there are inset and enabled scrollbars, this value may include the space
24482      * required to display the scrollbars as well.
24483      *
24484      * @return the end padding in pixels
24485      */
getPaddingEnd()24486     public int getPaddingEnd() {
24487         if (!isPaddingResolved()) {
24488             resolvePadding();
24489         }
24490         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
24491                 mPaddingLeft : mPaddingRight;
24492     }
24493 
24494     /**
24495      * Return if the padding has been set through relative values
24496      * {@link #setPaddingRelative(int, int, int, int)} or through
24497      * @attr ref android.R.styleable#View_paddingStart or
24498      * @attr ref android.R.styleable#View_paddingEnd
24499      *
24500      * @return true if the padding is relative or false if it is not.
24501      */
isPaddingRelative()24502     public boolean isPaddingRelative() {
24503         return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
24504     }
24505 
computeOpticalInsets()24506     Insets computeOpticalInsets() {
24507         return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
24508     }
24509 
24510     /**
24511      * @hide
24512      */
24513     @UnsupportedAppUsage
resetPaddingToInitialValues()24514     public void resetPaddingToInitialValues() {
24515         if (isRtlCompatibilityMode()) {
24516             mPaddingLeft = mUserPaddingLeftInitial;
24517             mPaddingRight = mUserPaddingRightInitial;
24518             return;
24519         }
24520         if (isLayoutRtl()) {
24521             mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
24522             mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
24523         } else {
24524             mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
24525             mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
24526         }
24527     }
24528 
24529     /**
24530      * @hide
24531      */
getOpticalInsets()24532     public Insets getOpticalInsets() {
24533         if (mLayoutInsets == null) {
24534             mLayoutInsets = computeOpticalInsets();
24535         }
24536         return mLayoutInsets;
24537     }
24538 
24539     /**
24540      * Set this view's optical insets.
24541      *
24542      * <p>This method should be treated similarly to setMeasuredDimension and not as a general
24543      * property. Views that compute their own optical insets should call it as part of measurement.
24544      * This method does not request layout. If you are setting optical insets outside of
24545      * measure/layout itself you will want to call requestLayout() yourself.
24546      * </p>
24547      * @hide
24548      */
setOpticalInsets(Insets insets)24549     public void setOpticalInsets(Insets insets) {
24550         mLayoutInsets = insets;
24551     }
24552 
24553     /**
24554      * Changes the selection state of this view. A view can be selected or not.
24555      * Note that selection is not the same as focus. Views are typically
24556      * selected in the context of an AdapterView like ListView or GridView;
24557      * the selected view is the view that is highlighted.
24558      *
24559      * @param selected true if the view must be selected, false otherwise
24560      */
setSelected(boolean selected)24561     public void setSelected(boolean selected) {
24562         //noinspection DoubleNegation
24563         if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
24564             mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
24565             if (!selected) resetPressedState();
24566             invalidate(true);
24567             refreshDrawableState();
24568             dispatchSetSelected(selected);
24569             if (selected) {
24570                 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
24571             } else {
24572                 notifyViewAccessibilityStateChangedIfNeeded(
24573                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
24574             }
24575         }
24576     }
24577 
24578     /**
24579      * Dispatch setSelected to all of this View's children.
24580      *
24581      * @see #setSelected(boolean)
24582      *
24583      * @param selected The new selected state
24584      */
dispatchSetSelected(boolean selected)24585     protected void dispatchSetSelected(boolean selected) {
24586     }
24587 
24588     /**
24589      * Indicates the selection state of this view.
24590      *
24591      * @return true if the view is selected, false otherwise
24592      */
24593     @ViewDebug.ExportedProperty
24594     @InspectableProperty(hasAttributeId = false)
isSelected()24595     public boolean isSelected() {
24596         return (mPrivateFlags & PFLAG_SELECTED) != 0;
24597     }
24598 
24599     /**
24600      * Changes the activated state of this view. A view can be activated or not.
24601      * Note that activation is not the same as selection.  Selection is
24602      * a transient property, representing the view (hierarchy) the user is
24603      * currently interacting with.  Activation is a longer-term state that the
24604      * user can move views in and out of.  For example, in a list view with
24605      * single or multiple selection enabled, the views in the current selection
24606      * set are activated.  (Um, yeah, we are deeply sorry about the terminology
24607      * here.)  The activated state is propagated down to children of the view it
24608      * is set on.
24609      *
24610      * @param activated true if the view must be activated, false otherwise
24611      */
setActivated(boolean activated)24612     public void setActivated(boolean activated) {
24613         //noinspection DoubleNegation
24614         if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
24615             mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
24616             invalidate(true);
24617             refreshDrawableState();
24618             dispatchSetActivated(activated);
24619         }
24620     }
24621 
24622     /**
24623      * Dispatch setActivated to all of this View's children.
24624      *
24625      * @see #setActivated(boolean)
24626      *
24627      * @param activated The new activated state
24628      */
dispatchSetActivated(boolean activated)24629     protected void dispatchSetActivated(boolean activated) {
24630     }
24631 
24632     /**
24633      * Indicates the activation state of this view.
24634      *
24635      * @return true if the view is activated, false otherwise
24636      */
24637     @ViewDebug.ExportedProperty
24638     @InspectableProperty(hasAttributeId = false)
isActivated()24639     public boolean isActivated() {
24640         return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
24641     }
24642 
24643     /**
24644      * Returns the ViewTreeObserver for this view's hierarchy. The view tree
24645      * observer can be used to get notifications when global events, like
24646      * layout, happen.
24647      *
24648      * The returned ViewTreeObserver observer is not guaranteed to remain
24649      * valid for the lifetime of this View. If the caller of this method keeps
24650      * a long-lived reference to ViewTreeObserver, it should always check for
24651      * the return value of {@link ViewTreeObserver#isAlive()}.
24652      *
24653      * @return The ViewTreeObserver for this view's hierarchy.
24654      */
getViewTreeObserver()24655     public ViewTreeObserver getViewTreeObserver() {
24656         if (mAttachInfo != null) {
24657             return mAttachInfo.mTreeObserver;
24658         }
24659         if (mFloatingTreeObserver == null) {
24660             mFloatingTreeObserver = new ViewTreeObserver(mContext);
24661         }
24662         return mFloatingTreeObserver;
24663     }
24664 
24665     /**
24666      * <p>Finds the topmost view in the current view hierarchy.</p>
24667      *
24668      * @return the topmost view containing this view
24669      */
getRootView()24670     public View getRootView() {
24671         if (mAttachInfo != null) {
24672             final View v = mAttachInfo.mRootView;
24673             if (v != null) {
24674                 return v;
24675             }
24676         }
24677 
24678         View parent = this;
24679 
24680         while (parent.mParent != null && parent.mParent instanceof View) {
24681             parent = (View) parent.mParent;
24682         }
24683 
24684         return parent;
24685     }
24686 
24687     /**
24688      * Transforms a motion event from view-local coordinates to on-screen
24689      * coordinates.
24690      *
24691      * @param ev the view-local motion event
24692      * @return false if the transformation could not be applied
24693      * @hide
24694      */
24695     @UnsupportedAppUsage
toGlobalMotionEvent(MotionEvent ev)24696     public boolean toGlobalMotionEvent(MotionEvent ev) {
24697         final AttachInfo info = mAttachInfo;
24698         if (info == null) {
24699             return false;
24700         }
24701 
24702         final Matrix m = info.mTmpMatrix;
24703         m.set(Matrix.IDENTITY_MATRIX);
24704         transformMatrixToGlobal(m);
24705         ev.transform(m);
24706         return true;
24707     }
24708 
24709     /**
24710      * Transforms a motion event from on-screen coordinates to view-local
24711      * coordinates.
24712      *
24713      * @param ev the on-screen motion event
24714      * @return false if the transformation could not be applied
24715      * @hide
24716      */
24717     @UnsupportedAppUsage
toLocalMotionEvent(MotionEvent ev)24718     public boolean toLocalMotionEvent(MotionEvent ev) {
24719         final AttachInfo info = mAttachInfo;
24720         if (info == null) {
24721             return false;
24722         }
24723 
24724         final Matrix m = info.mTmpMatrix;
24725         m.set(Matrix.IDENTITY_MATRIX);
24726         transformMatrixToLocal(m);
24727         ev.transform(m);
24728         return true;
24729     }
24730 
24731     /**
24732      * Modifies the input matrix such that it maps view-local coordinates to
24733      * on-screen coordinates.
24734      *
24735      * @param matrix input matrix to modify
24736      */
transformMatrixToGlobal(@onNull Matrix matrix)24737     public void transformMatrixToGlobal(@NonNull Matrix matrix) {
24738         final ViewParent parent = mParent;
24739         if (parent instanceof View) {
24740             final View vp = (View) parent;
24741             vp.transformMatrixToGlobal(matrix);
24742             matrix.preTranslate(-vp.mScrollX, -vp.mScrollY);
24743         } else if (parent instanceof ViewRootImpl) {
24744             final ViewRootImpl vr = (ViewRootImpl) parent;
24745             vr.transformMatrixToGlobal(matrix);
24746             matrix.preTranslate(0, -vr.mCurScrollY);
24747         }
24748 
24749         matrix.preTranslate(mLeft, mTop);
24750 
24751         if (!hasIdentityMatrix()) {
24752             matrix.preConcat(getMatrix());
24753         }
24754     }
24755 
24756     /**
24757      * Modifies the input matrix such that it maps on-screen coordinates to
24758      * view-local coordinates.
24759      *
24760      * @param matrix input matrix to modify
24761      */
transformMatrixToLocal(@onNull Matrix matrix)24762     public void transformMatrixToLocal(@NonNull Matrix matrix) {
24763         final ViewParent parent = mParent;
24764         if (parent instanceof View) {
24765             final View vp = (View) parent;
24766             vp.transformMatrixToLocal(matrix);
24767             matrix.postTranslate(vp.mScrollX, vp.mScrollY);
24768         } else if (parent instanceof ViewRootImpl) {
24769             final ViewRootImpl vr = (ViewRootImpl) parent;
24770             vr.transformMatrixToLocal(matrix);
24771             matrix.postTranslate(0, vr.mCurScrollY);
24772         }
24773 
24774         matrix.postTranslate(-mLeft, -mTop);
24775 
24776         if (!hasIdentityMatrix()) {
24777             matrix.postConcat(getInverseMatrix());
24778         }
24779     }
24780 
24781     /**
24782      * @hide
24783      */
24784     @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
24785             @ViewDebug.IntToString(from = 0, to = "x"),
24786             @ViewDebug.IntToString(from = 1, to = "y")
24787     })
24788     @UnsupportedAppUsage
getLocationOnScreen()24789     public int[] getLocationOnScreen() {
24790         int[] location = new int[2];
24791         getLocationOnScreen(location);
24792         return location;
24793     }
24794 
24795     /**
24796      * <p>Computes the coordinates of this view on the screen. The argument
24797      * must be an array of two integers. After the method returns, the array
24798      * contains the x and y location in that order.</p>
24799      *
24800      * @param outLocation an array of two integers in which to hold the coordinates
24801      */
getLocationOnScreen(@ize2) int[] outLocation)24802     public void getLocationOnScreen(@Size(2) int[] outLocation) {
24803         getLocationInWindow(outLocation);
24804 
24805         final AttachInfo info = mAttachInfo;
24806         if (info != null) {
24807             outLocation[0] += info.mWindowLeft;
24808             outLocation[1] += info.mWindowTop;
24809         }
24810     }
24811 
24812     /**
24813      * <p>Computes the coordinates of this view in its window. The argument
24814      * must be an array of two integers. After the method returns, the array
24815      * contains the x and y location in that order.</p>
24816      *
24817      * @param outLocation an array of two integers in which to hold the coordinates
24818      */
getLocationInWindow(@ize2) int[] outLocation)24819     public void getLocationInWindow(@Size(2) int[] outLocation) {
24820         if (outLocation == null || outLocation.length < 2) {
24821             throw new IllegalArgumentException("outLocation must be an array of two integers");
24822         }
24823 
24824         outLocation[0] = 0;
24825         outLocation[1] = 0;
24826 
24827         transformFromViewToWindowSpace(outLocation);
24828     }
24829 
24830     /** @hide */
transformFromViewToWindowSpace(@ize2) int[] inOutLocation)24831     public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
24832         if (inOutLocation == null || inOutLocation.length < 2) {
24833             throw new IllegalArgumentException("inOutLocation must be an array of two integers");
24834         }
24835 
24836         if (mAttachInfo == null) {
24837             // When the view is not attached to a window, this method does not make sense
24838             inOutLocation[0] = inOutLocation[1] = 0;
24839             return;
24840         }
24841 
24842         float position[] = mAttachInfo.mTmpTransformLocation;
24843         position[0] = inOutLocation[0];
24844         position[1] = inOutLocation[1];
24845 
24846         if (!hasIdentityMatrix()) {
24847             getMatrix().mapPoints(position);
24848         }
24849 
24850         position[0] += mLeft;
24851         position[1] += mTop;
24852 
24853         ViewParent viewParent = mParent;
24854         while (viewParent instanceof View) {
24855             final View view = (View) viewParent;
24856 
24857             position[0] -= view.mScrollX;
24858             position[1] -= view.mScrollY;
24859 
24860             if (!view.hasIdentityMatrix()) {
24861                 view.getMatrix().mapPoints(position);
24862             }
24863 
24864             position[0] += view.mLeft;
24865             position[1] += view.mTop;
24866 
24867             viewParent = view.mParent;
24868          }
24869 
24870         if (viewParent instanceof ViewRootImpl) {
24871             // *cough*
24872             final ViewRootImpl vr = (ViewRootImpl) viewParent;
24873             position[1] -= vr.mCurScrollY;
24874         }
24875 
24876         inOutLocation[0] = Math.round(position[0]);
24877         inOutLocation[1] = Math.round(position[1]);
24878     }
24879 
24880     /**
24881      * @param id the id of the view to be found
24882      * @return the view of the specified id, null if cannot be found
24883      * @hide
24884      */
findViewTraversal(@dRes int id)24885     protected <T extends View> T findViewTraversal(@IdRes int id) {
24886         if (id == mID) {
24887             return (T) this;
24888         }
24889         return null;
24890     }
24891 
24892     /**
24893      * @param tag the tag of the view to be found
24894      * @return the view of specified tag, null if cannot be found
24895      * @hide
24896      */
findViewWithTagTraversal(Object tag)24897     protected <T extends View> T findViewWithTagTraversal(Object tag) {
24898         if (tag != null && tag.equals(mTag)) {
24899             return (T) this;
24900         }
24901         return null;
24902     }
24903 
24904     /**
24905      * @param predicate The predicate to evaluate.
24906      * @param childToSkip If not null, ignores this child during the recursive traversal.
24907      * @return The first view that matches the predicate or null.
24908      * @hide
24909      */
findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip)24910     protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
24911             View childToSkip) {
24912         if (predicate.test(this)) {
24913             return (T) this;
24914         }
24915         return null;
24916     }
24917 
24918     /**
24919      * Finds the first descendant view with the given ID, the view itself if
24920      * the ID matches {@link #getId()}, or {@code null} if the ID is invalid
24921      * (< 0) or there is no matching view in the hierarchy.
24922      * <p>
24923      * <strong>Note:</strong> In most cases -- depending on compiler support --
24924      * the resulting view is automatically cast to the target class type. If
24925      * the target class type is unconstrained, an explicit cast may be
24926      * necessary.
24927      *
24928      * @param id the ID to search for
24929      * @return a view with given ID if found, or {@code null} otherwise
24930      * @see View#requireViewById(int)
24931      */
24932     @Nullable
findViewById(@dRes int id)24933     public final <T extends View> T findViewById(@IdRes int id) {
24934         if (id == NO_ID) {
24935             return null;
24936         }
24937         return findViewTraversal(id);
24938     }
24939 
24940     /**
24941      * Finds the first descendant view with the given ID, the view itself if the ID matches
24942      * {@link #getId()}, or throws an IllegalArgumentException if the ID is invalid or there is no
24943      * matching view in the hierarchy.
24944      * <p>
24945      * <strong>Note:</strong> In most cases -- depending on compiler support --
24946      * the resulting view is automatically cast to the target class type. If
24947      * the target class type is unconstrained, an explicit cast may be
24948      * necessary.
24949      *
24950      * @param id the ID to search for
24951      * @return a view with given ID
24952      * @see View#findViewById(int)
24953      */
24954     @NonNull
requireViewById(@dRes int id)24955     public final <T extends View> T requireViewById(@IdRes int id) {
24956         T view = findViewById(id);
24957         if (view == null) {
24958             throw new IllegalArgumentException("ID does not reference a View inside this View");
24959         }
24960         return view;
24961     }
24962 
24963     /**
24964      * Performs the traversal to find a view by its unique and stable accessibility id.
24965      *
24966      * <strong>Note:</strong>This method does not stop at the root namespace
24967      * boundary since the user can touch the screen at an arbitrary location
24968      * potentially crossing the root namespace boundary which will send an
24969      * accessibility event to accessibility services and they should be able
24970      * to obtain the event source. Also accessibility ids are guaranteed to be
24971      * unique in the window.
24972      *
24973      * @param accessibilityId The accessibility id.
24974      * @return The found view.
24975      * @hide
24976      */
findViewByAccessibilityIdTraversal(int accessibilityId)24977     public <T extends View> T findViewByAccessibilityIdTraversal(int accessibilityId) {
24978         if (getAccessibilityViewId() == accessibilityId) {
24979             return (T) this;
24980         }
24981         return null;
24982     }
24983 
24984     /**
24985      * Performs the traversal to find a view by its autofill id.
24986      *
24987      * <strong>Note:</strong>This method does not stop at the root namespace
24988      * boundary.
24989      *
24990      * @param autofillId The autofill id.
24991      * @return The found view.
24992      * @hide
24993      */
findViewByAutofillIdTraversal(int autofillId)24994     public <T extends View> T findViewByAutofillIdTraversal(int autofillId) {
24995         if (getAutofillViewId() == autofillId) {
24996             return (T) this;
24997         }
24998         return null;
24999     }
25000 
25001     /**
25002      * Look for a child view with the given tag.  If this view has the given
25003      * tag, return this view.
25004      *
25005      * @param tag The tag to search for, using "tag.equals(getTag())".
25006      * @return The View that has the given tag in the hierarchy or null
25007      */
findViewWithTag(Object tag)25008     public final <T extends View> T findViewWithTag(Object tag) {
25009         if (tag == null) {
25010             return null;
25011         }
25012         return findViewWithTagTraversal(tag);
25013     }
25014 
25015     /**
25016      * Look for a child view that matches the specified predicate.
25017      * If this view matches the predicate, return this view.
25018      *
25019      * @param predicate The predicate to evaluate.
25020      * @return The first view that matches the predicate or null.
25021      * @hide
25022      */
findViewByPredicate(Predicate<View> predicate)25023     public final <T extends View> T findViewByPredicate(Predicate<View> predicate) {
25024         return findViewByPredicateTraversal(predicate, null);
25025     }
25026 
25027     /**
25028      * Look for a child view that matches the specified predicate,
25029      * starting with the specified view and its descendents and then
25030      * recusively searching the ancestors and siblings of that view
25031      * until this view is reached.
25032      *
25033      * This method is useful in cases where the predicate does not match
25034      * a single unique view (perhaps multiple views use the same id)
25035      * and we are trying to find the view that is "closest" in scope to the
25036      * starting view.
25037      *
25038      * @param start The view to start from.
25039      * @param predicate The predicate to evaluate.
25040      * @return The first view that matches the predicate or null.
25041      * @hide
25042      */
findViewByPredicateInsideOut( View start, Predicate<View> predicate)25043     public final <T extends View> T findViewByPredicateInsideOut(
25044             View start, Predicate<View> predicate) {
25045         View childToSkip = null;
25046         for (;;) {
25047             T view = start.findViewByPredicateTraversal(predicate, childToSkip);
25048             if (view != null || start == this) {
25049                 return view;
25050             }
25051 
25052             ViewParent parent = start.getParent();
25053             if (parent == null || !(parent instanceof View)) {
25054                 return null;
25055             }
25056 
25057             childToSkip = start;
25058             start = (View) parent;
25059         }
25060     }
25061 
25062     /**
25063      * Sets the identifier for this view. The identifier does not have to be
25064      * unique in this view's hierarchy. The identifier should be a positive
25065      * number.
25066      *
25067      * @see #NO_ID
25068      * @see #getId()
25069      * @see #findViewById(int)
25070      *
25071      * @param id a number used to identify the view
25072      *
25073      * @attr ref android.R.styleable#View_id
25074      */
setId(@dRes int id)25075     public void setId(@IdRes int id) {
25076         mID = id;
25077         if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
25078             mID = generateViewId();
25079         }
25080     }
25081 
25082     /**
25083      * {@hide}
25084      *
25085      * @param isRoot true if the view belongs to the root namespace, false
25086      *        otherwise
25087      */
25088     @UnsupportedAppUsage
25089     @TestApi
setIsRootNamespace(boolean isRoot)25090     public void setIsRootNamespace(boolean isRoot) {
25091         if (isRoot) {
25092             mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
25093         } else {
25094             mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
25095         }
25096     }
25097 
25098     /**
25099      * {@hide}
25100      *
25101      * @return true if the view belongs to the root namespace, false otherwise
25102      */
25103     @UnsupportedAppUsage
isRootNamespace()25104     public boolean isRootNamespace() {
25105         return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
25106     }
25107 
25108     /**
25109      * Returns this view's identifier.
25110      *
25111      * @return a positive integer used to identify the view or {@link #NO_ID}
25112      *         if the view has no ID
25113      *
25114      * @see #setId(int)
25115      * @see #findViewById(int)
25116      * @attr ref android.R.styleable#View_id
25117      */
25118     @IdRes
25119     @ViewDebug.CapturedViewProperty
25120     @InspectableProperty
getId()25121     public int getId() {
25122         return mID;
25123     }
25124 
25125     /**
25126      * Get the identifier used for this view by the drawing system.
25127      *
25128      * @see RenderNode#getUniqueId()
25129      * @return A long that uniquely identifies this view's drawing component
25130      */
getUniqueDrawingId()25131     public long getUniqueDrawingId() {
25132         return mRenderNode.getUniqueId();
25133     }
25134 
25135     /**
25136      * Returns this view's tag.
25137      *
25138      * @return the Object stored in this view as a tag, or {@code null} if not
25139      *         set
25140      *
25141      * @see #setTag(Object)
25142      * @see #getTag(int)
25143      */
25144     @ViewDebug.ExportedProperty
25145     @InspectableProperty
getTag()25146     public Object getTag() {
25147         return mTag;
25148     }
25149 
25150     /**
25151      * Sets the tag associated with this view. A tag can be used to mark
25152      * a view in its hierarchy and does not have to be unique within the
25153      * hierarchy. Tags can also be used to store data within a view without
25154      * resorting to another data structure.
25155      *
25156      * @param tag an Object to tag the view with
25157      *
25158      * @see #getTag()
25159      * @see #setTag(int, Object)
25160      */
setTag(final Object tag)25161     public void setTag(final Object tag) {
25162         mTag = tag;
25163     }
25164 
25165     /**
25166      * Returns the tag associated with this view and the specified key.
25167      *
25168      * @param key The key identifying the tag
25169      *
25170      * @return the Object stored in this view as a tag, or {@code null} if not
25171      *         set
25172      *
25173      * @see #setTag(int, Object)
25174      * @see #getTag()
25175      */
getTag(int key)25176     public Object getTag(int key) {
25177         if (mKeyedTags != null) return mKeyedTags.get(key);
25178         return null;
25179     }
25180 
25181     /**
25182      * Sets a tag associated with this view and a key. A tag can be used
25183      * to mark a view in its hierarchy and does not have to be unique within
25184      * the hierarchy. Tags can also be used to store data within a view
25185      * without resorting to another data structure.
25186      *
25187      * The specified key should be an id declared in the resources of the
25188      * application to ensure it is unique (see the <a
25189      * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
25190      * Keys identified as belonging to
25191      * the Android framework or not associated with any package will cause
25192      * an {@link IllegalArgumentException} to be thrown.
25193      *
25194      * @param key The key identifying the tag
25195      * @param tag An Object to tag the view with
25196      *
25197      * @throws IllegalArgumentException If they specified key is not valid
25198      *
25199      * @see #setTag(Object)
25200      * @see #getTag(int)
25201      */
setTag(int key, final Object tag)25202     public void setTag(int key, final Object tag) {
25203         // If the package id is 0x00 or 0x01, it's either an undefined package
25204         // or a framework id
25205         if ((key >>> 24) < 2) {
25206             throw new IllegalArgumentException("The key must be an application-specific "
25207                     + "resource id.");
25208         }
25209 
25210         setKeyedTag(key, tag);
25211     }
25212 
25213     /**
25214      * Variation of {@link #setTag(int, Object)} that enforces the key to be a
25215      * framework id.
25216      *
25217      * @hide
25218      */
25219     @UnsupportedAppUsage
setTagInternal(int key, Object tag)25220     public void setTagInternal(int key, Object tag) {
25221         if ((key >>> 24) != 0x1) {
25222             throw new IllegalArgumentException("The key must be a framework-specific "
25223                     + "resource id.");
25224         }
25225 
25226         setKeyedTag(key, tag);
25227     }
25228 
setKeyedTag(int key, Object tag)25229     private void setKeyedTag(int key, Object tag) {
25230         if (mKeyedTags == null) {
25231             mKeyedTags = new SparseArray<Object>(2);
25232         }
25233 
25234         mKeyedTags.put(key, tag);
25235     }
25236 
25237     /**
25238      * Prints information about this view in the log output, with the tag
25239      * {@link #VIEW_LOG_TAG}.
25240      *
25241      * @hide
25242      */
25243     @UnsupportedAppUsage
debug()25244     public void debug() {
25245         debug(0);
25246     }
25247 
25248     /**
25249      * Prints information about this view in the log output, with the tag
25250      * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
25251      * indentation defined by the <code>depth</code>.
25252      *
25253      * @param depth the indentation level
25254      *
25255      * @hide
25256      */
25257     @UnsupportedAppUsage
debug(int depth)25258     protected void debug(int depth) {
25259         String output = debugIndent(depth - 1);
25260 
25261         output += "+ " + this;
25262         int id = getId();
25263         if (id != -1) {
25264             output += " (id=" + id + ")";
25265         }
25266         Object tag = getTag();
25267         if (tag != null) {
25268             output += " (tag=" + tag + ")";
25269         }
25270         Log.d(VIEW_LOG_TAG, output);
25271 
25272         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
25273             output = debugIndent(depth) + " FOCUSED";
25274             Log.d(VIEW_LOG_TAG, output);
25275         }
25276 
25277         output = debugIndent(depth);
25278         output += "frame={" + mLeft + ", " + mTop + ", " + mRight
25279                 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
25280                 + "} ";
25281         Log.d(VIEW_LOG_TAG, output);
25282 
25283         if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
25284                 || mPaddingBottom != 0) {
25285             output = debugIndent(depth);
25286             output += "padding={" + mPaddingLeft + ", " + mPaddingTop
25287                     + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
25288             Log.d(VIEW_LOG_TAG, output);
25289         }
25290 
25291         output = debugIndent(depth);
25292         output += "mMeasureWidth=" + mMeasuredWidth +
25293                 " mMeasureHeight=" + mMeasuredHeight;
25294         Log.d(VIEW_LOG_TAG, output);
25295 
25296         output = debugIndent(depth);
25297         if (mLayoutParams == null) {
25298             output += "BAD! no layout params";
25299         } else {
25300             output = mLayoutParams.debug(output);
25301         }
25302         Log.d(VIEW_LOG_TAG, output);
25303 
25304         output = debugIndent(depth);
25305         output += "flags={";
25306         output += View.printFlags(mViewFlags);
25307         output += "}";
25308         Log.d(VIEW_LOG_TAG, output);
25309 
25310         output = debugIndent(depth);
25311         output += "privateFlags={";
25312         output += View.printPrivateFlags(mPrivateFlags);
25313         output += "}";
25314         Log.d(VIEW_LOG_TAG, output);
25315     }
25316 
25317     /**
25318      * Creates a string of whitespaces used for indentation.
25319      *
25320      * @param depth the indentation level
25321      * @return a String containing (depth * 2 + 3) * 2 white spaces
25322      *
25323      * @hide
25324      */
debugIndent(int depth)25325     protected static String debugIndent(int depth) {
25326         StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
25327         for (int i = 0; i < (depth * 2) + 3; i++) {
25328             spaces.append(' ').append(' ');
25329         }
25330         return spaces.toString();
25331     }
25332 
25333     /**
25334      * <p>Return the offset of the widget's text baseline from the widget's top
25335      * boundary. If this widget does not support baseline alignment, this
25336      * method returns -1. </p>
25337      *
25338      * @return the offset of the baseline within the widget's bounds or -1
25339      *         if baseline alignment is not supported
25340      */
25341     @ViewDebug.ExportedProperty(category = "layout")
25342     @InspectableProperty
getBaseline()25343     public int getBaseline() {
25344         return -1;
25345     }
25346 
25347     /**
25348      * Returns whether the view hierarchy is currently undergoing a layout pass. This
25349      * information is useful to avoid situations such as calling {@link #requestLayout()} during
25350      * a layout pass.
25351      *
25352      * @return whether the view hierarchy is currently undergoing a layout pass
25353      */
isInLayout()25354     public boolean isInLayout() {
25355         ViewRootImpl viewRoot = getViewRootImpl();
25356         return (viewRoot != null && viewRoot.isInLayout());
25357     }
25358 
25359     /**
25360      * Call this when something has changed which has invalidated the
25361      * layout of this view. This will schedule a layout pass of the view
25362      * tree. This should not be called while the view hierarchy is currently in a layout
25363      * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
25364      * end of the current layout pass (and then layout will run again) or after the current
25365      * frame is drawn and the next layout occurs.
25366      *
25367      * <p>Subclasses which override this method should call the superclass method to
25368      * handle possible request-during-layout errors correctly.</p>
25369      */
25370     @CallSuper
requestLayout()25371     public void requestLayout() {
25372         if (mMeasureCache != null) mMeasureCache.clear();
25373 
25374         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
25375             // Only trigger request-during-layout logic if this is the view requesting it,
25376             // not the views in its parent hierarchy
25377             ViewRootImpl viewRoot = getViewRootImpl();
25378             if (viewRoot != null && viewRoot.isInLayout()) {
25379                 if (!viewRoot.requestLayoutDuringLayout(this)) {
25380                     return;
25381                 }
25382             }
25383             mAttachInfo.mViewRequestingLayout = this;
25384         }
25385 
25386         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
25387         mPrivateFlags |= PFLAG_INVALIDATED;
25388 
25389         if (mParent != null && !mParent.isLayoutRequested()) {
25390             mParent.requestLayout();
25391         }
25392         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
25393             mAttachInfo.mViewRequestingLayout = null;
25394         }
25395     }
25396 
25397     /**
25398      * Forces this view to be laid out during the next layout pass.
25399      * This method does not call requestLayout() or forceLayout()
25400      * on the parent.
25401      */
forceLayout()25402     public void forceLayout() {
25403         if (mMeasureCache != null) mMeasureCache.clear();
25404 
25405         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
25406         mPrivateFlags |= PFLAG_INVALIDATED;
25407     }
25408 
25409     /**
25410      * <p>
25411      * This is called to find out how big a view should be. The parent
25412      * supplies constraint information in the width and height parameters.
25413      * </p>
25414      *
25415      * <p>
25416      * The actual measurement work of a view is performed in
25417      * {@link #onMeasure(int, int)}, called by this method. Therefore, only
25418      * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
25419      * </p>
25420      *
25421      *
25422      * @param widthMeasureSpec Horizontal space requirements as imposed by the
25423      *        parent
25424      * @param heightMeasureSpec Vertical space requirements as imposed by the
25425      *        parent
25426      *
25427      * @see #onMeasure(int, int)
25428      */
measure(int widthMeasureSpec, int heightMeasureSpec)25429     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
25430         boolean optical = isLayoutModeOptical(this);
25431         if (optical != isLayoutModeOptical(mParent)) {
25432             Insets insets = getOpticalInsets();
25433             int oWidth  = insets.left + insets.right;
25434             int oHeight = insets.top  + insets.bottom;
25435             widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
25436             heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
25437         }
25438 
25439         // Suppress sign extension for the low bytes
25440         long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
25441         if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
25442 
25443         final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
25444 
25445         // Optimize layout by avoiding an extra EXACTLY pass when the view is
25446         // already measured as the correct size. In API 23 and below, this
25447         // extra pass is required to make LinearLayout re-distribute weight.
25448         final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
25449                 || heightMeasureSpec != mOldHeightMeasureSpec;
25450         final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
25451                 && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
25452         final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
25453                 && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
25454         final boolean needsLayout = specChanged
25455                 && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
25456 
25457         if (forceLayout || needsLayout) {
25458             // first clears the measured dimension flag
25459             mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
25460 
25461             resolveRtlPropertiesIfNeeded();
25462 
25463             int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
25464             if (cacheIndex < 0 || sIgnoreMeasureCache) {
25465                 // measure ourselves, this should set the measured dimension flag back
25466                 onMeasure(widthMeasureSpec, heightMeasureSpec);
25467                 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
25468             } else {
25469                 long value = mMeasureCache.valueAt(cacheIndex);
25470                 // Casting a long to int drops the high 32 bits, no mask needed
25471                 setMeasuredDimensionRaw((int) (value >> 32), (int) value);
25472                 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
25473             }
25474 
25475             // flag not set, setMeasuredDimension() was not invoked, we raise
25476             // an exception to warn the developer
25477             if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
25478                 throw new IllegalStateException("View with id " + getId() + ": "
25479                         + getClass().getName() + "#onMeasure() did not set the"
25480                         + " measured dimension by calling"
25481                         + " setMeasuredDimension()");
25482             }
25483 
25484             mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
25485         }
25486 
25487         mOldWidthMeasureSpec = widthMeasureSpec;
25488         mOldHeightMeasureSpec = heightMeasureSpec;
25489 
25490         mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
25491                 (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
25492     }
25493 
25494     /**
25495      * <p>
25496      * Measure the view and its content to determine the measured width and the
25497      * measured height. This method is invoked by {@link #measure(int, int)} and
25498      * should be overridden by subclasses to provide accurate and efficient
25499      * measurement of their contents.
25500      * </p>
25501      *
25502      * <p>
25503      * <strong>CONTRACT:</strong> When overriding this method, you
25504      * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
25505      * measured width and height of this view. Failure to do so will trigger an
25506      * <code>IllegalStateException</code>, thrown by
25507      * {@link #measure(int, int)}. Calling the superclass'
25508      * {@link #onMeasure(int, int)} is a valid use.
25509      * </p>
25510      *
25511      * <p>
25512      * The base class implementation of measure defaults to the background size,
25513      * unless a larger size is allowed by the MeasureSpec. Subclasses should
25514      * override {@link #onMeasure(int, int)} to provide better measurements of
25515      * their content.
25516      * </p>
25517      *
25518      * <p>
25519      * If this method is overridden, it is the subclass's responsibility to make
25520      * sure the measured height and width are at least the view's minimum height
25521      * and width ({@link #getSuggestedMinimumHeight()} and
25522      * {@link #getSuggestedMinimumWidth()}).
25523      * </p>
25524      *
25525      * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
25526      *                         The requirements are encoded with
25527      *                         {@link android.view.View.MeasureSpec}.
25528      * @param heightMeasureSpec vertical space requirements as imposed by the parent.
25529      *                         The requirements are encoded with
25530      *                         {@link android.view.View.MeasureSpec}.
25531      *
25532      * @see #getMeasuredWidth()
25533      * @see #getMeasuredHeight()
25534      * @see #setMeasuredDimension(int, int)
25535      * @see #getSuggestedMinimumHeight()
25536      * @see #getSuggestedMinimumWidth()
25537      * @see android.view.View.MeasureSpec#getMode(int)
25538      * @see android.view.View.MeasureSpec#getSize(int)
25539      */
onMeasure(int widthMeasureSpec, int heightMeasureSpec)25540     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
25541         setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
25542                 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
25543     }
25544 
25545     /**
25546      * <p>This method must be called by {@link #onMeasure(int, int)} to store the
25547      * measured width and measured height. Failing to do so will trigger an
25548      * exception at measurement time.</p>
25549      *
25550      * @param measuredWidth The measured width of this view.  May be a complex
25551      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
25552      * {@link #MEASURED_STATE_TOO_SMALL}.
25553      * @param measuredHeight The measured height of this view.  May be a complex
25554      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
25555      * {@link #MEASURED_STATE_TOO_SMALL}.
25556      */
setMeasuredDimension(int measuredWidth, int measuredHeight)25557     protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
25558         boolean optical = isLayoutModeOptical(this);
25559         if (optical != isLayoutModeOptical(mParent)) {
25560             Insets insets = getOpticalInsets();
25561             int opticalWidth  = insets.left + insets.right;
25562             int opticalHeight = insets.top  + insets.bottom;
25563 
25564             measuredWidth  += optical ? opticalWidth  : -opticalWidth;
25565             measuredHeight += optical ? opticalHeight : -opticalHeight;
25566         }
25567         setMeasuredDimensionRaw(measuredWidth, measuredHeight);
25568     }
25569 
25570     /**
25571      * Sets the measured dimension without extra processing for things like optical bounds.
25572      * Useful for reapplying consistent values that have already been cooked with adjustments
25573      * for optical bounds, etc. such as those from the measurement cache.
25574      *
25575      * @param measuredWidth The measured width of this view.  May be a complex
25576      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
25577      * {@link #MEASURED_STATE_TOO_SMALL}.
25578      * @param measuredHeight The measured height of this view.  May be a complex
25579      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
25580      * {@link #MEASURED_STATE_TOO_SMALL}.
25581      */
setMeasuredDimensionRaw(int measuredWidth, int measuredHeight)25582     private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
25583         mMeasuredWidth = measuredWidth;
25584         mMeasuredHeight = measuredHeight;
25585 
25586         mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
25587     }
25588 
25589     /**
25590      * Merge two states as returned by {@link #getMeasuredState()}.
25591      * @param curState The current state as returned from a view or the result
25592      * of combining multiple views.
25593      * @param newState The new view state to combine.
25594      * @return Returns a new integer reflecting the combination of the two
25595      * states.
25596      */
combineMeasuredStates(int curState, int newState)25597     public static int combineMeasuredStates(int curState, int newState) {
25598         return curState | newState;
25599     }
25600 
25601     /**
25602      * Version of {@link #resolveSizeAndState(int, int, int)}
25603      * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
25604      */
resolveSize(int size, int measureSpec)25605     public static int resolveSize(int size, int measureSpec) {
25606         return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
25607     }
25608 
25609     /**
25610      * Utility to reconcile a desired size and state, with constraints imposed
25611      * by a MeasureSpec. Will take the desired size, unless a different size
25612      * is imposed by the constraints. The returned value is a compound integer,
25613      * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
25614      * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
25615      * resulting size is smaller than the size the view wants to be.
25616      *
25617      * @param size How big the view wants to be.
25618      * @param measureSpec Constraints imposed by the parent.
25619      * @param childMeasuredState Size information bit mask for the view's
25620      *                           children.
25621      * @return Size information bit mask as defined by
25622      *         {@link #MEASURED_SIZE_MASK} and
25623      *         {@link #MEASURED_STATE_TOO_SMALL}.
25624      */
resolveSizeAndState(int size, int measureSpec, int childMeasuredState)25625     public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
25626         final int specMode = MeasureSpec.getMode(measureSpec);
25627         final int specSize = MeasureSpec.getSize(measureSpec);
25628         final int result;
25629         switch (specMode) {
25630             case MeasureSpec.AT_MOST:
25631                 if (specSize < size) {
25632                     result = specSize | MEASURED_STATE_TOO_SMALL;
25633                 } else {
25634                     result = size;
25635                 }
25636                 break;
25637             case MeasureSpec.EXACTLY:
25638                 result = specSize;
25639                 break;
25640             case MeasureSpec.UNSPECIFIED:
25641             default:
25642                 result = size;
25643         }
25644         return result | (childMeasuredState & MEASURED_STATE_MASK);
25645     }
25646 
25647     /**
25648      * Utility to return a default size. Uses the supplied size if the
25649      * MeasureSpec imposed no constraints. Will get larger if allowed
25650      * by the MeasureSpec.
25651      *
25652      * @param size Default size for this view
25653      * @param measureSpec Constraints imposed by the parent
25654      * @return The size this view should be.
25655      */
getDefaultSize(int size, int measureSpec)25656     public static int getDefaultSize(int size, int measureSpec) {
25657         int result = size;
25658         int specMode = MeasureSpec.getMode(measureSpec);
25659         int specSize = MeasureSpec.getSize(measureSpec);
25660 
25661         switch (specMode) {
25662         case MeasureSpec.UNSPECIFIED:
25663             result = size;
25664             break;
25665         case MeasureSpec.AT_MOST:
25666         case MeasureSpec.EXACTLY:
25667             result = specSize;
25668             break;
25669         }
25670         return result;
25671     }
25672 
25673     /**
25674      * Returns the suggested minimum height that the view should use. This
25675      * returns the maximum of the view's minimum height
25676      * and the background's minimum height
25677      * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
25678      * <p>
25679      * When being used in {@link #onMeasure(int, int)}, the caller should still
25680      * ensure the returned height is within the requirements of the parent.
25681      *
25682      * @return The suggested minimum height of the view.
25683      */
getSuggestedMinimumHeight()25684     protected int getSuggestedMinimumHeight() {
25685         return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
25686 
25687     }
25688 
25689     /**
25690      * Returns the suggested minimum width that the view should use. This
25691      * returns the maximum of the view's minimum width
25692      * and the background's minimum width
25693      *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
25694      * <p>
25695      * When being used in {@link #onMeasure(int, int)}, the caller should still
25696      * ensure the returned width is within the requirements of the parent.
25697      *
25698      * @return The suggested minimum width of the view.
25699      */
getSuggestedMinimumWidth()25700     protected int getSuggestedMinimumWidth() {
25701         return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
25702     }
25703 
25704     /**
25705      * Returns the minimum height of the view.
25706      *
25707      * @return the minimum height the view will try to be, in pixels
25708      *
25709      * @see #setMinimumHeight(int)
25710      *
25711      * @attr ref android.R.styleable#View_minHeight
25712      */
25713     @InspectableProperty(name = "minHeight")
getMinimumHeight()25714     public int getMinimumHeight() {
25715         return mMinHeight;
25716     }
25717 
25718     /**
25719      * Sets the minimum height of the view. It is not guaranteed the view will
25720      * be able to achieve this minimum height (for example, if its parent layout
25721      * constrains it with less available height).
25722      *
25723      * @param minHeight The minimum height the view will try to be, in pixels
25724      *
25725      * @see #getMinimumHeight()
25726      *
25727      * @attr ref android.R.styleable#View_minHeight
25728      */
25729     @RemotableViewMethod
setMinimumHeight(int minHeight)25730     public void setMinimumHeight(int minHeight) {
25731         mMinHeight = minHeight;
25732         requestLayout();
25733     }
25734 
25735     /**
25736      * Returns the minimum width of the view.
25737      *
25738      * @return the minimum width the view will try to be, in pixels
25739      *
25740      * @see #setMinimumWidth(int)
25741      *
25742      * @attr ref android.R.styleable#View_minWidth
25743      */
25744     @InspectableProperty(name = "minWidth")
getMinimumWidth()25745     public int getMinimumWidth() {
25746         return mMinWidth;
25747     }
25748 
25749     /**
25750      * Sets the minimum width of the view. It is not guaranteed the view will
25751      * be able to achieve this minimum width (for example, if its parent layout
25752      * constrains it with less available width).
25753      *
25754      * @param minWidth The minimum width the view will try to be, in pixels
25755      *
25756      * @see #getMinimumWidth()
25757      *
25758      * @attr ref android.R.styleable#View_minWidth
25759      */
setMinimumWidth(int minWidth)25760     public void setMinimumWidth(int minWidth) {
25761         mMinWidth = minWidth;
25762         requestLayout();
25763 
25764     }
25765 
25766     /**
25767      * Get the animation currently associated with this view.
25768      *
25769      * @return The animation that is currently playing or
25770      *         scheduled to play for this view.
25771      */
getAnimation()25772     public Animation getAnimation() {
25773         return mCurrentAnimation;
25774     }
25775 
25776     /**
25777      * Start the specified animation now.
25778      *
25779      * @param animation the animation to start now
25780      */
startAnimation(Animation animation)25781     public void startAnimation(Animation animation) {
25782         animation.setStartTime(Animation.START_ON_FIRST_FRAME);
25783         setAnimation(animation);
25784         invalidateParentCaches();
25785         invalidate(true);
25786     }
25787 
25788     /**
25789      * Cancels any animations for this view.
25790      */
clearAnimation()25791     public void clearAnimation() {
25792         if (mCurrentAnimation != null) {
25793             mCurrentAnimation.detach();
25794         }
25795         mCurrentAnimation = null;
25796         invalidateParentIfNeeded();
25797     }
25798 
25799     /**
25800      * Sets the next animation to play for this view.
25801      * If you want the animation to play immediately, use
25802      * {@link #startAnimation(android.view.animation.Animation)} instead.
25803      * This method provides allows fine-grained
25804      * control over the start time and invalidation, but you
25805      * must make sure that 1) the animation has a start time set, and
25806      * 2) the view's parent (which controls animations on its children)
25807      * will be invalidated when the animation is supposed to
25808      * start.
25809      *
25810      * @param animation The next animation, or null.
25811      */
setAnimation(Animation animation)25812     public void setAnimation(Animation animation) {
25813         mCurrentAnimation = animation;
25814 
25815         if (animation != null) {
25816             // If the screen is off assume the animation start time is now instead of
25817             // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
25818             // would cause the animation to start when the screen turns back on
25819             if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
25820                     && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
25821                 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
25822             }
25823             animation.reset();
25824         }
25825     }
25826 
25827     /**
25828      * Invoked by a parent ViewGroup to notify the start of the animation
25829      * currently associated with this view. If you override this method,
25830      * always call super.onAnimationStart();
25831      *
25832      * @see #setAnimation(android.view.animation.Animation)
25833      * @see #getAnimation()
25834      */
25835     @CallSuper
onAnimationStart()25836     protected void onAnimationStart() {
25837         mPrivateFlags |= PFLAG_ANIMATION_STARTED;
25838     }
25839 
25840     /**
25841      * Invoked by a parent ViewGroup to notify the end of the animation
25842      * currently associated with this view. If you override this method,
25843      * always call super.onAnimationEnd();
25844      *
25845      * @see #setAnimation(android.view.animation.Animation)
25846      * @see #getAnimation()
25847      */
25848     @CallSuper
onAnimationEnd()25849     protected void onAnimationEnd() {
25850         mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
25851     }
25852 
25853     /**
25854      * Invoked if there is a Transform that involves alpha. Subclass that can
25855      * draw themselves with the specified alpha should return true, and then
25856      * respect that alpha when their onDraw() is called. If this returns false
25857      * then the view may be redirected to draw into an offscreen buffer to
25858      * fulfill the request, which will look fine, but may be slower than if the
25859      * subclass handles it internally. The default implementation returns false.
25860      *
25861      * @param alpha The alpha (0..255) to apply to the view's drawing
25862      * @return true if the view can draw with the specified alpha.
25863      */
onSetAlpha(int alpha)25864     protected boolean onSetAlpha(int alpha) {
25865         return false;
25866     }
25867 
25868     /**
25869      * This is used by the RootView to perform an optimization when
25870      * the view hierarchy contains one or several SurfaceView.
25871      * SurfaceView is always considered transparent, but its children are not,
25872      * therefore all View objects remove themselves from the global transparent
25873      * region (passed as a parameter to this function).
25874      *
25875      * @param region The transparent region for this ViewAncestor (window).
25876      *
25877      * @return Returns true if the effective visibility of the view at this
25878      * point is opaque, regardless of the transparent region; returns false
25879      * if it is possible for underlying windows to be seen behind the view.
25880      *
25881      * {@hide}
25882      */
25883     @UnsupportedAppUsage
gatherTransparentRegion(Region region)25884     public boolean gatherTransparentRegion(Region region) {
25885         final AttachInfo attachInfo = mAttachInfo;
25886         if (region != null && attachInfo != null) {
25887             final int pflags = mPrivateFlags;
25888             if ((pflags & PFLAG_SKIP_DRAW) == 0) {
25889                 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
25890                 // remove it from the transparent region.
25891                 final int[] location = attachInfo.mTransparentLocation;
25892                 getLocationInWindow(location);
25893                 // When a view has Z value, then it will be better to leave some area below the view
25894                 // for drawing shadow. The shadow outset is proportional to the Z value. Note that
25895                 // the bottom part needs more offset than the left, top and right parts due to the
25896                 // spot light effects.
25897                 int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
25898                 region.op(location[0] - shadowOffset, location[1] - shadowOffset,
25899                         location[0] + mRight - mLeft + shadowOffset,
25900                         location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
25901             } else {
25902                 if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
25903                     // The SKIP_DRAW flag IS set and the background drawable exists, we remove
25904                     // the background drawable's non-transparent parts from this transparent region.
25905                     applyDrawableToTransparentRegion(mBackground, region);
25906                 }
25907                 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
25908                         && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
25909                     // Similarly, we remove the foreground drawable's non-transparent parts.
25910                     applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
25911                 }
25912                 if (mDefaultFocusHighlight != null
25913                         && mDefaultFocusHighlight.getOpacity() != PixelFormat.TRANSPARENT) {
25914                     // Similarly, we remove the default focus highlight's non-transparent parts.
25915                     applyDrawableToTransparentRegion(mDefaultFocusHighlight, region);
25916                 }
25917             }
25918         }
25919         return true;
25920     }
25921 
25922     /**
25923      * Play a sound effect for this view.
25924      *
25925      * <p>The framework will play sound effects for some built in actions, such as
25926      * clicking, but you may wish to play these effects in your widget,
25927      * for instance, for internal navigation.
25928      *
25929      * <p>The sound effect will only be played if sound effects are enabled by the user, and
25930      * {@link #isSoundEffectsEnabled()} is true.
25931      *
25932      * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
25933      */
playSoundEffect(int soundConstant)25934     public void playSoundEffect(int soundConstant) {
25935         if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
25936             return;
25937         }
25938         mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
25939     }
25940 
25941     /**
25942      * BZZZTT!!1!
25943      *
25944      * <p>Provide haptic feedback to the user for this view.
25945      *
25946      * <p>The framework will provide haptic feedback for some built in actions,
25947      * such as long presses, but you may wish to provide feedback for your
25948      * own widget.
25949      *
25950      * <p>The feedback will only be performed if
25951      * {@link #isHapticFeedbackEnabled()} is true.
25952      *
25953      * @param feedbackConstant One of the constants defined in
25954      * {@link HapticFeedbackConstants}
25955      */
performHapticFeedback(int feedbackConstant)25956     public boolean performHapticFeedback(int feedbackConstant) {
25957         return performHapticFeedback(feedbackConstant, 0);
25958     }
25959 
25960     /**
25961      * BZZZTT!!1!
25962      *
25963      * <p>Like {@link #performHapticFeedback(int)}, with additional options.
25964      *
25965      * @param feedbackConstant One of the constants defined in
25966      * {@link HapticFeedbackConstants}
25967      * @param flags Additional flags as per {@link HapticFeedbackConstants}.
25968      */
performHapticFeedback(int feedbackConstant, int flags)25969     public boolean performHapticFeedback(int feedbackConstant, int flags) {
25970         if (mAttachInfo == null) {
25971             return false;
25972         }
25973         //noinspection SimplifiableIfStatement
25974         if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
25975                 && !isHapticFeedbackEnabled()) {
25976             return false;
25977         }
25978         return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
25979                 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
25980     }
25981 
25982     /**
25983      * Request that the visibility of the status bar or other screen/window
25984      * decorations be changed.
25985      *
25986      * <p>This method is used to put the over device UI into temporary modes
25987      * where the user's attention is focused more on the application content,
25988      * by dimming or hiding surrounding system affordances.  This is typically
25989      * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
25990      * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
25991      * to be placed behind the action bar (and with these flags other system
25992      * affordances) so that smooth transitions between hiding and showing them
25993      * can be done.
25994      *
25995      * <p>Two representative examples of the use of system UI visibility is
25996      * implementing a content browsing application (like a magazine reader)
25997      * and a video playing application.
25998      *
25999      * <p>The first code shows a typical implementation of a View in a content
26000      * browsing application.  In this implementation, the application goes
26001      * into a content-oriented mode by hiding the status bar and action bar,
26002      * and putting the navigation elements into lights out mode.  The user can
26003      * then interact with content while in this mode.  Such an application should
26004      * provide an easy way for the user to toggle out of the mode (such as to
26005      * check information in the status bar or access notifications).  In the
26006      * implementation here, this is done simply by tapping on the content.
26007      *
26008      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
26009      *      content}
26010      *
26011      * <p>This second code sample shows a typical implementation of a View
26012      * in a video playing application.  In this situation, while the video is
26013      * playing the application would like to go into a complete full-screen mode,
26014      * to use as much of the display as possible for the video.  When in this state
26015      * the user can not interact with the application; the system intercepts
26016      * touching on the screen to pop the UI out of full screen mode.  See
26017      * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
26018      *
26019      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
26020      *      content}
26021      *
26022      * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
26023      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
26024      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
26025      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
26026      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
26027      *
26028      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
26029      * instead.
26030      */
26031     @Deprecated
setSystemUiVisibility(int visibility)26032     public void setSystemUiVisibility(int visibility) {
26033         if (visibility != mSystemUiVisibility) {
26034             mSystemUiVisibility = visibility;
26035             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
26036                 mParent.recomputeViewAttributes(this);
26037             }
26038         }
26039     }
26040 
26041     /**
26042      * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
26043      * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
26044      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
26045      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
26046      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
26047      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
26048      *
26049      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
26050      * instead.
26051      */
26052     @Deprecated
getSystemUiVisibility()26053     public int getSystemUiVisibility() {
26054         return mSystemUiVisibility;
26055     }
26056 
26057     /**
26058      * Returns the current system UI visibility that is currently set for
26059      * the entire window.  This is the combination of the
26060      * {@link #setSystemUiVisibility(int)} values supplied by all of the
26061      * views in the window.
26062      *
26063      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
26064      * instead.
26065      */
26066     @Deprecated
getWindowSystemUiVisibility()26067     public int getWindowSystemUiVisibility() {
26068         return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
26069     }
26070 
26071     /**
26072      * Override to find out when the window's requested system UI visibility
26073      * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
26074      * This is different from the callbacks received through
26075      * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
26076      * in that this is only telling you about the local request of the window,
26077      * not the actual values applied by the system.
26078      *
26079      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
26080      * instead.
26081      */
26082     @Deprecated
onWindowSystemUiVisibilityChanged(int visible)26083     public void onWindowSystemUiVisibilityChanged(int visible) {
26084     }
26085 
26086     /**
26087      * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
26088      * the view hierarchy.
26089      *
26090      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
26091      * instead.
26092      */
26093     @Deprecated
dispatchWindowSystemUiVisiblityChanged(int visible)26094     public void dispatchWindowSystemUiVisiblityChanged(int visible) {
26095         onWindowSystemUiVisibilityChanged(visible);
26096     }
26097 
26098     /**
26099      * Set a listener to receive callbacks when the visibility of the system bar changes.
26100      * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
26101      *
26102      * @deprecated Use {@link WindowInsets#isVisible(int)} to find out about system bar visibilities
26103      * by setting a {@link OnApplyWindowInsetsListener} on this view.
26104      */
26105     @Deprecated
setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l)26106     public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
26107         getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
26108         if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
26109             mParent.recomputeViewAttributes(this);
26110         }
26111     }
26112 
26113     /**
26114      * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
26115      * the view hierarchy.
26116      *
26117      * @deprecated Use {@link WindowInsets#isVisible(int)} to find out about system bar visibilities
26118      * by setting a {@link OnApplyWindowInsetsListener} on this view.
26119      */
26120     @Deprecated
dispatchSystemUiVisibilityChanged(int visibility)26121     public void dispatchSystemUiVisibilityChanged(int visibility) {
26122         ListenerInfo li = mListenerInfo;
26123         if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
26124             li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
26125                     visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
26126         }
26127     }
26128 
updateLocalSystemUiVisibility(int localValue, int localChanges)26129     boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
26130         int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
26131         if (val != mSystemUiVisibility) {
26132             setSystemUiVisibility(val);
26133             return true;
26134         }
26135         return false;
26136     }
26137 
26138     /** @hide */
26139     @UnsupportedAppUsage
setDisabledSystemUiVisibility(int flags)26140     public void setDisabledSystemUiVisibility(int flags) {
26141         if (mAttachInfo != null) {
26142             if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
26143                 mAttachInfo.mDisabledSystemUiVisibility = flags;
26144                 if (mParent != null) {
26145                     mParent.recomputeViewAttributes(this);
26146                 }
26147             }
26148         }
26149     }
26150 
26151     /**
26152      * Creates an image that the system displays during the drag and drop
26153      * operation. This is called a &quot;drag shadow&quot;. The default implementation
26154      * for a DragShadowBuilder based on a View returns an image that has exactly the same
26155      * appearance as the given View. The default also positions the center of the drag shadow
26156      * directly under the touch point. If no View is provided (the constructor with no parameters
26157      * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
26158      * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
26159      * default is an invisible drag shadow.
26160      * <p>
26161      * You are not required to use the View you provide to the constructor as the basis of the
26162      * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
26163      * anything you want as the drag shadow.
26164      * </p>
26165      * <p>
26166      *  You pass a DragShadowBuilder object to the system when you start the drag. The system
26167      *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
26168      *  size and position of the drag shadow. It uses this data to construct a
26169      *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
26170      *  so that your application can draw the shadow image in the Canvas.
26171      * </p>
26172      *
26173      * <div class="special reference">
26174      * <h3>Developer Guides</h3>
26175      * <p>For a guide to implementing drag and drop features, read the
26176      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
26177      * </div>
26178      */
26179     public static class DragShadowBuilder {
26180         @UnsupportedAppUsage
26181         private final WeakReference<View> mView;
26182 
26183         /**
26184          * Constructs a shadow image builder based on a View. By default, the resulting drag
26185          * shadow will have the same appearance and dimensions as the View, with the touch point
26186          * over the center of the View.
26187          * @param view A View. Any View in scope can be used.
26188          */
DragShadowBuilder(View view)26189         public DragShadowBuilder(View view) {
26190             mView = new WeakReference<View>(view);
26191         }
26192 
26193         /**
26194          * Construct a shadow builder object with no associated View.  This
26195          * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
26196          * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
26197          * to supply the drag shadow's dimensions and appearance without
26198          * reference to any View object.
26199          */
DragShadowBuilder()26200         public DragShadowBuilder() {
26201             mView = new WeakReference<View>(null);
26202         }
26203 
26204         /**
26205          * Returns the View object that had been passed to the
26206          * {@link #DragShadowBuilder(View)}
26207          * constructor.  If that View parameter was {@code null} or if the
26208          * {@link #DragShadowBuilder()}
26209          * constructor was used to instantiate the builder object, this method will return
26210          * null.
26211          *
26212          * @return The View object associate with this builder object.
26213          */
26214         @SuppressWarnings({"JavadocReference"})
getView()26215         final public View getView() {
26216             return mView.get();
26217         }
26218 
26219         /**
26220          * Provides the metrics for the shadow image. These include the dimensions of
26221          * the shadow image, and the point within that shadow that should
26222          * be centered under the touch location while dragging.
26223          * <p>
26224          * The default implementation sets the dimensions of the shadow to be the
26225          * same as the dimensions of the View itself and centers the shadow under
26226          * the touch point.
26227          * </p>
26228          *
26229          * @param outShadowSize A {@link android.graphics.Point} containing the width and height
26230          * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
26231          * desired width and must set {@link android.graphics.Point#y} to the desired height of the
26232          * image. Since Android P, the width and height must be positive values.
26233          *
26234          * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
26235          * shadow image that should be underneath the touch point during the drag and drop
26236          * operation. Your application must set {@link android.graphics.Point#x} to the
26237          * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
26238          */
onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint)26239         public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
26240             final View view = mView.get();
26241             if (view != null) {
26242                 outShadowSize.set(view.getWidth(), view.getHeight());
26243                 outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
26244             } else {
26245                 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
26246             }
26247         }
26248 
26249         /**
26250          * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
26251          * based on the dimensions it received from the
26252          * {@link #onProvideShadowMetrics(Point, Point)} callback.
26253          *
26254          * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
26255          */
onDrawShadow(Canvas canvas)26256         public void onDrawShadow(Canvas canvas) {
26257             final View view = mView.get();
26258             if (view != null) {
26259                 view.draw(canvas);
26260             } else {
26261                 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
26262             }
26263         }
26264     }
26265 
26266     /**
26267      * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
26268      * startDragAndDrop()} for newer platform versions.
26269      */
26270     @Deprecated
startDrag(ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flags)26271     public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
26272                                    Object myLocalState, int flags) {
26273         return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
26274     }
26275 
26276     /**
26277      * Starts a drag and drop operation. When your application calls this method, it passes a
26278      * {@link android.view.View.DragShadowBuilder} object to the system. The
26279      * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
26280      * to get metrics for the drag shadow, and then calls the object's
26281      * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
26282      * <p>
26283      *  Once the system has the drag shadow, it begins the drag and drop operation by sending
26284      *  drag events to all the View objects in your application that are currently visible. It does
26285      *  this either by calling the View object's drag listener (an implementation of
26286      *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
26287      *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
26288      *  Both are passed a {@link android.view.DragEvent} object that has a
26289      *  {@link android.view.DragEvent#getAction()} value of
26290      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
26291      * </p>
26292      * <p>
26293      * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
26294      * int) startDragAndDrop()} on any attached View object. The View object does not need to be
26295      * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
26296      * to the View the user selected for dragging.
26297      * </p>
26298      * @param data A {@link android.content.ClipData} object pointing to the data to be
26299      * transferred by the drag and drop operation.
26300      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
26301      * drag shadow.
26302      * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
26303      * drop operation. When dispatching drag events to views in the same activity this object
26304      * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other
26305      * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()}
26306      * will return null).
26307      * <p>
26308      * myLocalState is a lightweight mechanism for the sending information from the dragged View
26309      * to the target Views. For example, it can contain flags that differentiate between a
26310      * a copy operation and a move operation.
26311      * </p>
26312      * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
26313      * flags, or any combination of the following:
26314      *     <ul>
26315      *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
26316      *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
26317      *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
26318      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
26319      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
26320      *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
26321      *     </ul>
26322      * @return {@code true} if the method completes successfully, or
26323      * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
26324      * do a drag because of another ongoing operation or some other reasons.
26325      */
startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flags)26326     public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
26327             Object myLocalState, int flags) {
26328         if (ViewDebug.DEBUG_DRAG) {
26329             Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
26330         }
26331         if (mAttachInfo == null) {
26332             Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
26333             return false;
26334         }
26335         if (!mAttachInfo.mViewRootImpl.mSurface.isValid()) {
26336             Log.w(VIEW_LOG_TAG, "startDragAndDrop called with an invalid surface.");
26337             return false;
26338         }
26339 
26340         if (data != null) {
26341             data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0);
26342         }
26343 
26344         Point shadowSize = new Point();
26345         Point shadowTouchPoint = new Point();
26346         shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
26347 
26348         if ((shadowSize.x < 0) || (shadowSize.y < 0)
26349                 || (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
26350             throw new IllegalStateException("Drag shadow dimensions must not be negative");
26351         }
26352 
26353         // Create 1x1 surface when zero surface size is specified because SurfaceControl.Builder
26354         // does not accept zero size surface.
26355         if (shadowSize.x == 0  || shadowSize.y == 0) {
26356             if (!sAcceptZeroSizeDragShadow) {
26357                 throw new IllegalStateException("Drag shadow dimensions must be positive");
26358             }
26359             shadowSize.x = 1;
26360             shadowSize.y = 1;
26361         }
26362 
26363         if (ViewDebug.DEBUG_DRAG) {
26364             Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
26365                     + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
26366         }
26367 
26368         final ViewRootImpl root = mAttachInfo.mViewRootImpl;
26369         final SurfaceSession session = new SurfaceSession();
26370         final SurfaceControl surfaceControl = new SurfaceControl.Builder(session)
26371                 .setName("drag surface")
26372                 .setParent(root.getSurfaceControl())
26373                 .setBufferSize(shadowSize.x, shadowSize.y)
26374                 .setFormat(PixelFormat.TRANSLUCENT)
26375                 .setCallsite("View.startDragAndDrop")
26376                 .build();
26377         final Surface surface = new Surface();
26378         surface.copyFrom(surfaceControl);
26379         IBinder token = null;
26380         try {
26381             final Canvas canvas = surface.lockCanvas(null);
26382             try {
26383                 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
26384                 shadowBuilder.onDrawShadow(canvas);
26385             } finally {
26386                 surface.unlockCanvasAndPost(canvas);
26387             }
26388 
26389             // repurpose 'shadowSize' for the last touch point
26390             root.getLastTouchPoint(shadowSize);
26391 
26392             token = mAttachInfo.mSession.performDrag(
26393                     mAttachInfo.mWindow, flags, surfaceControl, root.getLastTouchSource(),
26394                     shadowSize.x, shadowSize.y, shadowTouchPoint.x, shadowTouchPoint.y, data);
26395             if (ViewDebug.DEBUG_DRAG) {
26396                 Log.d(VIEW_LOG_TAG, "performDrag returned " + token);
26397             }
26398             if (token != null) {
26399                 if (mAttachInfo.mDragSurface != null) {
26400                     mAttachInfo.mDragSurface.release();
26401                 }
26402                 mAttachInfo.mDragSurface = surface;
26403                 mAttachInfo.mDragToken = token;
26404                 // Cache the local state object for delivery with DragEvents
26405                 root.setLocalDragState(myLocalState);
26406             }
26407             return token != null;
26408         } catch (Exception e) {
26409             Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
26410             return false;
26411         } finally {
26412             if (token == null) {
26413                 surface.destroy();
26414             }
26415             session.kill();
26416         }
26417     }
26418 
26419     /**
26420      * Cancels an ongoing drag and drop operation.
26421      * <p>
26422      * A {@link android.view.DragEvent} object with
26423      * {@link android.view.DragEvent#getAction()} value of
26424      * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
26425      * {@link android.view.DragEvent#getResult()} value of {@code false}
26426      * will be sent to every
26427      * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
26428      * even if they are not currently visible.
26429      * </p>
26430      * <p>
26431      * This method can be called on any View in the same window as the View on which
26432      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
26433      * was called.
26434      * </p>
26435      */
cancelDragAndDrop()26436     public final void cancelDragAndDrop() {
26437         if (ViewDebug.DEBUG_DRAG) {
26438             Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
26439         }
26440         if (mAttachInfo == null) {
26441             Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
26442             return;
26443         }
26444         if (mAttachInfo.mDragToken != null) {
26445             try {
26446                 mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken, false);
26447             } catch (Exception e) {
26448                 Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
26449             }
26450             mAttachInfo.mDragToken = null;
26451         } else {
26452             Log.e(VIEW_LOG_TAG, "No active drag to cancel");
26453         }
26454     }
26455 
26456     /**
26457      * Updates the drag shadow for the ongoing drag and drop operation.
26458      *
26459      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
26460      * new drag shadow.
26461      */
updateDragShadow(DragShadowBuilder shadowBuilder)26462     public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
26463         if (ViewDebug.DEBUG_DRAG) {
26464             Log.d(VIEW_LOG_TAG, "updateDragShadow");
26465         }
26466         if (mAttachInfo == null) {
26467             Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
26468             return;
26469         }
26470         if (mAttachInfo.mDragToken != null) {
26471             try {
26472                 Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
26473                 try {
26474                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
26475                     shadowBuilder.onDrawShadow(canvas);
26476                 } finally {
26477                     mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
26478                 }
26479             } catch (Exception e) {
26480                 Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
26481             }
26482         } else {
26483             Log.e(VIEW_LOG_TAG, "No active drag");
26484         }
26485     }
26486 
26487     /**
26488      * Starts a move from {startX, startY}, the amount of the movement will be the offset
26489      * between {startX, startY} and the new cursor positon.
26490      * @param startX horizontal coordinate where the move started.
26491      * @param startY vertical coordinate where the move started.
26492      * @return whether moving was started successfully.
26493      * @hide
26494      */
startMovingTask(float startX, float startY)26495     public final boolean startMovingTask(float startX, float startY) {
26496         if (ViewDebug.DEBUG_POSITIONING) {
26497             Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
26498         }
26499         try {
26500             return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
26501         } catch (RemoteException e) {
26502             Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
26503         }
26504         return false;
26505     }
26506 
26507     /**
26508      * Finish a window move task.
26509      * @hide
26510      */
finishMovingTask()26511     public void finishMovingTask() {
26512         if (ViewDebug.DEBUG_POSITIONING) {
26513             Log.d(VIEW_LOG_TAG, "finishMovingTask");
26514         }
26515         try {
26516             mAttachInfo.mSession.finishMovingTask(mAttachInfo.mWindow);
26517         } catch (RemoteException e) {
26518             Log.e(VIEW_LOG_TAG, "Unable to finish moving", e);
26519         }
26520     }
26521 
26522     /**
26523      * Handles drag events sent by the system following a call to
26524      * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
26525      * startDragAndDrop()}.
26526      *<p>
26527      * When the system calls this method, it passes a
26528      * {@link android.view.DragEvent} object. A call to
26529      * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
26530      * in DragEvent. The method uses these to determine what is happening in the drag and drop
26531      * operation.
26532      * @param event The {@link android.view.DragEvent} sent by the system.
26533      * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
26534      * in DragEvent, indicating the type of drag event represented by this object.
26535      * @return {@code true} if the method was successful, otherwise {@code false}.
26536      * <p>
26537      *  The method should return {@code true} in response to an action type of
26538      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
26539      *  operation.
26540      * </p>
26541      * <p>
26542      *  The method should also return {@code true} in response to an action type of
26543      *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
26544      *  {@code false} if it didn't.
26545      * </p>
26546      * <p>
26547      *  For all other events, the return value is ignored.
26548      * </p>
26549      */
onDragEvent(DragEvent event)26550     public boolean onDragEvent(DragEvent event) {
26551         return false;
26552     }
26553 
26554     // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps.
dispatchDragEnterExitInPreN(DragEvent event)26555     boolean dispatchDragEnterExitInPreN(DragEvent event) {
26556         return callDragEventHandler(event);
26557     }
26558 
26559     /**
26560      * Detects if this View is enabled and has a drag event listener.
26561      * If both are true, then it calls the drag event listener with the
26562      * {@link android.view.DragEvent} it received. If the drag event listener returns
26563      * {@code true}, then dispatchDragEvent() returns {@code true}.
26564      * <p>
26565      * For all other cases, the method calls the
26566      * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
26567      * method and returns its result.
26568      * </p>
26569      * <p>
26570      * This ensures that a drag event is always consumed, even if the View does not have a drag
26571      * event listener. However, if the View has a listener and the listener returns true, then
26572      * onDragEvent() is not called.
26573      * </p>
26574      */
dispatchDragEvent(DragEvent event)26575     public boolean dispatchDragEvent(DragEvent event) {
26576         event.mEventHandlerWasCalled = true;
26577         if (event.mAction == DragEvent.ACTION_DRAG_LOCATION ||
26578             event.mAction == DragEvent.ACTION_DROP) {
26579             // About to deliver an event with coordinates to this view. Notify that now this view
26580             // has drag focus. This will send exit/enter events as needed.
26581             getViewRootImpl().setDragFocus(this, event);
26582         }
26583         return callDragEventHandler(event);
26584     }
26585 
callDragEventHandler(DragEvent event)26586     final boolean callDragEventHandler(DragEvent event) {
26587         final boolean result;
26588 
26589         ListenerInfo li = mListenerInfo;
26590         //noinspection SimplifiableIfStatement
26591         if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
26592                 && li.mOnDragListener.onDrag(this, event)) {
26593             result = true;
26594         } else {
26595             result = onDragEvent(event);
26596         }
26597 
26598         switch (event.mAction) {
26599             case DragEvent.ACTION_DRAG_ENTERED: {
26600                 mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
26601                 refreshDrawableState();
26602             } break;
26603             case DragEvent.ACTION_DRAG_EXITED: {
26604                 mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
26605                 refreshDrawableState();
26606             } break;
26607             case DragEvent.ACTION_DRAG_ENDED: {
26608                 mPrivateFlags2 &= ~View.DRAG_MASK;
26609                 refreshDrawableState();
26610             } break;
26611         }
26612 
26613         return result;
26614     }
26615 
canAcceptDrag()26616     boolean canAcceptDrag() {
26617         return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
26618     }
26619 
26620     /**
26621      * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
26622      * it is ever exposed at all.
26623      * @hide
26624      */
26625     @UnsupportedAppUsage
onCloseSystemDialogs(String reason)26626     public void onCloseSystemDialogs(String reason) {
26627     }
26628 
26629     /**
26630      * Given a Drawable whose bounds have been set to draw into this view,
26631      * update a Region being computed for
26632      * {@link #gatherTransparentRegion(android.graphics.Region)} so
26633      * that any non-transparent parts of the Drawable are removed from the
26634      * given transparent region.
26635      *
26636      * @param dr The Drawable whose transparency is to be applied to the region.
26637      * @param region A Region holding the current transparency information,
26638      * where any parts of the region that are set are considered to be
26639      * transparent.  On return, this region will be modified to have the
26640      * transparency information reduced by the corresponding parts of the
26641      * Drawable that are not transparent.
26642      * {@hide}
26643      */
26644     @UnsupportedAppUsage
applyDrawableToTransparentRegion(Drawable dr, Region region)26645     public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
26646         if (DBG) {
26647             Log.i("View", "Getting transparent region for: " + this);
26648         }
26649         final Region r = dr.getTransparentRegion();
26650         final Rect db = dr.getBounds();
26651         final AttachInfo attachInfo = mAttachInfo;
26652         if (r != null && attachInfo != null) {
26653             final int w = getRight()-getLeft();
26654             final int h = getBottom()-getTop();
26655             if (db.left > 0) {
26656                 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
26657                 r.op(0, 0, db.left, h, Region.Op.UNION);
26658             }
26659             if (db.right < w) {
26660                 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
26661                 r.op(db.right, 0, w, h, Region.Op.UNION);
26662             }
26663             if (db.top > 0) {
26664                 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
26665                 r.op(0, 0, w, db.top, Region.Op.UNION);
26666             }
26667             if (db.bottom < h) {
26668                 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
26669                 r.op(0, db.bottom, w, h, Region.Op.UNION);
26670             }
26671             final int[] location = attachInfo.mTransparentLocation;
26672             getLocationInWindow(location);
26673             r.translate(location[0], location[1]);
26674             region.op(r, Region.Op.INTERSECT);
26675         } else {
26676             region.op(db, Region.Op.DIFFERENCE);
26677         }
26678     }
26679 
checkForLongClick(long delay, float x, float y, int classification)26680     private void checkForLongClick(long delay, float x, float y, int classification) {
26681         if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
26682             mHasPerformedLongPress = false;
26683 
26684             if (mPendingCheckForLongPress == null) {
26685                 mPendingCheckForLongPress = new CheckForLongPress();
26686             }
26687             mPendingCheckForLongPress.setAnchor(x, y);
26688             mPendingCheckForLongPress.rememberWindowAttachCount();
26689             mPendingCheckForLongPress.rememberPressedState();
26690             mPendingCheckForLongPress.setClassification(classification);
26691             postDelayed(mPendingCheckForLongPress, delay);
26692         }
26693     }
26694 
26695     /**
26696      * Inflate a view from an XML resource.  This convenience method wraps the {@link
26697      * LayoutInflater} class, which provides a full range of options for view inflation.
26698      *
26699      * @param context The Context object for your activity or application.
26700      * @param resource The resource ID to inflate
26701      * @param root A view group that will be the parent.  Used to properly inflate the
26702      * layout_* parameters.
26703      * @see LayoutInflater
26704      */
inflate(Context context, @LayoutRes int resource, ViewGroup root)26705     public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
26706         LayoutInflater factory = LayoutInflater.from(context);
26707         return factory.inflate(resource, root);
26708     }
26709 
26710     /**
26711      * Scroll the view with standard behavior for scrolling beyond the normal
26712      * content boundaries. Views that call this method should override
26713      * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
26714      * results of an over-scroll operation.
26715      *
26716      * Views can use this method to handle any touch or fling-based scrolling.
26717      *
26718      * @param deltaX Change in X in pixels
26719      * @param deltaY Change in Y in pixels
26720      * @param scrollX Current X scroll value in pixels before applying deltaX
26721      * @param scrollY Current Y scroll value in pixels before applying deltaY
26722      * @param scrollRangeX Maximum content scroll range along the X axis
26723      * @param scrollRangeY Maximum content scroll range along the Y axis
26724      * @param maxOverScrollX Number of pixels to overscroll by in either direction
26725      *          along the X axis.
26726      * @param maxOverScrollY Number of pixels to overscroll by in either direction
26727      *          along the Y axis.
26728      * @param isTouchEvent true if this scroll operation is the result of a touch event.
26729      * @return true if scrolling was clamped to an over-scroll boundary along either
26730      *          axis, false otherwise.
26731      */
26732     @SuppressWarnings({"UnusedParameters"})
overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent)26733     protected boolean overScrollBy(int deltaX, int deltaY,
26734             int scrollX, int scrollY,
26735             int scrollRangeX, int scrollRangeY,
26736             int maxOverScrollX, int maxOverScrollY,
26737             boolean isTouchEvent) {
26738         final int overScrollMode = mOverScrollMode;
26739         final boolean canScrollHorizontal =
26740                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
26741         final boolean canScrollVertical =
26742                 computeVerticalScrollRange() > computeVerticalScrollExtent();
26743         final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
26744                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
26745         final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
26746                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
26747 
26748         int newScrollX = scrollX + deltaX;
26749         if (!overScrollHorizontal) {
26750             maxOverScrollX = 0;
26751         }
26752 
26753         int newScrollY = scrollY + deltaY;
26754         if (!overScrollVertical) {
26755             maxOverScrollY = 0;
26756         }
26757 
26758         // Clamp values if at the limits and record
26759         final int left = -maxOverScrollX;
26760         final int right = maxOverScrollX + scrollRangeX;
26761         final int top = -maxOverScrollY;
26762         final int bottom = maxOverScrollY + scrollRangeY;
26763 
26764         boolean clampedX = false;
26765         if (newScrollX > right) {
26766             newScrollX = right;
26767             clampedX = true;
26768         } else if (newScrollX < left) {
26769             newScrollX = left;
26770             clampedX = true;
26771         }
26772 
26773         boolean clampedY = false;
26774         if (newScrollY > bottom) {
26775             newScrollY = bottom;
26776             clampedY = true;
26777         } else if (newScrollY < top) {
26778             newScrollY = top;
26779             clampedY = true;
26780         }
26781 
26782         onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
26783 
26784         return clampedX || clampedY;
26785     }
26786 
26787     /**
26788      * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
26789      * respond to the results of an over-scroll operation.
26790      *
26791      * @param scrollX New X scroll value in pixels
26792      * @param scrollY New Y scroll value in pixels
26793      * @param clampedX True if scrollX was clamped to an over-scroll boundary
26794      * @param clampedY True if scrollY was clamped to an over-scroll boundary
26795      */
onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY)26796     protected void onOverScrolled(int scrollX, int scrollY,
26797             boolean clampedX, boolean clampedY) {
26798         // Intentionally empty.
26799     }
26800 
26801     /**
26802      * Returns the over-scroll mode for this view. The result will be
26803      * one of {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
26804      * (allow over-scrolling only if the view content is larger than the container),
26805      * or {@link #OVER_SCROLL_NEVER}.
26806      *
26807      * @return This view's over-scroll mode.
26808      */
26809     @InspectableProperty(enumMapping = {
26810             @EnumEntry(value = OVER_SCROLL_ALWAYS, name = "always"),
26811             @EnumEntry(value = OVER_SCROLL_IF_CONTENT_SCROLLS, name = "ifContentScrolls"),
26812             @EnumEntry(value = OVER_SCROLL_NEVER, name = "never")
26813     })
getOverScrollMode()26814     public int getOverScrollMode() {
26815         return mOverScrollMode;
26816     }
26817 
26818     /**
26819      * Set the over-scroll mode for this view. Valid over-scroll modes are
26820      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
26821      * (allow over-scrolling only if the view content is larger than the container),
26822      * or {@link #OVER_SCROLL_NEVER}.
26823      *
26824      * Setting the over-scroll mode of a view will have an effect only if the
26825      * view is capable of scrolling.
26826      *
26827      * @param overScrollMode The new over-scroll mode for this view.
26828      */
setOverScrollMode(int overScrollMode)26829     public void setOverScrollMode(int overScrollMode) {
26830         if (overScrollMode != OVER_SCROLL_ALWAYS &&
26831                 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
26832                 overScrollMode != OVER_SCROLL_NEVER) {
26833             throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
26834         }
26835         mOverScrollMode = overScrollMode;
26836     }
26837 
26838     /**
26839      * Enable or disable nested scrolling for this view.
26840      *
26841      * <p>If this property is set to true the view will be permitted to initiate nested
26842      * scrolling operations with a compatible parent view in the current hierarchy. If this
26843      * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
26844      * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
26845      * the nested scroll.</p>
26846      *
26847      * @param enabled true to enable nested scrolling, false to disable
26848      *
26849      * @see #isNestedScrollingEnabled()
26850      */
setNestedScrollingEnabled(boolean enabled)26851     public void setNestedScrollingEnabled(boolean enabled) {
26852         if (enabled) {
26853             mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
26854         } else {
26855             stopNestedScroll();
26856             mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
26857         }
26858     }
26859 
26860     /**
26861      * Returns true if nested scrolling is enabled for this view.
26862      *
26863      * <p>If nested scrolling is enabled and this View class implementation supports it,
26864      * this view will act as a nested scrolling child view when applicable, forwarding data
26865      * about the scroll operation in progress to a compatible and cooperating nested scrolling
26866      * parent.</p>
26867      *
26868      * @return true if nested scrolling is enabled
26869      *
26870      * @see #setNestedScrollingEnabled(boolean)
26871      */
26872     @InspectableProperty
isNestedScrollingEnabled()26873     public boolean isNestedScrollingEnabled() {
26874         return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
26875                 PFLAG3_NESTED_SCROLLING_ENABLED;
26876     }
26877 
26878     /**
26879      * Begin a nestable scroll operation along the given axes.
26880      *
26881      * <p>A view starting a nested scroll promises to abide by the following contract:</p>
26882      *
26883      * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
26884      * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
26885      * In the case of touch scrolling the nested scroll will be terminated automatically in
26886      * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
26887      * In the event of programmatic scrolling the caller must explicitly call
26888      * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
26889      *
26890      * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
26891      * If it returns false the caller may ignore the rest of this contract until the next scroll.
26892      * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
26893      *
26894      * <p>At each incremental step of the scroll the caller should invoke
26895      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
26896      * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
26897      * parent at least partially consumed the scroll and the caller should adjust the amount it
26898      * scrolls by.</p>
26899      *
26900      * <p>After applying the remainder of the scroll delta the caller should invoke
26901      * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
26902      * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
26903      * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
26904      * </p>
26905      *
26906      * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
26907      *             {@link #SCROLL_AXIS_VERTICAL}.
26908      * @return true if a cooperative parent was found and nested scrolling has been enabled for
26909      *         the current gesture.
26910      *
26911      * @see #stopNestedScroll()
26912      * @see #dispatchNestedPreScroll(int, int, int[], int[])
26913      * @see #dispatchNestedScroll(int, int, int, int, int[])
26914      */
startNestedScroll(int axes)26915     public boolean startNestedScroll(int axes) {
26916         if (hasNestedScrollingParent()) {
26917             // Already in progress
26918             return true;
26919         }
26920         if (isNestedScrollingEnabled()) {
26921             ViewParent p = getParent();
26922             View child = this;
26923             while (p != null) {
26924                 try {
26925                     if (p.onStartNestedScroll(child, this, axes)) {
26926                         mNestedScrollingParent = p;
26927                         p.onNestedScrollAccepted(child, this, axes);
26928                         return true;
26929                     }
26930                 } catch (AbstractMethodError e) {
26931                     Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
26932                             "method onStartNestedScroll", e);
26933                     // Allow the search upward to continue
26934                 }
26935                 if (p instanceof View) {
26936                     child = (View) p;
26937                 }
26938                 p = p.getParent();
26939             }
26940         }
26941         return false;
26942     }
26943 
26944     /**
26945      * Stop a nested scroll in progress.
26946      *
26947      * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
26948      *
26949      * @see #startNestedScroll(int)
26950      */
stopNestedScroll()26951     public void stopNestedScroll() {
26952         if (mNestedScrollingParent != null) {
26953             mNestedScrollingParent.onStopNestedScroll(this);
26954             mNestedScrollingParent = null;
26955         }
26956     }
26957 
26958     /**
26959      * Returns true if this view has a nested scrolling parent.
26960      *
26961      * <p>The presence of a nested scrolling parent indicates that this view has initiated
26962      * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
26963      *
26964      * @return whether this view has a nested scrolling parent
26965      */
hasNestedScrollingParent()26966     public boolean hasNestedScrollingParent() {
26967         return mNestedScrollingParent != null;
26968     }
26969 
26970     /**
26971      * Dispatch one step of a nested scroll in progress.
26972      *
26973      * <p>Implementations of views that support nested scrolling should call this to report
26974      * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
26975      * is not currently in progress or nested scrolling is not
26976      * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
26977      *
26978      * <p>Compatible View implementations should also call
26979      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
26980      * consuming a component of the scroll event themselves.</p>
26981      *
26982      * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
26983      * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
26984      * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
26985      * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
26986      * @param offsetInWindow Optional. If not null, on return this will contain the offset
26987      *                       in local view coordinates of this view from before this operation
26988      *                       to after it completes. View implementations may use this to adjust
26989      *                       expected input coordinate tracking.
26990      * @return true if the event was dispatched, false if it could not be dispatched.
26991      * @see #dispatchNestedPreScroll(int, int, int[], int[])
26992      */
dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow)26993     public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
26994             int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
26995         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
26996             if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
26997                 int startX = 0;
26998                 int startY = 0;
26999                 if (offsetInWindow != null) {
27000                     getLocationInWindow(offsetInWindow);
27001                     startX = offsetInWindow[0];
27002                     startY = offsetInWindow[1];
27003                 }
27004 
27005                 mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
27006                         dxUnconsumed, dyUnconsumed);
27007 
27008                 if (offsetInWindow != null) {
27009                     getLocationInWindow(offsetInWindow);
27010                     offsetInWindow[0] -= startX;
27011                     offsetInWindow[1] -= startY;
27012                 }
27013                 return true;
27014             } else if (offsetInWindow != null) {
27015                 // No motion, no dispatch. Keep offsetInWindow up to date.
27016                 offsetInWindow[0] = 0;
27017                 offsetInWindow[1] = 0;
27018             }
27019         }
27020         return false;
27021     }
27022 
27023     /**
27024      * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
27025      *
27026      * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
27027      * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
27028      * scrolling operation to consume some or all of the scroll operation before the child view
27029      * consumes it.</p>
27030      *
27031      * @param dx Horizontal scroll distance in pixels
27032      * @param dy Vertical scroll distance in pixels
27033      * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
27034      *                 and consumed[1] the consumed dy.
27035      * @param offsetInWindow Optional. If not null, on return this will contain the offset
27036      *                       in local view coordinates of this view from before this operation
27037      *                       to after it completes. View implementations may use this to adjust
27038      *                       expected input coordinate tracking.
27039      * @return true if the parent consumed some or all of the scroll delta
27040      * @see #dispatchNestedScroll(int, int, int, int, int[])
27041      */
dispatchNestedPreScroll(int dx, int dy, @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow)27042     public boolean dispatchNestedPreScroll(int dx, int dy,
27043             @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
27044         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
27045             if (dx != 0 || dy != 0) {
27046                 int startX = 0;
27047                 int startY = 0;
27048                 if (offsetInWindow != null) {
27049                     getLocationInWindow(offsetInWindow);
27050                     startX = offsetInWindow[0];
27051                     startY = offsetInWindow[1];
27052                 }
27053 
27054                 if (consumed == null) {
27055                     if (mTempNestedScrollConsumed == null) {
27056                         mTempNestedScrollConsumed = new int[2];
27057                     }
27058                     consumed = mTempNestedScrollConsumed;
27059                 }
27060                 consumed[0] = 0;
27061                 consumed[1] = 0;
27062                 mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
27063 
27064                 if (offsetInWindow != null) {
27065                     getLocationInWindow(offsetInWindow);
27066                     offsetInWindow[0] -= startX;
27067                     offsetInWindow[1] -= startY;
27068                 }
27069                 return consumed[0] != 0 || consumed[1] != 0;
27070             } else if (offsetInWindow != null) {
27071                 offsetInWindow[0] = 0;
27072                 offsetInWindow[1] = 0;
27073             }
27074         }
27075         return false;
27076     }
27077 
27078     /**
27079      * Dispatch a fling to a nested scrolling parent.
27080      *
27081      * <p>This method should be used to indicate that a nested scrolling child has detected
27082      * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
27083      * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
27084      * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
27085      * along a scrollable axis.</p>
27086      *
27087      * <p>If a nested scrolling child view would normally fling but it is at the edge of
27088      * its own content, it can use this method to delegate the fling to its nested scrolling
27089      * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
27090      *
27091      * @param velocityX Horizontal fling velocity in pixels per second
27092      * @param velocityY Vertical fling velocity in pixels per second
27093      * @param consumed true if the child consumed the fling, false otherwise
27094      * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
27095      */
dispatchNestedFling(float velocityX, float velocityY, boolean consumed)27096     public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
27097         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
27098             return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
27099         }
27100         return false;
27101     }
27102 
27103     /**
27104      * Dispatch a fling to a nested scrolling parent before it is processed by this view.
27105      *
27106      * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
27107      * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
27108      * offsets an opportunity for the parent view in a nested fling to fully consume the fling
27109      * before the child view consumes it. If this method returns <code>true</code>, a nested
27110      * parent view consumed the fling and this view should not scroll as a result.</p>
27111      *
27112      * <p>For a better user experience, only one view in a nested scrolling chain should consume
27113      * the fling at a time. If a parent view consumed the fling this method will return false.
27114      * Custom view implementations should account for this in two ways:</p>
27115      *
27116      * <ul>
27117      *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
27118      *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
27119      *     position regardless.</li>
27120      *     <li>If a nested parent does consume the fling, this view should not scroll at all,
27121      *     even to settle back to a valid idle position.</li>
27122      * </ul>
27123      *
27124      * <p>Views should also not offer fling velocities to nested parent views along an axis
27125      * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
27126      * should not offer a horizontal fling velocity to its parents since scrolling along that
27127      * axis is not permitted and carrying velocity along that motion does not make sense.</p>
27128      *
27129      * @param velocityX Horizontal fling velocity in pixels per second
27130      * @param velocityY Vertical fling velocity in pixels per second
27131      * @return true if a nested scrolling parent consumed the fling
27132      */
dispatchNestedPreFling(float velocityX, float velocityY)27133     public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
27134         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
27135             return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
27136         }
27137         return false;
27138     }
27139 
27140     /**
27141      * Gets a scale factor that determines the distance the view should scroll
27142      * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
27143      * @return The vertical scroll scale factor.
27144      * @hide
27145      */
27146     @UnsupportedAppUsage
getVerticalScrollFactor()27147     protected float getVerticalScrollFactor() {
27148         if (mVerticalScrollFactor == 0) {
27149             TypedValue outValue = new TypedValue();
27150             if (!mContext.getTheme().resolveAttribute(
27151                     com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
27152                 throw new IllegalStateException(
27153                         "Expected theme to define listPreferredItemHeight.");
27154             }
27155             mVerticalScrollFactor = outValue.getDimension(
27156                     mContext.getResources().getDisplayMetrics());
27157         }
27158         return mVerticalScrollFactor;
27159     }
27160 
27161     /**
27162      * Gets a scale factor that determines the distance the view should scroll
27163      * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
27164      * @return The horizontal scroll scale factor.
27165      * @hide
27166      */
27167     @UnsupportedAppUsage
getHorizontalScrollFactor()27168     protected float getHorizontalScrollFactor() {
27169         // TODO: Should use something else.
27170         return getVerticalScrollFactor();
27171     }
27172 
27173     /**
27174      * Return the value specifying the text direction or policy that was set with
27175      * {@link #setTextDirection(int)}.
27176      *
27177      * @return the defined text direction. It can be one of:
27178      *
27179      * {@link #TEXT_DIRECTION_INHERIT},
27180      * {@link #TEXT_DIRECTION_FIRST_STRONG},
27181      * {@link #TEXT_DIRECTION_ANY_RTL},
27182      * {@link #TEXT_DIRECTION_LTR},
27183      * {@link #TEXT_DIRECTION_RTL},
27184      * {@link #TEXT_DIRECTION_LOCALE},
27185      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
27186      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
27187      *
27188      * @attr ref android.R.styleable#View_textDirection
27189      *
27190      * @hide
27191      */
27192     @ViewDebug.ExportedProperty(category = "text", mapping = {
27193             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
27194             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
27195             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
27196             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
27197             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
27198             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
27199             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
27200             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
27201     })
27202     @InspectableProperty(hasAttributeId = false, enumMapping = {
27203             @EnumEntry(value = TEXT_DIRECTION_INHERIT, name = "inherit"),
27204             @EnumEntry(value = TEXT_DIRECTION_LOCALE, name = "locale"),
27205             @EnumEntry(value = TEXT_DIRECTION_ANY_RTL, name = "anyRtl"),
27206             @EnumEntry(value = TEXT_DIRECTION_LTR, name = "ltr"),
27207             @EnumEntry(value = TEXT_DIRECTION_RTL, name = "rtl"),
27208             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG, name = "firstStrong"),
27209             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_LTR, name = "firstStrongLtr"),
27210             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_RTL, name = "firstStrongRtl"),
27211     })
27212     @UnsupportedAppUsage
getRawTextDirection()27213     public int getRawTextDirection() {
27214         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
27215     }
27216 
27217     /**
27218      * Set the text direction.
27219      *
27220      * @param textDirection the direction to set. Should be one of:
27221      *
27222      * {@link #TEXT_DIRECTION_INHERIT},
27223      * {@link #TEXT_DIRECTION_FIRST_STRONG},
27224      * {@link #TEXT_DIRECTION_ANY_RTL},
27225      * {@link #TEXT_DIRECTION_LTR},
27226      * {@link #TEXT_DIRECTION_RTL},
27227      * {@link #TEXT_DIRECTION_LOCALE}
27228      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
27229      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
27230      *
27231      * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
27232      * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
27233      * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
27234      *
27235      * @attr ref android.R.styleable#View_textDirection
27236      */
setTextDirection(int textDirection)27237     public void setTextDirection(int textDirection) {
27238         if (getRawTextDirection() != textDirection) {
27239             // Reset the current text direction and the resolved one
27240             mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
27241             resetResolvedTextDirection();
27242             // Set the new text direction
27243             mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
27244             // Do resolution
27245             resolveTextDirection();
27246             // Notify change
27247             onRtlPropertiesChanged(getLayoutDirection());
27248             // Refresh
27249             requestLayout();
27250             invalidate(true);
27251         }
27252     }
27253 
27254     /**
27255      * Return the resolved text direction.
27256      *
27257      * @return the resolved text direction. Returns one of:
27258      *
27259      * {@link #TEXT_DIRECTION_FIRST_STRONG},
27260      * {@link #TEXT_DIRECTION_ANY_RTL},
27261      * {@link #TEXT_DIRECTION_LTR},
27262      * {@link #TEXT_DIRECTION_RTL},
27263      * {@link #TEXT_DIRECTION_LOCALE},
27264      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
27265      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
27266      *
27267      * @attr ref android.R.styleable#View_textDirection
27268      */
27269     @ViewDebug.ExportedProperty(category = "text", mapping = {
27270             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
27271             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
27272             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
27273             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
27274             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
27275             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
27276             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
27277             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
27278     })
27279     @InspectableProperty(hasAttributeId = false, enumMapping = {
27280             @EnumEntry(value = TEXT_DIRECTION_LOCALE, name = "locale"),
27281             @EnumEntry(value = TEXT_DIRECTION_ANY_RTL, name = "anyRtl"),
27282             @EnumEntry(value = TEXT_DIRECTION_LTR, name = "ltr"),
27283             @EnumEntry(value = TEXT_DIRECTION_RTL, name = "rtl"),
27284             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG, name = "firstStrong"),
27285             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_LTR, name = "firstStrongLtr"),
27286             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_RTL, name = "firstStrongRtl"),
27287     })
getTextDirection()27288     public int getTextDirection() {
27289         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
27290     }
27291 
27292     /**
27293      * Resolve the text direction.
27294      *
27295      * @return true if resolution has been done, false otherwise.
27296      *
27297      * @hide
27298      */
resolveTextDirection()27299     public boolean resolveTextDirection() {
27300         // Reset any previous text direction resolution
27301         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
27302 
27303         if (hasRtlSupport()) {
27304             // Set resolved text direction flag depending on text direction flag
27305             final int textDirection = getRawTextDirection();
27306             switch(textDirection) {
27307                 case TEXT_DIRECTION_INHERIT:
27308                     if (!canResolveTextDirection()) {
27309                         // We cannot do the resolution if there is no parent, so use the default one
27310                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
27311                         // Resolution will need to happen again later
27312                         return false;
27313                     }
27314 
27315                     // Parent has not yet resolved, so we still return the default
27316                     try {
27317                         if (!mParent.isTextDirectionResolved()) {
27318                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
27319                             // Resolution will need to happen again later
27320                             return false;
27321                         }
27322                     } catch (AbstractMethodError e) {
27323                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
27324                                 " does not fully implement ViewParent", e);
27325                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
27326                                 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
27327                         return true;
27328                     }
27329 
27330                     // Set current resolved direction to the same value as the parent's one
27331                     int parentResolvedDirection;
27332                     try {
27333                         parentResolvedDirection = mParent.getTextDirection();
27334                     } catch (AbstractMethodError e) {
27335                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
27336                                 " does not fully implement ViewParent", e);
27337                         parentResolvedDirection = TEXT_DIRECTION_LTR;
27338                     }
27339                     switch (parentResolvedDirection) {
27340                         case TEXT_DIRECTION_FIRST_STRONG:
27341                         case TEXT_DIRECTION_ANY_RTL:
27342                         case TEXT_DIRECTION_LTR:
27343                         case TEXT_DIRECTION_RTL:
27344                         case TEXT_DIRECTION_LOCALE:
27345                         case TEXT_DIRECTION_FIRST_STRONG_LTR:
27346                         case TEXT_DIRECTION_FIRST_STRONG_RTL:
27347                             mPrivateFlags2 |=
27348                                     (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
27349                             break;
27350                         default:
27351                             // Default resolved direction is "first strong" heuristic
27352                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
27353                     }
27354                     break;
27355                 case TEXT_DIRECTION_FIRST_STRONG:
27356                 case TEXT_DIRECTION_ANY_RTL:
27357                 case TEXT_DIRECTION_LTR:
27358                 case TEXT_DIRECTION_RTL:
27359                 case TEXT_DIRECTION_LOCALE:
27360                 case TEXT_DIRECTION_FIRST_STRONG_LTR:
27361                 case TEXT_DIRECTION_FIRST_STRONG_RTL:
27362                     // Resolved direction is the same as text direction
27363                     mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
27364                     break;
27365                 default:
27366                     // Default resolved direction is "first strong" heuristic
27367                     mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
27368             }
27369         } else {
27370             // Default resolved direction is "first strong" heuristic
27371             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
27372         }
27373 
27374         // Set to resolved
27375         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
27376         return true;
27377     }
27378 
27379     /**
27380      * Check if text direction resolution can be done.
27381      *
27382      * @return true if text direction resolution can be done otherwise return false.
27383      */
canResolveTextDirection()27384     public boolean canResolveTextDirection() {
27385         switch (getRawTextDirection()) {
27386             case TEXT_DIRECTION_INHERIT:
27387                 if (mParent != null) {
27388                     try {
27389                         return mParent.canResolveTextDirection();
27390                     } catch (AbstractMethodError e) {
27391                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
27392                                 " does not fully implement ViewParent", e);
27393                     }
27394                 }
27395                 return false;
27396 
27397             default:
27398                 return true;
27399         }
27400     }
27401 
27402     /**
27403      * Reset resolved text direction. Text direction will be resolved during a call to
27404      * {@link #onMeasure(int, int)}.
27405      *
27406      * @hide
27407      */
27408     @TestApi
resetResolvedTextDirection()27409     public void resetResolvedTextDirection() {
27410         // Reset any previous text direction resolution
27411         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
27412         // Set to default value
27413         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
27414     }
27415 
27416     /**
27417      * @return true if text direction is inherited.
27418      *
27419      * @hide
27420      */
isTextDirectionInherited()27421     public boolean isTextDirectionInherited() {
27422         return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
27423     }
27424 
27425     /**
27426      * @return true if text direction is resolved.
27427      */
isTextDirectionResolved()27428     public boolean isTextDirectionResolved() {
27429         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
27430     }
27431 
27432     /**
27433      * Return the value specifying the text alignment or policy that was set with
27434      * {@link #setTextAlignment(int)}.
27435      *
27436      * @return the defined text alignment. It can be one of:
27437      *
27438      * {@link #TEXT_ALIGNMENT_INHERIT},
27439      * {@link #TEXT_ALIGNMENT_GRAVITY},
27440      * {@link #TEXT_ALIGNMENT_CENTER},
27441      * {@link #TEXT_ALIGNMENT_TEXT_START},
27442      * {@link #TEXT_ALIGNMENT_TEXT_END},
27443      * {@link #TEXT_ALIGNMENT_VIEW_START},
27444      * {@link #TEXT_ALIGNMENT_VIEW_END}
27445      *
27446      * @attr ref android.R.styleable#View_textAlignment
27447      *
27448      * @hide
27449      */
27450     @ViewDebug.ExportedProperty(category = "text", mapping = {
27451             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
27452             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
27453             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
27454             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
27455             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
27456             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
27457             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
27458     })
27459     @InspectableProperty(hasAttributeId = false, enumMapping = {
27460             @EnumEntry(value = TEXT_ALIGNMENT_INHERIT, name = "inherit"),
27461             @EnumEntry(value = TEXT_ALIGNMENT_GRAVITY, name = "gravity"),
27462             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_START, name = "textStart"),
27463             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_END, name = "textEnd"),
27464             @EnumEntry(value = TEXT_ALIGNMENT_CENTER, name = "center"),
27465             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_START, name = "viewStart"),
27466             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_END, name = "viewEnd")
27467     })
27468     @TextAlignment
27469     @UnsupportedAppUsage
getRawTextAlignment()27470     public int getRawTextAlignment() {
27471         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
27472     }
27473 
27474     /**
27475      * Set the text alignment.
27476      *
27477      * @param textAlignment The text alignment to set. Should be one of
27478      *
27479      * {@link #TEXT_ALIGNMENT_INHERIT},
27480      * {@link #TEXT_ALIGNMENT_GRAVITY},
27481      * {@link #TEXT_ALIGNMENT_CENTER},
27482      * {@link #TEXT_ALIGNMENT_TEXT_START},
27483      * {@link #TEXT_ALIGNMENT_TEXT_END},
27484      * {@link #TEXT_ALIGNMENT_VIEW_START},
27485      * {@link #TEXT_ALIGNMENT_VIEW_END}
27486      *
27487      * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
27488      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
27489      * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
27490      *
27491      * @attr ref android.R.styleable#View_textAlignment
27492      */
setTextAlignment(@extAlignment int textAlignment)27493     public void setTextAlignment(@TextAlignment int textAlignment) {
27494         if (textAlignment != getRawTextAlignment()) {
27495             // Reset the current and resolved text alignment
27496             mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
27497             resetResolvedTextAlignment();
27498             // Set the new text alignment
27499             mPrivateFlags2 |=
27500                     ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
27501             // Do resolution
27502             resolveTextAlignment();
27503             // Notify change
27504             onRtlPropertiesChanged(getLayoutDirection());
27505             // Refresh
27506             requestLayout();
27507             invalidate(true);
27508         }
27509     }
27510 
27511     /**
27512      * Return the resolved text alignment.
27513      *
27514      * @return the resolved text alignment. Returns one of:
27515      *
27516      * {@link #TEXT_ALIGNMENT_GRAVITY},
27517      * {@link #TEXT_ALIGNMENT_CENTER},
27518      * {@link #TEXT_ALIGNMENT_TEXT_START},
27519      * {@link #TEXT_ALIGNMENT_TEXT_END},
27520      * {@link #TEXT_ALIGNMENT_VIEW_START},
27521      * {@link #TEXT_ALIGNMENT_VIEW_END}
27522      *
27523      * @attr ref android.R.styleable#View_textAlignment
27524      */
27525     @ViewDebug.ExportedProperty(category = "text", mapping = {
27526             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
27527             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
27528             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
27529             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
27530             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
27531             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
27532             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
27533     })
27534     @InspectableProperty(enumMapping = {
27535             @EnumEntry(value = TEXT_ALIGNMENT_GRAVITY, name = "gravity"),
27536             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_START, name = "textStart"),
27537             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_END, name = "textEnd"),
27538             @EnumEntry(value = TEXT_ALIGNMENT_CENTER, name = "center"),
27539             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_START, name = "viewStart"),
27540             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_END, name = "viewEnd")
27541     })
27542     @TextAlignment
getTextAlignment()27543     public int getTextAlignment() {
27544         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
27545                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
27546     }
27547 
27548     /**
27549      * Resolve the text alignment.
27550      *
27551      * @return true if resolution has been done, false otherwise.
27552      *
27553      * @hide
27554      */
resolveTextAlignment()27555     public boolean resolveTextAlignment() {
27556         // Reset any previous text alignment resolution
27557         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
27558 
27559         if (hasRtlSupport()) {
27560             // Set resolved text alignment flag depending on text alignment flag
27561             final int textAlignment = getRawTextAlignment();
27562             switch (textAlignment) {
27563                 case TEXT_ALIGNMENT_INHERIT:
27564                     // Check if we can resolve the text alignment
27565                     if (!canResolveTextAlignment()) {
27566                         // We cannot do the resolution if there is no parent so use the default
27567                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
27568                         // Resolution will need to happen again later
27569                         return false;
27570                     }
27571 
27572                     // Parent has not yet resolved, so we still return the default
27573                     try {
27574                         if (!mParent.isTextAlignmentResolved()) {
27575                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
27576                             // Resolution will need to happen again later
27577                             return false;
27578                         }
27579                     } catch (AbstractMethodError e) {
27580                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
27581                                 " does not fully implement ViewParent", e);
27582                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
27583                                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
27584                         return true;
27585                     }
27586 
27587                     int parentResolvedTextAlignment;
27588                     try {
27589                         parentResolvedTextAlignment = mParent.getTextAlignment();
27590                     } catch (AbstractMethodError e) {
27591                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
27592                                 " does not fully implement ViewParent", e);
27593                         parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
27594                     }
27595                     switch (parentResolvedTextAlignment) {
27596                         case TEXT_ALIGNMENT_GRAVITY:
27597                         case TEXT_ALIGNMENT_TEXT_START:
27598                         case TEXT_ALIGNMENT_TEXT_END:
27599                         case TEXT_ALIGNMENT_CENTER:
27600                         case TEXT_ALIGNMENT_VIEW_START:
27601                         case TEXT_ALIGNMENT_VIEW_END:
27602                             // Resolved text alignment is the same as the parent resolved
27603                             // text alignment
27604                             mPrivateFlags2 |=
27605                                     (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
27606                             break;
27607                         default:
27608                             // Use default resolved text alignment
27609                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
27610                     }
27611                     break;
27612                 case TEXT_ALIGNMENT_GRAVITY:
27613                 case TEXT_ALIGNMENT_TEXT_START:
27614                 case TEXT_ALIGNMENT_TEXT_END:
27615                 case TEXT_ALIGNMENT_CENTER:
27616                 case TEXT_ALIGNMENT_VIEW_START:
27617                 case TEXT_ALIGNMENT_VIEW_END:
27618                     // Resolved text alignment is the same as text alignment
27619                     mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
27620                     break;
27621                 default:
27622                     // Use default resolved text alignment
27623                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
27624             }
27625         } else {
27626             // Use default resolved text alignment
27627             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
27628         }
27629 
27630         // Set the resolved
27631         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
27632         return true;
27633     }
27634 
27635     /**
27636      * Check if text alignment resolution can be done.
27637      *
27638      * @return true if text alignment resolution can be done otherwise return false.
27639      */
canResolveTextAlignment()27640     public boolean canResolveTextAlignment() {
27641         switch (getRawTextAlignment()) {
27642             case TEXT_DIRECTION_INHERIT:
27643                 if (mParent != null) {
27644                     try {
27645                         return mParent.canResolveTextAlignment();
27646                     } catch (AbstractMethodError e) {
27647                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
27648                                 " does not fully implement ViewParent", e);
27649                     }
27650                 }
27651                 return false;
27652 
27653             default:
27654                 return true;
27655         }
27656     }
27657 
27658     /**
27659      * Reset resolved text alignment. Text alignment will be resolved during a call to
27660      * {@link #onMeasure(int, int)}.
27661      *
27662      * @hide
27663      */
27664     @TestApi
resetResolvedTextAlignment()27665     public void resetResolvedTextAlignment() {
27666         // Reset any previous text alignment resolution
27667         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
27668         // Set to default
27669         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
27670     }
27671 
27672     /**
27673      * @return true if text alignment is inherited.
27674      *
27675      * @hide
27676      */
isTextAlignmentInherited()27677     public boolean isTextAlignmentInherited() {
27678         return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
27679     }
27680 
27681     /**
27682      * @return true if text alignment is resolved.
27683      */
isTextAlignmentResolved()27684     public boolean isTextAlignmentResolved() {
27685         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
27686     }
27687 
27688     /**
27689      * Generate a value suitable for use in {@link #setId(int)}.
27690      * This value will not collide with ID values generated at build time by aapt for R.id.
27691      *
27692      * @return a generated ID value
27693      */
generateViewId()27694     public static int generateViewId() {
27695         for (;;) {
27696             final int result = sNextGeneratedId.get();
27697             // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
27698             int newValue = result + 1;
27699             if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
27700             if (sNextGeneratedId.compareAndSet(result, newValue)) {
27701                 return result;
27702             }
27703         }
27704     }
27705 
isViewIdGenerated(int id)27706     private static boolean isViewIdGenerated(int id) {
27707         return (id & 0xFF000000) == 0 && (id & 0x00FFFFFF) != 0;
27708     }
27709 
27710     /**
27711      * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
27712      * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
27713      *                           a normal View or a ViewGroup with
27714      *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
27715      * @hide
27716      */
captureTransitioningViews(List<View> transitioningViews)27717     public void captureTransitioningViews(List<View> transitioningViews) {
27718         if (getVisibility() == View.VISIBLE) {
27719             transitioningViews.add(this);
27720         }
27721     }
27722 
27723     /**
27724      * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
27725      * @param namedElements Will contain all Views in the hierarchy having a transitionName.
27726      * @hide
27727      */
findNamedViews(Map<String, View> namedElements)27728     public void findNamedViews(Map<String, View> namedElements) {
27729         if (getVisibility() == VISIBLE || mGhostView != null) {
27730             String transitionName = getTransitionName();
27731             if (transitionName != null) {
27732                 namedElements.put(transitionName, this);
27733             }
27734         }
27735     }
27736 
27737     /**
27738      * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
27739      * The default implementation does not care the location or event types, but some subclasses
27740      * may use it (such as WebViews).
27741      * @param event The MotionEvent from a mouse
27742      * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
27743      *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
27744      * @see PointerIcon
27745      */
onResolvePointerIcon(MotionEvent event, int pointerIndex)27746     public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
27747         final float x = event.getX(pointerIndex);
27748         final float y = event.getY(pointerIndex);
27749         if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
27750             return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
27751         }
27752         return mPointerIcon;
27753     }
27754 
27755     /**
27756      * Set the pointer icon for the current view.
27757      * Passing {@code null} will restore the pointer icon to its default value.
27758      * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
27759      */
setPointerIcon(PointerIcon pointerIcon)27760     public void setPointerIcon(PointerIcon pointerIcon) {
27761         mPointerIcon = pointerIcon;
27762         if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
27763             return;
27764         }
27765         try {
27766             mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
27767         } catch (RemoteException e) {
27768         }
27769     }
27770 
27771     /**
27772      * Gets the pointer icon for the current view.
27773      */
27774     @InspectableProperty
getPointerIcon()27775     public PointerIcon getPointerIcon() {
27776         return mPointerIcon;
27777     }
27778 
27779     /**
27780      * Checks pointer capture status.
27781      *
27782      * @return true if the view has pointer capture.
27783      * @see #requestPointerCapture()
27784      * @see #hasPointerCapture()
27785      */
hasPointerCapture()27786     public boolean hasPointerCapture() {
27787         final ViewRootImpl viewRootImpl = getViewRootImpl();
27788         if (viewRootImpl == null) {
27789             return false;
27790         }
27791         return viewRootImpl.hasPointerCapture();
27792     }
27793 
27794     /**
27795      * Requests pointer capture mode.
27796      * <p>
27797      * When the window has pointer capture, the mouse pointer icon will disappear and will not
27798      * change its position. Further mouse will be dispatched with the source
27799      * {@link InputDevice#SOURCE_MOUSE_RELATIVE}, and relative position changes will be available
27800      * through {@link MotionEvent#getX} and {@link MotionEvent#getY}. Non-mouse events
27801      * (touchscreens, or stylus) will not be affected.
27802      * <p>
27803      * If the window already has pointer capture, this call does nothing.
27804      * <p>
27805      * The capture may be released through {@link #releasePointerCapture()}, or will be lost
27806      * automatically when the window loses focus.
27807      *
27808      * @see #releasePointerCapture()
27809      * @see #hasPointerCapture()
27810      */
requestPointerCapture()27811     public void requestPointerCapture() {
27812         final ViewRootImpl viewRootImpl = getViewRootImpl();
27813         if (viewRootImpl != null) {
27814             viewRootImpl.requestPointerCapture(true);
27815         }
27816     }
27817 
27818 
27819     /**
27820      * Releases the pointer capture.
27821      * <p>
27822      * If the window does not have pointer capture, this call will do nothing.
27823      * @see #requestPointerCapture()
27824      * @see #hasPointerCapture()
27825      */
releasePointerCapture()27826     public void releasePointerCapture() {
27827         final ViewRootImpl viewRootImpl = getViewRootImpl();
27828         if (viewRootImpl != null) {
27829             viewRootImpl.requestPointerCapture(false);
27830         }
27831     }
27832 
27833     /**
27834      * Called when the window has just acquired or lost pointer capture.
27835      *
27836      * @param hasCapture True if the view now has pointerCapture, false otherwise.
27837      */
27838     @CallSuper
onPointerCaptureChange(boolean hasCapture)27839     public void onPointerCaptureChange(boolean hasCapture) {
27840     }
27841 
27842     /**
27843      * @see #onPointerCaptureChange
27844      */
dispatchPointerCaptureChanged(boolean hasCapture)27845     public void dispatchPointerCaptureChanged(boolean hasCapture) {
27846         onPointerCaptureChange(hasCapture);
27847     }
27848 
27849     /**
27850      * Implement this method to handle captured pointer events
27851      *
27852      * @param event The captured pointer event.
27853      * @return True if the event was handled, false otherwise.
27854      * @see #requestPointerCapture()
27855      */
onCapturedPointerEvent(MotionEvent event)27856     public boolean onCapturedPointerEvent(MotionEvent event) {
27857         return false;
27858     }
27859 
27860     /**
27861      * Interface definition for a callback to be invoked when a captured pointer event
27862      * is being dispatched this view. The callback will be invoked before the event is
27863      * given to the view.
27864      */
27865     public interface OnCapturedPointerListener {
27866         /**
27867          * Called when a captured pointer event is dispatched to a view.
27868          * @param view The view this event has been dispatched to.
27869          * @param event The captured event.
27870          * @return True if the listener has consumed the event, false otherwise.
27871          */
27872         boolean onCapturedPointer(View view, MotionEvent event);
27873     }
27874 
27875     /**
27876      * Set a listener to receive callbacks when the pointer capture state of a view changes.
27877      * @param l  The {@link OnCapturedPointerListener} to receive callbacks.
27878      */
setOnCapturedPointerListener(OnCapturedPointerListener l)27879     public void setOnCapturedPointerListener(OnCapturedPointerListener l) {
27880         getListenerInfo().mOnCapturedPointerListener = l;
27881     }
27882 
27883     // Properties
27884     //
27885     /**
27886      * A Property wrapper around the <code>alpha</code> functionality handled by the
27887      * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
27888      */
27889     public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
27890         @Override
27891         public void setValue(View object, float value) {
27892             object.setAlpha(value);
27893         }
27894 
27895         @Override
27896         public Float get(View object) {
27897             return object.getAlpha();
27898         }
27899     };
27900 
27901     /**
27902      * A Property wrapper around the <code>translationX</code> functionality handled by the
27903      * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
27904      */
27905     public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
27906         @Override
27907         public void setValue(View object, float value) {
27908             object.setTranslationX(value);
27909         }
27910 
27911                 @Override
27912         public Float get(View object) {
27913             return object.getTranslationX();
27914         }
27915     };
27916 
27917     /**
27918      * A Property wrapper around the <code>translationY</code> functionality handled by the
27919      * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
27920      */
27921     public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
27922         @Override
27923         public void setValue(View object, float value) {
27924             object.setTranslationY(value);
27925         }
27926 
27927         @Override
27928         public Float get(View object) {
27929             return object.getTranslationY();
27930         }
27931     };
27932 
27933     /**
27934      * A Property wrapper around the <code>translationZ</code> functionality handled by the
27935      * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
27936      */
27937     public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
27938         @Override
27939         public void setValue(View object, float value) {
27940             object.setTranslationZ(value);
27941         }
27942 
27943         @Override
27944         public Float get(View object) {
27945             return object.getTranslationZ();
27946         }
27947     };
27948 
27949     /**
27950      * A Property wrapper around the <code>x</code> functionality handled by the
27951      * {@link View#setX(float)} and {@link View#getX()} methods.
27952      */
27953     public static final Property<View, Float> X = new FloatProperty<View>("x") {
27954         @Override
27955         public void setValue(View object, float value) {
27956             object.setX(value);
27957         }
27958 
27959         @Override
27960         public Float get(View object) {
27961             return object.getX();
27962         }
27963     };
27964 
27965     /**
27966      * A Property wrapper around the <code>y</code> functionality handled by the
27967      * {@link View#setY(float)} and {@link View#getY()} methods.
27968      */
27969     public static final Property<View, Float> Y = new FloatProperty<View>("y") {
27970         @Override
27971         public void setValue(View object, float value) {
27972             object.setY(value);
27973         }
27974 
27975         @Override
27976         public Float get(View object) {
27977             return object.getY();
27978         }
27979     };
27980 
27981     /**
27982      * A Property wrapper around the <code>z</code> functionality handled by the
27983      * {@link View#setZ(float)} and {@link View#getZ()} methods.
27984      */
27985     public static final Property<View, Float> Z = new FloatProperty<View>("z") {
27986         @Override
27987         public void setValue(View object, float value) {
27988             object.setZ(value);
27989         }
27990 
27991         @Override
27992         public Float get(View object) {
27993             return object.getZ();
27994         }
27995     };
27996 
27997     /**
27998      * A Property wrapper around the <code>rotation</code> functionality handled by the
27999      * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
28000      */
28001     public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
28002         @Override
28003         public void setValue(View object, float value) {
28004             object.setRotation(value);
28005         }
28006 
28007         @Override
28008         public Float get(View object) {
28009             return object.getRotation();
28010         }
28011     };
28012 
28013     /**
28014      * A Property wrapper around the <code>rotationX</code> functionality handled by the
28015      * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
28016      */
28017     public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
28018         @Override
28019         public void setValue(View object, float value) {
28020             object.setRotationX(value);
28021         }
28022 
28023         @Override
28024         public Float get(View object) {
28025             return object.getRotationX();
28026         }
28027     };
28028 
28029     /**
28030      * A Property wrapper around the <code>rotationY</code> functionality handled by the
28031      * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
28032      */
28033     public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
28034         @Override
28035         public void setValue(View object, float value) {
28036             object.setRotationY(value);
28037         }
28038 
28039         @Override
28040         public Float get(View object) {
28041             return object.getRotationY();
28042         }
28043     };
28044 
28045     /**
28046      * A Property wrapper around the <code>scaleX</code> functionality handled by the
28047      * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
28048      */
28049     public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
28050         @Override
28051         public void setValue(View object, float value) {
28052             object.setScaleX(value);
28053         }
28054 
28055         @Override
28056         public Float get(View object) {
28057             return object.getScaleX();
28058         }
28059     };
28060 
28061     /**
28062      * A Property wrapper around the <code>scaleY</code> functionality handled by the
28063      * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
28064      */
28065     public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
28066         @Override
28067         public void setValue(View object, float value) {
28068             object.setScaleY(value);
28069         }
28070 
28071         @Override
28072         public Float get(View object) {
28073             return object.getScaleY();
28074         }
28075     };
28076 
28077     /**
28078      * A MeasureSpec encapsulates the layout requirements passed from parent to child.
28079      * Each MeasureSpec represents a requirement for either the width or the height.
28080      * A MeasureSpec is comprised of a size and a mode. There are three possible
28081      * modes:
28082      * <dl>
28083      * <dt>UNSPECIFIED</dt>
28084      * <dd>
28085      * The parent has not imposed any constraint on the child. It can be whatever size
28086      * it wants.
28087      * </dd>
28088      *
28089      * <dt>EXACTLY</dt>
28090      * <dd>
28091      * The parent has determined an exact size for the child. The child is going to be
28092      * given those bounds regardless of how big it wants to be.
28093      * </dd>
28094      *
28095      * <dt>AT_MOST</dt>
28096      * <dd>
28097      * The child can be as large as it wants up to the specified size.
28098      * </dd>
28099      * </dl>
28100      *
28101      * MeasureSpecs are implemented as ints to reduce object allocation. This class
28102      * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
28103      */
28104     public static class MeasureSpec {
28105         private static final int MODE_SHIFT = 30;
28106         private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
28107 
28108         /** @hide */
28109         @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
28110         @Retention(RetentionPolicy.SOURCE)
28111         public @interface MeasureSpecMode {}
28112 
28113         /**
28114          * Measure specification mode: The parent has not imposed any constraint
28115          * on the child. It can be whatever size it wants.
28116          */
28117         public static final int UNSPECIFIED = 0 << MODE_SHIFT;
28118 
28119         /**
28120          * Measure specification mode: The parent has determined an exact size
28121          * for the child. The child is going to be given those bounds regardless
28122          * of how big it wants to be.
28123          */
28124         public static final int EXACTLY     = 1 << MODE_SHIFT;
28125 
28126         /**
28127          * Measure specification mode: The child can be as large as it wants up
28128          * to the specified size.
28129          */
28130         public static final int AT_MOST     = 2 << MODE_SHIFT;
28131 
28132         /**
28133          * Creates a measure specification based on the supplied size and mode.
28134          *
28135          * The mode must always be one of the following:
28136          * <ul>
28137          *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
28138          *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
28139          *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
28140          * </ul>
28141          *
28142          * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
28143          * implementation was such that the order of arguments did not matter
28144          * and overflow in either value could impact the resulting MeasureSpec.
28145          * {@link android.widget.RelativeLayout} was affected by this bug.
28146          * Apps targeting API levels greater than 17 will get the fixed, more strict
28147          * behavior.</p>
28148          *
28149          * @param size the size of the measure specification
28150          * @param mode the mode of the measure specification
28151          * @return the measure specification based on size and mode
28152          */
makeMeasureSpec(@ntRangefrom = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size, @MeasureSpecMode int mode)28153         public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
28154                                           @MeasureSpecMode int mode) {
28155             if (sUseBrokenMakeMeasureSpec) {
28156                 return size + mode;
28157             } else {
28158                 return (size & ~MODE_MASK) | (mode & MODE_MASK);
28159             }
28160         }
28161 
28162         /**
28163          * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
28164          * will automatically get a size of 0. Older apps expect this.
28165          *
28166          * @hide internal use only for compatibility with system widgets and older apps
28167          */
28168         @UnsupportedAppUsage
makeSafeMeasureSpec(int size, int mode)28169         public static int makeSafeMeasureSpec(int size, int mode) {
28170             if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
28171                 return 0;
28172             }
28173             return makeMeasureSpec(size, mode);
28174         }
28175 
28176         /**
28177          * Extracts the mode from the supplied measure specification.
28178          *
28179          * @param measureSpec the measure specification to extract the mode from
28180          * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
28181          *         {@link android.view.View.MeasureSpec#AT_MOST} or
28182          *         {@link android.view.View.MeasureSpec#EXACTLY}
28183          */
28184         @MeasureSpecMode
getMode(int measureSpec)28185         public static int getMode(int measureSpec) {
28186             //noinspection ResourceType
28187             return (measureSpec & MODE_MASK);
28188         }
28189 
28190         /**
28191          * Extracts the size from the supplied measure specification.
28192          *
28193          * @param measureSpec the measure specification to extract the size from
28194          * @return the size in pixels defined in the supplied measure specification
28195          */
getSize(int measureSpec)28196         public static int getSize(int measureSpec) {
28197             return (measureSpec & ~MODE_MASK);
28198         }
28199 
adjust(int measureSpec, int delta)28200         static int adjust(int measureSpec, int delta) {
28201             final int mode = getMode(measureSpec);
28202             int size = getSize(measureSpec);
28203             if (mode == UNSPECIFIED) {
28204                 // No need to adjust size for UNSPECIFIED mode.
28205                 return makeMeasureSpec(size, UNSPECIFIED);
28206             }
28207             size += delta;
28208             if (size < 0) {
28209                 Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
28210                         ") spec: " + toString(measureSpec) + " delta: " + delta);
28211                 size = 0;
28212             }
28213             return makeMeasureSpec(size, mode);
28214         }
28215 
28216         /**
28217          * Returns a String representation of the specified measure
28218          * specification.
28219          *
28220          * @param measureSpec the measure specification to convert to a String
28221          * @return a String with the following format: "MeasureSpec: MODE SIZE"
28222          */
toString(int measureSpec)28223         public static String toString(int measureSpec) {
28224             int mode = getMode(measureSpec);
28225             int size = getSize(measureSpec);
28226 
28227             StringBuilder sb = new StringBuilder("MeasureSpec: ");
28228 
28229             if (mode == UNSPECIFIED)
28230                 sb.append("UNSPECIFIED ");
28231             else if (mode == EXACTLY)
28232                 sb.append("EXACTLY ");
28233             else if (mode == AT_MOST)
28234                 sb.append("AT_MOST ");
28235             else
28236                 sb.append(mode).append(" ");
28237 
28238             sb.append(size);
28239             return sb.toString();
28240         }
28241     }
28242 
28243     private final class CheckForLongPress implements Runnable {
28244         private int mOriginalWindowAttachCount;
28245         private float mX;
28246         private float mY;
28247         private boolean mOriginalPressedState;
28248         /**
28249          * The classification of the long click being checked: one of the
28250          * FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__* constants.
28251          */
28252         private int mClassification;
28253 
28254         @UnsupportedAppUsage
CheckForLongPress()28255         private CheckForLongPress() {
28256         }
28257 
28258         @Override
run()28259         public void run() {
28260             if ((mOriginalPressedState == isPressed()) && (mParent != null)
28261                     && mOriginalWindowAttachCount == mWindowAttachCount) {
28262                 recordGestureClassification(mClassification);
28263                 if (performLongClick(mX, mY)) {
28264                     mHasPerformedLongPress = true;
28265                 }
28266             }
28267         }
28268 
setAnchor(float x, float y)28269         public void setAnchor(float x, float y) {
28270             mX = x;
28271             mY = y;
28272         }
28273 
rememberWindowAttachCount()28274         public void rememberWindowAttachCount() {
28275             mOriginalWindowAttachCount = mWindowAttachCount;
28276         }
28277 
rememberPressedState()28278         public void rememberPressedState() {
28279             mOriginalPressedState = isPressed();
28280         }
28281 
setClassification(int classification)28282         public void setClassification(int classification) {
28283             mClassification = classification;
28284         }
28285     }
28286 
28287     private final class CheckForTap implements Runnable {
28288         public float x;
28289         public float y;
28290 
28291         @Override
run()28292         public void run() {
28293             mPrivateFlags &= ~PFLAG_PREPRESSED;
28294             setPressed(true, x, y);
28295             final long delay =
28296                     ViewConfiguration.getLongPressTimeout() - ViewConfiguration.getTapTimeout();
28297             checkForLongClick(delay, x, y, TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
28298         }
28299     }
28300 
28301     private final class PerformClick implements Runnable {
28302         @Override
run()28303         public void run() {
28304             recordGestureClassification(TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP);
28305             performClickInternal();
28306         }
28307     }
28308 
28309     /** Records a classification for the current event stream. */
recordGestureClassification(int classification)28310     private void recordGestureClassification(int classification) {
28311         if (classification == TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION) {
28312             return;
28313         }
28314         // To avoid negatively impacting View performance, the latency and displacement metrics
28315         // are omitted.
28316         FrameworkStatsLog.write(FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED, getClass().getName(),
28317                 classification);
28318     }
28319 
28320     /**
28321      * This method returns a ViewPropertyAnimator object, which can be used to animate
28322      * specific properties on this View.
28323      *
28324      * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
28325      */
animate()28326     public ViewPropertyAnimator animate() {
28327         if (mAnimator == null) {
28328             mAnimator = new ViewPropertyAnimator(this);
28329         }
28330         return mAnimator;
28331     }
28332 
28333     /**
28334      * Sets the name of the View to be used to identify Views in Transitions.
28335      * Names should be unique in the View hierarchy.
28336      *
28337      * @param transitionName The name of the View to uniquely identify it for Transitions.
28338      */
setTransitionName(String transitionName)28339     public final void setTransitionName(String transitionName) {
28340         mTransitionName = transitionName;
28341     }
28342 
28343     /**
28344      * Returns the name of the View to be used to identify Views in Transitions.
28345      * Names should be unique in the View hierarchy.
28346      *
28347      * <p>This returns null if the View has not been given a name.</p>
28348      *
28349      * @return The name used of the View to be used to identify Views in Transitions or null
28350      * if no name has been given.
28351      */
28352     @ViewDebug.ExportedProperty
28353     @InspectableProperty
getTransitionName()28354     public String getTransitionName() {
28355         return mTransitionName;
28356     }
28357 
28358     /**
28359      * @hide
28360      */
requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId)28361     public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
28362         // Do nothing.
28363     }
28364 
28365     /**
28366      * Interface definition for a callback to be invoked when a hardware key event is
28367      * dispatched to this view. The callback will be invoked before the key event is
28368      * given to the view. This is only useful for hardware keyboards; a software input
28369      * method has no obligation to trigger this listener.
28370      */
28371     public interface OnKeyListener {
28372         /**
28373          * Called when a hardware key is dispatched to a view. This allows listeners to
28374          * get a chance to respond before the target view.
28375          * <p>Key presses in software keyboards will generally NOT trigger this method,
28376          * although some may elect to do so in some situations. Do not assume a
28377          * software input method has to be key-based; even if it is, it may use key presses
28378          * in a different way than you expect, so there is no way to reliably catch soft
28379          * input key presses.
28380          *
28381          * @param v The view the key has been dispatched to.
28382          * @param keyCode The code for the physical key that was pressed
28383          * @param event The KeyEvent object containing full information about
28384          *        the event.
28385          * @return True if the listener has consumed the event, false otherwise.
28386          */
28387         boolean onKey(View v, int keyCode, KeyEvent event);
28388     }
28389 
28390     /**
28391      * Interface definition for a callback to be invoked when a hardware key event hasn't
28392      * been handled by the view hierarchy.
28393      */
28394     public interface OnUnhandledKeyEventListener {
28395         /**
28396          * Called when a hardware key is dispatched to a view after being unhandled during normal
28397          * {@link KeyEvent} dispatch.
28398          *
28399          * @param v The view the key has been dispatched to.
28400          * @param event The KeyEvent object containing information about the event.
28401          * @return {@code true} if the listener has consumed the event, {@code false} otherwise.
28402          */
28403         boolean onUnhandledKeyEvent(View v, KeyEvent event);
28404     }
28405 
28406     /**
28407      * Interface definition for a callback to be invoked when a touch event is
28408      * dispatched to this view. The callback will be invoked before the touch
28409      * event is given to the view.
28410      */
28411     public interface OnTouchListener {
28412         /**
28413          * Called when a touch event is dispatched to a view. This allows listeners to
28414          * get a chance to respond before the target view.
28415          *
28416          * @param v The view the touch event has been dispatched to.
28417          * @param event The MotionEvent object containing full information about
28418          *        the event.
28419          * @return True if the listener has consumed the event, false otherwise.
28420          */
28421         boolean onTouch(View v, MotionEvent event);
28422     }
28423 
28424     /**
28425      * Interface definition for a callback to be invoked when a hover event is
28426      * dispatched to this view. The callback will be invoked before the hover
28427      * event is given to the view.
28428      */
28429     public interface OnHoverListener {
28430         /**
28431          * Called when a hover event is dispatched to a view. This allows listeners to
28432          * get a chance to respond before the target view.
28433          *
28434          * @param v The view the hover event has been dispatched to.
28435          * @param event The MotionEvent object containing full information about
28436          *        the event.
28437          * @return True if the listener has consumed the event, false otherwise.
28438          */
28439         boolean onHover(View v, MotionEvent event);
28440     }
28441 
28442     /**
28443      * Interface definition for a callback to be invoked when a generic motion event is
28444      * dispatched to this view. The callback will be invoked before the generic motion
28445      * event is given to the view.
28446      */
28447     public interface OnGenericMotionListener {
28448         /**
28449          * Called when a generic motion event is dispatched to a view. This allows listeners to
28450          * get a chance to respond before the target view.
28451          *
28452          * @param v The view the generic motion event has been dispatched to.
28453          * @param event The MotionEvent object containing full information about
28454          *        the event.
28455          * @return True if the listener has consumed the event, false otherwise.
28456          */
28457         boolean onGenericMotion(View v, MotionEvent event);
28458     }
28459 
28460     /**
28461      * Interface definition for a callback to be invoked when a view has been clicked and held.
28462      */
28463     public interface OnLongClickListener {
28464         /**
28465          * Called when a view has been clicked and held.
28466          *
28467          * @param v The view that was clicked and held.
28468          *
28469          * @return true if the callback consumed the long click, false otherwise.
28470          */
28471         boolean onLongClick(View v);
28472     }
28473 
28474     /**
28475      * Interface definition for a callback to be invoked when a drag is being dispatched
28476      * to this view.  The callback will be invoked before the hosting view's own
28477      * onDrag(event) method.  If the listener wants to fall back to the hosting view's
28478      * onDrag(event) behavior, it should return 'false' from this callback.
28479      *
28480      * <div class="special reference">
28481      * <h3>Developer Guides</h3>
28482      * <p>For a guide to implementing drag and drop features, read the
28483      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
28484      * </div>
28485      */
28486     public interface OnDragListener {
28487         /**
28488          * Called when a drag event is dispatched to a view. This allows listeners
28489          * to get a chance to override base View behavior.
28490          *
28491          * @param v The View that received the drag event.
28492          * @param event The {@link android.view.DragEvent} object for the drag event.
28493          * @return {@code true} if the drag event was handled successfully, or {@code false}
28494          * if the drag event was not handled. Note that {@code false} will trigger the View
28495          * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
28496          */
28497         boolean onDrag(View v, DragEvent event);
28498     }
28499 
28500     /**
28501      * Interface definition for a callback to be invoked when the focus state of
28502      * a view changed.
28503      */
28504     public interface OnFocusChangeListener {
28505         /**
28506          * Called when the focus state of a view has changed.
28507          *
28508          * @param v The view whose state has changed.
28509          * @param hasFocus The new focus state of v.
28510          */
28511         void onFocusChange(View v, boolean hasFocus);
28512     }
28513 
28514     /**
28515      * Interface definition for a callback to be invoked when a view is clicked.
28516      */
28517     public interface OnClickListener {
28518         /**
28519          * Called when a view has been clicked.
28520          *
28521          * @param v The view that was clicked.
28522          */
28523         void onClick(View v);
28524     }
28525 
28526     /**
28527      * Interface definition for a callback to be invoked when a view is context clicked.
28528      */
28529     public interface OnContextClickListener {
28530         /**
28531          * Called when a view is context clicked.
28532          *
28533          * @param v The view that has been context clicked.
28534          * @return true if the callback consumed the context click, false otherwise.
28535          */
28536         boolean onContextClick(View v);
28537     }
28538 
28539     /**
28540      * Interface definition for a callback to be invoked when the context menu
28541      * for this view is being built.
28542      */
28543     public interface OnCreateContextMenuListener {
28544         /**
28545          * Called when the context menu for this view is being built. It is not
28546          * safe to hold onto the menu after this method returns.
28547          *
28548          * @param menu The context menu that is being built
28549          * @param v The view for which the context menu is being built
28550          * @param menuInfo Extra information about the item for which the
28551          *            context menu should be shown. This information will vary
28552          *            depending on the class of v.
28553          */
28554         void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
28555     }
28556 
28557     /**
28558      * Interface definition for a callback to be invoked when the status bar changes
28559      * visibility.  This reports <strong>global</strong> changes to the system UI
28560      * state, not what the application is requesting.
28561      *
28562      * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
28563      *
28564      * @deprecated Use {@link WindowInsets#isVisible(int)} to find out about system bar visibilities
28565      * by setting a {@link OnApplyWindowInsetsListener} on this view.
28566      */
28567     @Deprecated
28568     public interface OnSystemUiVisibilityChangeListener {
28569         /**
28570          * Called when the status bar changes visibility because of a call to
28571          * {@link View#setSystemUiVisibility(int)}.
28572          *
28573          * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
28574          * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
28575          * This tells you the <strong>global</strong> state of these UI visibility
28576          * flags, not what your app is currently applying.
28577          */
28578         public void onSystemUiVisibilityChange(int visibility);
28579     }
28580 
28581     /**
28582      * Interface definition for a callback to be invoked when this view is attached
28583      * or detached from its window.
28584      */
28585     public interface OnAttachStateChangeListener {
28586         /**
28587          * Called when the view is attached to a window.
28588          * @param v The view that was attached
28589          */
28590         public void onViewAttachedToWindow(View v);
28591         /**
28592          * Called when the view is detached from a window.
28593          * @param v The view that was detached
28594          */
28595         public void onViewDetachedFromWindow(View v);
28596     }
28597 
28598     /**
28599      * Listener for applying window insets on a view in a custom way.
28600      *
28601      * <p>Apps may choose to implement this interface if they want to apply custom policy
28602      * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
28603      * is set, its
28604      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
28605      * method will be called instead of the View's own
28606      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
28607      * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
28608      * the View's normal behavior as part of its own.</p>
28609      */
28610     public interface OnApplyWindowInsetsListener {
28611         /**
28612          * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
28613          * on a View, this listener method will be called instead of the view's own
28614          * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
28615          *
28616          * @param v The view applying window insets
28617          * @param insets The insets to apply
28618          * @return The insets supplied, minus any insets that were consumed
28619          */
28620         public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
28621     }
28622 
28623     private final class UnsetPressedState implements Runnable {
28624         @Override
run()28625         public void run() {
28626             setPressed(false);
28627         }
28628     }
28629 
28630     /**
28631      * When a view becomes invisible checks if autofill considers the view invisible too. This
28632      * happens after the regular removal operation to make sure the operation is finished by the
28633      * time this is called.
28634      */
28635     private static class VisibilityChangeForAutofillHandler extends Handler {
28636         private final AutofillManager mAfm;
28637         private final View mView;
28638 
VisibilityChangeForAutofillHandler(@onNull AutofillManager afm, @NonNull View view)28639         private VisibilityChangeForAutofillHandler(@NonNull AutofillManager afm,
28640                 @NonNull View view) {
28641             mAfm = afm;
28642             mView = view;
28643         }
28644 
28645         @Override
handleMessage(Message msg)28646         public void handleMessage(Message msg) {
28647             mAfm.notifyViewVisibilityChanged(mView, mView.isShown());
28648         }
28649     }
28650 
28651     /**
28652      * Base class for derived classes that want to save and restore their own
28653      * state in {@link android.view.View#onSaveInstanceState()}.
28654      */
28655     public static class BaseSavedState extends AbsSavedState {
28656         static final int START_ACTIVITY_REQUESTED_WHO_SAVED = 0b1;
28657         static final int IS_AUTOFILLED = 0b10;
28658         static final int AUTOFILL_ID = 0b100;
28659 
28660         // Flags that describe what data in this state is valid
28661         int mSavedData;
28662         String mStartActivityRequestWhoSaved;
28663         boolean mIsAutofilled;
28664         boolean mHideHighlight;
28665         int mAutofillViewId;
28666 
28667         /**
28668          * Constructor used when reading from a parcel. Reads the state of the superclass.
28669          *
28670          * @param source parcel to read from
28671          */
BaseSavedState(Parcel source)28672         public BaseSavedState(Parcel source) {
28673             this(source, null);
28674         }
28675 
28676         /**
28677          * Constructor used when reading from a parcel using a given class loader.
28678          * Reads the state of the superclass.
28679          *
28680          * @param source parcel to read from
28681          * @param loader ClassLoader to use for reading
28682          */
BaseSavedState(Parcel source, ClassLoader loader)28683         public BaseSavedState(Parcel source, ClassLoader loader) {
28684             super(source, loader);
28685             mSavedData = source.readInt();
28686             mStartActivityRequestWhoSaved = source.readString();
28687             mIsAutofilled = source.readBoolean();
28688             mHideHighlight = source.readBoolean();
28689             mAutofillViewId = source.readInt();
28690         }
28691 
28692         /**
28693          * Constructor called by derived classes when creating their SavedState objects
28694          *
28695          * @param superState The state of the superclass of this view
28696          */
BaseSavedState(Parcelable superState)28697         public BaseSavedState(Parcelable superState) {
28698             super(superState);
28699         }
28700 
28701         @Override
writeToParcel(Parcel out, int flags)28702         public void writeToParcel(Parcel out, int flags) {
28703             super.writeToParcel(out, flags);
28704 
28705             out.writeInt(mSavedData);
28706             out.writeString(mStartActivityRequestWhoSaved);
28707             out.writeBoolean(mIsAutofilled);
28708             out.writeBoolean(mHideHighlight);
28709             out.writeInt(mAutofillViewId);
28710         }
28711 
28712         public static final @android.annotation.NonNull Parcelable.Creator<BaseSavedState> CREATOR
28713                 = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
28714             @Override
28715             public BaseSavedState createFromParcel(Parcel in) {
28716                 return new BaseSavedState(in);
28717             }
28718 
28719             @Override
28720             public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
28721                 return new BaseSavedState(in, loader);
28722             }
28723 
28724             @Override
28725             public BaseSavedState[] newArray(int size) {
28726                 return new BaseSavedState[size];
28727             }
28728         };
28729     }
28730 
28731     /**
28732      * A set of information given to a view when it is attached to its parent
28733      * window.
28734      */
28735     final static class AttachInfo {
28736 
28737         interface Callbacks {
28738             void playSoundEffect(int effectId);
28739             boolean performHapticFeedback(int effectId, boolean always);
28740         }
28741 
28742         /**
28743          * InvalidateInfo is used to post invalidate(int, int, int, int) messages
28744          * to a Handler. This class contains the target (View) to invalidate and
28745          * the coordinates of the dirty rectangle.
28746          *
28747          * For performance purposes, this class also implements a pool of up to
28748          * POOL_LIMIT objects that get reused. This reduces memory allocations
28749          * whenever possible.
28750          */
28751         static class InvalidateInfo {
28752 
28753             @UnsupportedAppUsage
InvalidateInfo()28754             InvalidateInfo() {
28755             }
28756 
28757             private static final int POOL_LIMIT = 10;
28758 
28759             private static final SynchronizedPool<InvalidateInfo> sPool =
28760                     new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
28761 
28762             @UnsupportedAppUsage
28763             View target;
28764 
28765             @UnsupportedAppUsage
28766             int left;
28767             @UnsupportedAppUsage
28768             int top;
28769             @UnsupportedAppUsage
28770             int right;
28771             @UnsupportedAppUsage
28772             int bottom;
28773 
obtain()28774             public static InvalidateInfo obtain() {
28775                 InvalidateInfo instance = sPool.acquire();
28776                 return (instance != null) ? instance : new InvalidateInfo();
28777             }
28778 
recycle()28779             public void recycle() {
28780                 target = null;
28781                 sPool.release(this);
28782             }
28783         }
28784 
28785         @UnsupportedAppUsage
28786         final IWindowSession mSession;
28787 
28788         @UnsupportedAppUsage
28789         final IWindow mWindow;
28790 
28791         final IBinder mWindowToken;
28792 
28793         Display mDisplay;
28794 
28795         final Callbacks mRootCallbacks;
28796 
28797         IWindowId mIWindowId;
28798         WindowId mWindowId;
28799 
28800         /**
28801          * The top view of the hierarchy.
28802          */
28803         View mRootView;
28804 
28805         IBinder mPanelParentWindowToken;
28806 
28807         boolean mHardwareAccelerated;
28808         boolean mHardwareAccelerationRequested;
28809         ThreadedRenderer mThreadedRenderer;
28810         List<RenderNode> mPendingAnimatingRenderNodes;
28811 
28812         /**
28813          * The state of the display to which the window is attached, as reported
28814          * by {@link Display#getState()}.  Note that the display state constants
28815          * declared by {@link Display} do not exactly line up with the screen state
28816          * constants declared by {@link View} (there are more display states than
28817          * screen states).
28818          */
28819         @UnsupportedAppUsage
28820         int mDisplayState = Display.STATE_UNKNOWN;
28821 
28822         /**
28823          * Scale factor used by the compatibility mode
28824          */
28825         @UnsupportedAppUsage
28826         float mApplicationScale;
28827 
28828         /**
28829          * Indicates whether the application is in compatibility mode
28830          */
28831         @UnsupportedAppUsage
28832         boolean mScalingRequired;
28833 
28834         /**
28835          * Left position of this view's window
28836          */
28837         int mWindowLeft;
28838 
28839         /**
28840          * Top position of this view's window
28841          */
28842         int mWindowTop;
28843 
28844         /**
28845          * Indicates whether views need to use 32-bit drawing caches
28846          */
28847         boolean mUse32BitDrawingCache;
28848 
28849         /**
28850          * For windows that are full-screen but using insets to layout inside
28851          * of the screen decorations, these are the current insets for the
28852          * content of the window.
28853          */
28854         @UnsupportedAppUsage(maxTargetSdk = VERSION_CODES.Q,
28855                 publicAlternatives = "Use {@link WindowInsets#getInsets(int)}")
28856         final Rect mContentInsets = new Rect();
28857 
28858         /**
28859          * For windows that are full-screen but using insets to layout inside
28860          * of the screen decorations, these are the current insets for the
28861          * actual visible parts of the window.
28862          */
28863         @UnsupportedAppUsage(maxTargetSdk = VERSION_CODES.Q,
28864                 publicAlternatives = "Use {@link WindowInsets#getInsets(int)}")
28865         final Rect mVisibleInsets = new Rect();
28866 
28867         /**
28868          * For windows that are full-screen but using insets to layout inside
28869          * of the screen decorations, these are the current insets for the
28870          * stable system windows.
28871          */
28872         @UnsupportedAppUsage(maxTargetSdk = VERSION_CODES.Q,
28873                 publicAlternatives = "Use {@link WindowInsets#getInsets(int)}")
28874         final Rect mStableInsets = new Rect();
28875 
28876         /**
28877          * Current caption insets to the display coordinate.
28878          */
28879         final Rect mCaptionInsets = new Rect();
28880 
28881         final DisplayCutout.ParcelableWrapper mDisplayCutout =
28882                 new DisplayCutout.ParcelableWrapper(DisplayCutout.NO_CUTOUT);
28883 
28884         /**
28885          * In multi-window we force show the system bars. Because we don't want that the surface
28886          * size changes in this mode, we instead have a flag whether the system bars sizes should
28887          * always be consumed, so the app is treated like there are no virtual system bars at all.
28888          */
28889         boolean mAlwaysConsumeSystemBars;
28890 
28891         /**
28892          * The internal insets given by this window.  This value is
28893          * supplied by the client (through
28894          * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
28895          * be given to the window manager when changed to be used in laying
28896          * out windows behind it.
28897          */
28898         @UnsupportedAppUsage
28899         final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
28900                 = new ViewTreeObserver.InternalInsetsInfo();
28901 
28902         /**
28903          * Set to true when mGivenInternalInsets is non-empty.
28904          */
28905         boolean mHasNonEmptyGivenInternalInsets;
28906 
28907         /**
28908          * All views in the window's hierarchy that serve as scroll containers,
28909          * used to determine if the window can be resized or must be panned
28910          * to adjust for a soft input area.
28911          */
28912         @UnsupportedAppUsage
28913         final ArrayList<View> mScrollContainers = new ArrayList<View>();
28914 
28915         @UnsupportedAppUsage
28916         final KeyEvent.DispatcherState mKeyDispatchState
28917                 = new KeyEvent.DispatcherState();
28918 
28919         /**
28920          * Indicates whether the view's window currently has the focus.
28921          */
28922         @UnsupportedAppUsage
28923         boolean mHasWindowFocus;
28924 
28925         /**
28926          * The current visibility of the window.
28927          */
28928         int mWindowVisibility;
28929 
28930         /**
28931          * Indicates the time at which drawing started to occur.
28932          */
28933         @UnsupportedAppUsage
28934         long mDrawingTime;
28935 
28936         /**
28937          * Indicates whether the view's window is currently in touch mode.
28938          */
28939         @UnsupportedAppUsage
28940         boolean mInTouchMode;
28941 
28942         /**
28943          * Indicates whether the view has requested unbuffered input dispatching for the current
28944          * event stream.
28945          */
28946         boolean mUnbufferedDispatchRequested;
28947 
28948         /**
28949          * Indicates that ViewAncestor should trigger a global layout change
28950          * the next time it performs a traversal
28951          */
28952         @UnsupportedAppUsage
28953         boolean mRecomputeGlobalAttributes;
28954 
28955         /**
28956          * Always report new attributes at next traversal.
28957          */
28958         boolean mForceReportNewAttributes;
28959 
28960         /**
28961          * Set during a traveral if any views want to keep the screen on.
28962          */
28963         @UnsupportedAppUsage
28964         boolean mKeepScreenOn;
28965 
28966         /**
28967          * Set during a traveral if the light center needs to be updated.
28968          */
28969         boolean mNeedsUpdateLightCenter;
28970 
28971         /**
28972          * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
28973          */
28974         int mSystemUiVisibility;
28975 
28976         /**
28977          * Hack to force certain system UI visibility flags to be cleared.
28978          */
28979         int mDisabledSystemUiVisibility;
28980 
28981         /**
28982          * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
28983          * attached.
28984          */
28985         boolean mHasSystemUiListeners;
28986 
28987         /**
28988          * Set if the visibility of any views has changed.
28989          */
28990         @UnsupportedAppUsage
28991         boolean mViewVisibilityChanged;
28992 
28993         /**
28994          * Set to true if a view has been scrolled.
28995          */
28996         @UnsupportedAppUsage
28997         boolean mViewScrollChanged;
28998 
28999         /**
29000          * Set to true if a pointer event is currently being handled.
29001          */
29002         boolean mHandlingPointerEvent;
29003 
29004         /**
29005          * The offset of this view's window when it's on an embedded display that is re-parented
29006          * to another window.
29007          */
29008         final Point mLocationInParentDisplay = new Point();
29009 
29010         /**
29011          * The screen matrix of this view when it's on a {@link SurfaceControlViewHost} that is
29012          * embedded within a SurfaceView.
29013          */
29014         Matrix mScreenMatrixInEmbeddedHierarchy;
29015 
29016         /**
29017          * Global to the view hierarchy used as a temporary for dealing with
29018          * x/y points in the transparent region computations.
29019          */
29020         final int[] mTransparentLocation = new int[2];
29021 
29022         /**
29023          * Global to the view hierarchy used as a temporary for dealing with
29024          * x/y points in the ViewGroup.invalidateChild implementation.
29025          */
29026         final int[] mInvalidateChildLocation = new int[2];
29027 
29028         /**
29029          * Global to the view hierarchy used as a temporary for dealing with
29030          * computing absolute on-screen location.
29031          */
29032         final int[] mTmpLocation = new int[2];
29033 
29034         /**
29035          * Global to the view hierarchy used as a temporary for dealing with
29036          * x/y location when view is transformed.
29037          */
29038         final float[] mTmpTransformLocation = new float[2];
29039 
29040         /**
29041          * The view tree observer used to dispatch global events like
29042          * layout, pre-draw, touch mode change, etc.
29043          */
29044         @UnsupportedAppUsage
29045         final ViewTreeObserver mTreeObserver;
29046 
29047         /**
29048          * A Canvas used by the view hierarchy to perform bitmap caching.
29049          */
29050         Canvas mCanvas;
29051 
29052         /**
29053          * The view root impl.
29054          */
29055         final ViewRootImpl mViewRootImpl;
29056 
29057         /**
29058          * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
29059          * handler can be used to pump events in the UI events queue.
29060          */
29061         @UnsupportedAppUsage
29062         final Handler mHandler;
29063 
29064         /**
29065          * Temporary for use in computing invalidate rectangles while
29066          * calling up the hierarchy.
29067          */
29068         final Rect mTmpInvalRect = new Rect();
29069 
29070         /**
29071          * Temporary for use in computing hit areas with transformed views
29072          */
29073         final RectF mTmpTransformRect = new RectF();
29074 
29075         /**
29076          * Temporary for use in computing hit areas with transformed views
29077          */
29078         final RectF mTmpTransformRect1 = new RectF();
29079 
29080         /**
29081          * Temporary list of rectanges.
29082          */
29083         final List<RectF> mTmpRectList = new ArrayList<>();
29084 
29085         /**
29086          * Temporary for use in transforming invalidation rect
29087          */
29088         final Matrix mTmpMatrix = new Matrix();
29089 
29090         /**
29091          * Temporary for use in transforming invalidation rect
29092          */
29093         final Transformation mTmpTransformation = new Transformation();
29094 
29095         /**
29096          * Temporary for use in querying outlines from OutlineProviders
29097          */
29098         final Outline mTmpOutline = new Outline();
29099 
29100         /**
29101          * Temporary list for use in collecting focusable descendents of a view.
29102          */
29103         final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
29104 
29105         /**
29106          * The id of the window for accessibility purposes.
29107          */
29108         int mAccessibilityWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
29109 
29110         /**
29111          * Flags related to accessibility processing.
29112          *
29113          * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
29114          * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
29115          */
29116         int mAccessibilityFetchFlags;
29117 
29118         /**
29119          * The drawable for highlighting accessibility focus.
29120          */
29121         Drawable mAccessibilityFocusDrawable;
29122 
29123         /**
29124          * The drawable for highlighting autofilled views.
29125          *
29126          * @see #isAutofilled()
29127          */
29128         Drawable mAutofilledDrawable;
29129 
29130         /**
29131          * Show where the margins, bounds and layout bounds are for each view.
29132          */
29133         boolean mDebugLayout = DisplayProperties.debug_layout().orElse(false);
29134 
29135         /**
29136          * Point used to compute visible regions.
29137          */
29138         final Point mPoint = new Point();
29139 
29140         /**
29141          * Used to track which View originated a requestLayout() call, used when
29142          * requestLayout() is called during layout.
29143          */
29144         View mViewRequestingLayout;
29145 
29146         /**
29147          * Used to track the identity of the current drag operation.
29148          */
29149         IBinder mDragToken;
29150 
29151         /**
29152          * The drag shadow surface for the current drag operation.
29153          */
29154         public Surface mDragSurface;
29155 
29156 
29157         /**
29158          * The view that currently has a tooltip displayed.
29159          */
29160         View mTooltipHost;
29161 
29162         /**
29163          * The initial structure has been reported so the view is ready to report updates.
29164          */
29165         boolean mReadyForContentCaptureUpdates;
29166 
29167         /**
29168          * Map(keyed by session) of content capture events that need to be notified after the view
29169          * hierarchy is traversed: value is either the view itself for appearead events, or its
29170          * autofill id for disappeared.
29171          */
29172         SparseArray<ArrayList<Object>> mContentCaptureEvents;
29173 
29174         /**
29175          * Cached reference to the {@link ContentCaptureManager}.
29176          */
29177         ContentCaptureManager mContentCaptureManager;
29178 
29179         /**
29180          * Listener used to fit content on window level.
29181          */
29182         OnContentApplyWindowInsetsListener mContentOnApplyWindowInsetsListener;
29183 
29184         /**
29185          * The leash token of this view's parent when it's in an embedded hierarchy that is
29186          * re-parented to another window.
29187          */
29188         IBinder mLeashedParentToken;
29189 
29190         /**
29191          * The accessibility view id of this view's parent when it's in an embedded
29192          * hierarchy that is re-parented to another window.
29193          */
29194         int mLeashedParentAccessibilityViewId;
29195 
29196         /**
29197          *
29198          */
29199         ScrollCaptureInternal mScrollCaptureInternal;
29200 
29201         /**
29202          * Creates a new set of attachment information with the specified
29203          * events handler and thread.
29204          *
29205          * @param handler the events handler the view must use
29206          */
AttachInfo(IWindowSession session, IWindow window, Display display, ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer, Context context)29207         AttachInfo(IWindowSession session, IWindow window, Display display,
29208                 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer,
29209                 Context context) {
29210             mSession = session;
29211             mWindow = window;
29212             mWindowToken = window.asBinder();
29213             mDisplay = display;
29214             mViewRootImpl = viewRootImpl;
29215             mHandler = handler;
29216             mRootCallbacks = effectPlayer;
29217             mTreeObserver = new ViewTreeObserver(context);
29218         }
29219 
29220         @Nullable
getContentCaptureManager(@onNull Context context)29221         ContentCaptureManager getContentCaptureManager(@NonNull Context context) {
29222             if (mContentCaptureManager != null) {
29223                 return mContentCaptureManager;
29224             }
29225             mContentCaptureManager = context.getSystemService(ContentCaptureManager.class);
29226             return mContentCaptureManager;
29227         }
29228 
delayNotifyContentCaptureInsetsEvent(@onNull Insets insets)29229         void delayNotifyContentCaptureInsetsEvent(@NonNull Insets insets) {
29230             if (mContentCaptureManager == null) {
29231                 return;
29232             }
29233 
29234             ArrayList<Object> events = ensureEvents(
29235                         mContentCaptureManager.getMainContentCaptureSession());
29236             events.add(insets);
29237         }
29238 
delayNotifyContentCaptureEvent(@onNull ContentCaptureSession session, @NonNull View view, boolean appeared)29239         private void delayNotifyContentCaptureEvent(@NonNull ContentCaptureSession session,
29240                 @NonNull View view, boolean appeared) {
29241             ArrayList<Object> events = ensureEvents(session);
29242             events.add(appeared ? view : view.getAutofillId());
29243         }
29244 
29245         @NonNull
ensureEvents(@onNull ContentCaptureSession session)29246         private ArrayList<Object> ensureEvents(@NonNull ContentCaptureSession session) {
29247             if (mContentCaptureEvents == null) {
29248                 // Most of the time there will be just one session, so intial capacity is 1
29249                 mContentCaptureEvents = new SparseArray<>(1);
29250             }
29251             int sessionId = session.getId();
29252             // TODO: life would be much easier if we provided a MultiMap implementation somwhere...
29253             ArrayList<Object> events = mContentCaptureEvents.get(sessionId);
29254             if (events == null) {
29255                 events = new ArrayList<>();
29256                 mContentCaptureEvents.put(sessionId, events);
29257             }
29258 
29259             return events;
29260         }
29261 
29262         @Nullable
getScrollCaptureInternal()29263         ScrollCaptureInternal getScrollCaptureInternal() {
29264             if (mScrollCaptureInternal != null) {
29265                 mScrollCaptureInternal = new ScrollCaptureInternal();
29266             }
29267             return mScrollCaptureInternal;
29268         }
29269     }
29270 
29271     /**
29272      * <p>ScrollabilityCache holds various fields used by a View when scrolling
29273      * is supported. This avoids keeping too many unused fields in most
29274      * instances of View.</p>
29275      */
29276     private static class ScrollabilityCache implements Runnable {
29277 
29278         /**
29279          * Scrollbars are not visible
29280          */
29281         public static final int OFF = 0;
29282 
29283         /**
29284          * Scrollbars are visible
29285          */
29286         public static final int ON = 1;
29287 
29288         /**
29289          * Scrollbars are fading away
29290          */
29291         public static final int FADING = 2;
29292 
29293         public boolean fadeScrollBars;
29294 
29295         public int fadingEdgeLength;
29296         public int scrollBarDefaultDelayBeforeFade;
29297         public int scrollBarFadeDuration;
29298 
29299         public int scrollBarSize;
29300         public int scrollBarMinTouchTarget;
29301         @UnsupportedAppUsage
29302         public ScrollBarDrawable scrollBar;
29303         public float[] interpolatorValues;
29304         @UnsupportedAppUsage
29305         public View host;
29306 
29307         public final Paint paint;
29308         public final Matrix matrix;
29309         public Shader shader;
29310 
29311         public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
29312 
29313         private static final float[] OPAQUE = { 255 };
29314         private static final float[] TRANSPARENT = { 0.0f };
29315 
29316         /**
29317          * When fading should start. This time moves into the future every time
29318          * a new scroll happens. Measured based on SystemClock.uptimeMillis()
29319          */
29320         public long fadeStartTime;
29321 
29322 
29323         /**
29324          * The current state of the scrollbars: ON, OFF, or FADING
29325          */
29326         @UnsupportedAppUsage
29327         public int state = OFF;
29328 
29329         private int mLastColor;
29330 
29331         public final Rect mScrollBarBounds = new Rect();
29332         public final Rect mScrollBarTouchBounds = new Rect();
29333 
29334         public static final int NOT_DRAGGING = 0;
29335         public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
29336         public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
29337         public int mScrollBarDraggingState = NOT_DRAGGING;
29338 
29339         public float mScrollBarDraggingPos = 0;
29340 
ScrollabilityCache(ViewConfiguration configuration, View host)29341         public ScrollabilityCache(ViewConfiguration configuration, View host) {
29342             fadingEdgeLength = configuration.getScaledFadingEdgeLength();
29343             scrollBarSize = configuration.getScaledScrollBarSize();
29344             scrollBarMinTouchTarget = configuration.getScaledMinScrollbarTouchTarget();
29345             scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
29346             scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
29347 
29348             paint = new Paint();
29349             matrix = new Matrix();
29350             // use use a height of 1, and then wack the matrix each time we
29351             // actually use it.
29352             shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
29353             paint.setShader(shader);
29354             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
29355 
29356             this.host = host;
29357         }
29358 
setFadeColor(int color)29359         public void setFadeColor(int color) {
29360             if (color != mLastColor) {
29361                 mLastColor = color;
29362 
29363                 if (color != 0) {
29364                     shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
29365                             color & 0x00FFFFFF, Shader.TileMode.CLAMP);
29366                     paint.setShader(shader);
29367                     // Restore the default transfer mode (src_over)
29368                     paint.setXfermode(null);
29369                 } else {
29370                     shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
29371                     paint.setShader(shader);
29372                     paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
29373                 }
29374             }
29375         }
29376 
run()29377         public void run() {
29378             long now = AnimationUtils.currentAnimationTimeMillis();
29379             if (now >= fadeStartTime) {
29380 
29381                 // the animation fades the scrollbars out by changing
29382                 // the opacity (alpha) from fully opaque to fully
29383                 // transparent
29384                 int nextFrame = (int) now;
29385                 int framesCount = 0;
29386 
29387                 Interpolator interpolator = scrollBarInterpolator;
29388 
29389                 // Start opaque
29390                 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
29391 
29392                 // End transparent
29393                 nextFrame += scrollBarFadeDuration;
29394                 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
29395 
29396                 state = FADING;
29397 
29398                 // Kick off the fade animation
29399                 host.invalidate(true);
29400             }
29401         }
29402     }
29403 
29404     private class SendAccessibilityEventThrottle implements Runnable {
29405         public volatile boolean mIsPending;
29406         private AccessibilityEvent mAccessibilityEvent;
29407 
post(AccessibilityEvent accessibilityEvent)29408         public void post(AccessibilityEvent accessibilityEvent) {
29409             updateWithAccessibilityEvent(accessibilityEvent);
29410             if (!mIsPending) {
29411                 mIsPending = true;
29412                 postDelayed(this,
29413                         ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
29414             }
29415         }
29416 
29417         @Override
run()29418         public void run() {
29419             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
29420                 requestParentSendAccessibilityEvent(mAccessibilityEvent);
29421             }
29422             reset();
29423         }
29424 
updateWithAccessibilityEvent(AccessibilityEvent accessibilityEvent)29425         public void updateWithAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
29426             mAccessibilityEvent = accessibilityEvent;
29427         }
29428 
reset()29429         public void reset() {
29430             mIsPending = false;
29431             mAccessibilityEvent = null;
29432         }
29433 
29434     }
29435 
29436     /**
29437      * Resuable callback for sending
29438      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
29439      */
29440     private class SendViewScrolledAccessibilityEvent extends SendAccessibilityEventThrottle {
29441         public int mDeltaX;
29442         public int mDeltaY;
29443 
29444         @Override
updateWithAccessibilityEvent(AccessibilityEvent accessibilityEvent)29445         public void updateWithAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
29446             super.updateWithAccessibilityEvent(accessibilityEvent);
29447             mDeltaX += accessibilityEvent.getScrollDeltaX();
29448             mDeltaY += accessibilityEvent.getScrollDeltaY();
29449             accessibilityEvent.setScrollDeltaX(mDeltaX);
29450             accessibilityEvent.setScrollDeltaY(mDeltaY);
29451         }
29452 
29453         @Override
reset()29454         public void reset() {
29455             super.reset();
29456             mDeltaX = 0;
29457             mDeltaY = 0;
29458         }
29459     }
29460     /**
29461      * Remove the pending callback for sending a throttled accessibility event.
29462      */
29463     @UnsupportedAppUsage
cancel(@ullable SendAccessibilityEventThrottle callback)29464     private void cancel(@Nullable SendAccessibilityEventThrottle callback) {
29465         if (callback == null || !callback.mIsPending) return;
29466         removeCallbacks(callback);
29467         callback.reset();
29468     }
29469 
29470     /**
29471      * <p>
29472      * This class represents a delegate that can be registered in a {@link View}
29473      * to enhance accessibility support via composition rather via inheritance.
29474      * It is specifically targeted to widget developers that extend basic View
29475      * classes i.e. classes in package android.view, that would like their
29476      * applications to be backwards compatible.
29477      * </p>
29478      * <div class="special reference">
29479      * <h3>Developer Guides</h3>
29480      * <p>For more information about making applications accessible, read the
29481      * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
29482      * developer guide.</p>
29483      * </div>
29484      * <p>
29485      * A scenario in which a developer would like to use an accessibility delegate
29486      * is overriding a method introduced in a later API version than the minimal API
29487      * version supported by the application. For example, the method
29488      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
29489      * in API version 4 when the accessibility APIs were first introduced. If a
29490      * developer would like their application to run on API version 4 devices (assuming
29491      * all other APIs used by the application are version 4 or lower) and take advantage
29492      * of this method, instead of overriding the method which would break the application's
29493      * backwards compatibility, they can override the corresponding method in this
29494      * delegate and register the delegate in the target View if the API version of
29495      * the system is high enough, i.e. the API version is the same as or higher than the API
29496      * version that introduced
29497      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
29498      * </p>
29499      * <p>
29500      * Here is an example implementation:
29501      * </p>
29502      * <code><pre><p>
29503      * if (Build.VERSION.SDK_INT >= 14) {
29504      *     // If the API version is equal of higher than the version in
29505      *     // which onInitializeAccessibilityNodeInfo was introduced we
29506      *     // register a delegate with a customized implementation.
29507      *     View view = findViewById(R.id.view_id);
29508      *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
29509      *         public void onInitializeAccessibilityNodeInfo(View host,
29510      *                 AccessibilityNodeInfo info) {
29511      *             // Let the default implementation populate the info.
29512      *             super.onInitializeAccessibilityNodeInfo(host, info);
29513      *             // Set some other information.
29514      *             info.setEnabled(host.isEnabled());
29515      *         }
29516      *     });
29517      * }
29518      * </code></pre></p>
29519      * <p>
29520      * This delegate contains methods that correspond to the accessibility methods
29521      * in View. If a delegate has been specified the implementation in View hands
29522      * off handling to the corresponding method in this delegate. The default
29523      * implementation the delegate methods behaves exactly as the corresponding
29524      * method in View for the case of no accessibility delegate been set. Hence,
29525      * to customize the behavior of a View method, clients can override only the
29526      * corresponding delegate method without altering the behavior of the rest
29527      * accessibility related methods of the host view.
29528      * </p>
29529      * <p>
29530      * <strong>Note:</strong> On platform versions prior to
29531      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
29532      * views in the {@code android.widget.*} package are called <i>before</i>
29533      * host methods. This prevents certain properties such as class name from
29534      * being modified by overriding
29535      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
29536      * as any changes will be overwritten by the host class.
29537      * <p>
29538      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
29539      * methods are called <i>after</i> host methods, which all properties to be
29540      * modified without being overwritten by the host class.
29541      */
29542     public static class AccessibilityDelegate {
29543 
29544         /**
29545          * Sends an accessibility event of the given type. If accessibility is not
29546          * enabled this method has no effect.
29547          * <p>
29548          * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
29549          *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
29550          * been set.
29551          * </p>
29552          *
29553          * @param host The View hosting the delegate.
29554          * @param eventType The type of the event to send.
29555          *
29556          * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
29557          */
sendAccessibilityEvent(View host, int eventType)29558         public void sendAccessibilityEvent(View host, int eventType) {
29559             host.sendAccessibilityEventInternal(eventType);
29560         }
29561 
29562         /**
29563          * Performs the specified accessibility action on the view. For
29564          * possible accessibility actions look at {@link AccessibilityNodeInfo}.
29565          * <p>
29566          * The default implementation behaves as
29567          * {@link View#performAccessibilityAction(int, Bundle)
29568          *  View#performAccessibilityAction(int, Bundle)} for the case of
29569          *  no accessibility delegate been set.
29570          * </p>
29571          *
29572          * @param action The action to perform.
29573          * @return Whether the action was performed.
29574          *
29575          * @see View#performAccessibilityAction(int, Bundle)
29576          *      View#performAccessibilityAction(int, Bundle)
29577          */
performAccessibilityAction(View host, int action, Bundle args)29578         public boolean performAccessibilityAction(View host, int action, Bundle args) {
29579             return host.performAccessibilityActionInternal(action, args);
29580         }
29581 
29582         /**
29583          * Sends an accessibility event. This method behaves exactly as
29584          * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
29585          * empty {@link AccessibilityEvent} and does not perform a check whether
29586          * accessibility is enabled.
29587          * <p>
29588          * The default implementation behaves as
29589          * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
29590          *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
29591          * the case of no accessibility delegate been set.
29592          * </p>
29593          *
29594          * @param host The View hosting the delegate.
29595          * @param event The event to send.
29596          *
29597          * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
29598          *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
29599          */
sendAccessibilityEventUnchecked(View host, AccessibilityEvent event)29600         public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
29601             host.sendAccessibilityEventUncheckedInternal(event);
29602         }
29603 
29604         /**
29605          * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
29606          * to its children for adding their text content to the event.
29607          * <p>
29608          * The default implementation behaves as
29609          * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
29610          *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
29611          * the case of no accessibility delegate been set.
29612          * </p>
29613          *
29614          * @param host The View hosting the delegate.
29615          * @param event The event.
29616          * @return True if the event population was completed.
29617          *
29618          * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
29619          *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
29620          */
dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event)29621         public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
29622             return host.dispatchPopulateAccessibilityEventInternal(event);
29623         }
29624 
29625         /**
29626          * Gives a chance to the host View to populate the accessibility event with its
29627          * text content.
29628          * <p>
29629          * The default implementation behaves as
29630          * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
29631          *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
29632          * the case of no accessibility delegate been set.
29633          * </p>
29634          *
29635          * @param host The View hosting the delegate.
29636          * @param event The accessibility event which to populate.
29637          *
29638          * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
29639          *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
29640          */
onPopulateAccessibilityEvent(View host, AccessibilityEvent event)29641         public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
29642             host.onPopulateAccessibilityEventInternal(event);
29643         }
29644 
29645         /**
29646          * Initializes an {@link AccessibilityEvent} with information about the
29647          * the host View which is the event source.
29648          * <p>
29649          * The default implementation behaves as
29650          * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
29651          *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
29652          * the case of no accessibility delegate been set.
29653          * </p>
29654          *
29655          * @param host The View hosting the delegate.
29656          * @param event The event to initialize.
29657          *
29658          * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
29659          *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
29660          */
onInitializeAccessibilityEvent(View host, AccessibilityEvent event)29661         public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
29662             host.onInitializeAccessibilityEventInternal(event);
29663         }
29664 
29665         /**
29666          * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
29667          * <p>
29668          * The default implementation behaves as
29669          * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
29670          *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
29671          * the case of no accessibility delegate been set.
29672          * </p>
29673          *
29674          * @param host The View hosting the delegate.
29675          * @param info The instance to initialize.
29676          *
29677          * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
29678          *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
29679          */
onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info)29680         public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
29681             host.onInitializeAccessibilityNodeInfoInternal(info);
29682         }
29683 
29684         /**
29685          * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
29686          * additional data.
29687          * <p>
29688          * This method only needs to be implemented if the View offers to provide additional data.
29689          * </p>
29690          * <p>
29691          * The default implementation behaves as
29692          * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, String, Bundle)
29693          * for the case where no accessibility delegate is set.
29694          * </p>
29695          *
29696          * @param host The View hosting the delegate. Never {@code null}.
29697          * @param info The info to which to add the extra data. Never {@code null}.
29698          * @param extraDataKey A key specifying the type of extra data to add to the info. The
29699          *                     extra data should be added to the {@link Bundle} returned by
29700          *                     the info's {@link AccessibilityNodeInfo#getExtras} method.  Never
29701          *                     {@code null}.
29702          * @param arguments A {@link Bundle} holding any arguments relevant for this request.
29703          *                  May be {@code null} if the if the service provided no arguments.
29704          *
29705          * @see AccessibilityNodeInfo#setAvailableExtraData(List)
29706          */
addExtraDataToAccessibilityNodeInfo(@onNull View host, @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey, @Nullable Bundle arguments)29707         public void addExtraDataToAccessibilityNodeInfo(@NonNull View host,
29708                 @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
29709                 @Nullable Bundle arguments) {
29710             host.addExtraDataToAccessibilityNodeInfo(info, extraDataKey, arguments);
29711         }
29712 
29713         /**
29714          * Called when a child of the host View has requested sending an
29715          * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
29716          * to augment the event.
29717          * <p>
29718          * The default implementation behaves as
29719          * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
29720          *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
29721          * the case of no accessibility delegate been set.
29722          * </p>
29723          *
29724          * @param host The View hosting the delegate.
29725          * @param child The child which requests sending the event.
29726          * @param event The event to be sent.
29727          * @return True if the event should be sent
29728          *
29729          * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
29730          *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
29731          */
onRequestSendAccessibilityEvent(ViewGroup host, View child, AccessibilityEvent event)29732         public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
29733                 AccessibilityEvent event) {
29734             return host.onRequestSendAccessibilityEventInternal(child, event);
29735         }
29736 
29737         /**
29738          * Gets the provider for managing a virtual view hierarchy rooted at this View
29739          * and reported to {@link android.accessibilityservice.AccessibilityService}s
29740          * that explore the window content.
29741          * <p>
29742          * The default implementation behaves as
29743          * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
29744          * the case of no accessibility delegate been set.
29745          * </p>
29746          *
29747          * @return The provider.
29748          *
29749          * @see AccessibilityNodeProvider
29750          */
getAccessibilityNodeProvider(View host)29751         public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
29752             return null;
29753         }
29754 
29755         /**
29756          * Returns an {@link AccessibilityNodeInfo} representing the host view from the
29757          * point of view of an {@link android.accessibilityservice.AccessibilityService}.
29758          * This method is responsible for obtaining an accessibility node info from a
29759          * pool of reusable instances and calling
29760          * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
29761          * view to initialize the former.
29762          * <p>
29763          * <strong>Note:</strong> The client is responsible for recycling the obtained
29764          * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
29765          * creation.
29766          * </p>
29767          * <p>
29768          * The default implementation behaves as
29769          * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
29770          * the case of no accessibility delegate been set.
29771          * </p>
29772          * @return A populated {@link AccessibilityNodeInfo}.
29773          *
29774          * @see AccessibilityNodeInfo
29775          *
29776          * @hide
29777          */
29778         @UnsupportedAppUsage
createAccessibilityNodeInfo(View host)29779         public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
29780             return host.createAccessibilityNodeInfoInternal();
29781         }
29782     }
29783 
29784     private static class MatchIdPredicate implements Predicate<View> {
29785         public int mId;
29786 
29787         @Override
test(View view)29788         public boolean test(View view) {
29789             return (view.mID == mId);
29790         }
29791     }
29792 
29793     private static class MatchLabelForPredicate implements Predicate<View> {
29794         private int mLabeledId;
29795 
29796         @Override
test(View view)29797         public boolean test(View view) {
29798             return (view.mLabelForId == mLabeledId);
29799         }
29800     }
29801 
29802 
29803     /**
29804      * Returns the current scroll capture hint for this view.
29805      *
29806      * @return the current scroll capture hint
29807      *
29808      * @hide
29809      */
29810     @ScrollCaptureHint
getScrollCaptureHint()29811     public int getScrollCaptureHint() {
29812         return (mPrivateFlags4 & PFLAG4_SCROLL_CAPTURE_HINT_MASK)
29813                 >> PFLAG4_SCROLL_CAPTURE_HINT_SHIFT;
29814     }
29815 
29816     /**
29817      * Sets the scroll capture hint for this View. These flags affect the search for a potential
29818      * scroll capture targets.
29819      *
29820      * @param hint the scrollCaptureHint flags value to set
29821      *
29822      * @hide
29823      */
setScrollCaptureHint(@crollCaptureHint int hint)29824     public void setScrollCaptureHint(@ScrollCaptureHint int hint) {
29825         mPrivateFlags4 &= ~PFLAG4_SCROLL_CAPTURE_HINT_MASK;
29826         mPrivateFlags4 |= ((hint << PFLAG4_SCROLL_CAPTURE_HINT_SHIFT)
29827                 & PFLAG4_SCROLL_CAPTURE_HINT_MASK);
29828     }
29829 
29830     /**
29831      * Sets the callback to receive scroll capture requests. This component is the adapter between
29832      * the scroll capture API and application UI code. If no callback is set, the system may provide
29833      * an implementation. Any value provided here will take precedence over a system version.
29834      * <p>
29835      * This view will be ignored when {@link #SCROLL_CAPTURE_HINT_EXCLUDE} is set in its {@link
29836      * #setScrollCaptureHint(int) scrollCaptureHint}, regardless whether a callback has been set.
29837      * <p>
29838      * It is recommended to set the scroll capture hint {@link #SCROLL_CAPTURE_HINT_INCLUDE} when
29839      * setting a custom callback to help ensure it is selected as the target.
29840      *
29841      * @param callback the new callback to assign
29842      *
29843      * @hide
29844      */
setScrollCaptureCallback(@ullable ScrollCaptureCallback callback)29845     public void setScrollCaptureCallback(@Nullable ScrollCaptureCallback callback) {
29846         getListenerInfo().mScrollCaptureCallback = callback;
29847     }
29848 
29849     /** {@hide} */
29850     @Nullable
createScrollCaptureCallbackInternal(@onNull Rect localVisibleRect, @NonNull Point windowOffset)29851     public ScrollCaptureCallback createScrollCaptureCallbackInternal(@NonNull Rect localVisibleRect,
29852             @NonNull Point windowOffset) {
29853         if (mAttachInfo == null) {
29854             return null;
29855         }
29856         if (mAttachInfo.mScrollCaptureInternal == null) {
29857             mAttachInfo.mScrollCaptureInternal = new ScrollCaptureInternal();
29858         }
29859         return mAttachInfo.mScrollCaptureInternal.requestCallback(this, localVisibleRect,
29860                 windowOffset);
29861     }
29862 
29863     /**
29864      * Called when scroll capture is requested, to search for appropriate content to scroll. If
29865      * applicable, this view adds itself to the provided list for consideration, subject to the
29866      * flags set by {@link #setScrollCaptureHint}.
29867      *
29868      * @param localVisibleRect the local visible rect of this view
29869      * @param windowOffset     the offset of localVisibleRect within the window
29870      * @param targets          a queue which collects potential targets
29871      *
29872      * @throws IllegalStateException if this view is not attached to a window
29873      * @hide
29874      */
dispatchScrollCaptureSearch(@onNull Rect localVisibleRect, @NonNull Point windowOffset, @NonNull Queue<ScrollCaptureTarget> targets)29875     public void dispatchScrollCaptureSearch(@NonNull Rect localVisibleRect,
29876             @NonNull Point windowOffset, @NonNull Queue<ScrollCaptureTarget> targets) {
29877         int hint = getScrollCaptureHint();
29878         if ((hint & SCROLL_CAPTURE_HINT_EXCLUDE) != 0) {
29879             return;
29880         }
29881 
29882         // Get a callback provided by the framework, library or application.
29883         ScrollCaptureCallback callback =
29884                 (mListenerInfo == null) ? null : mListenerInfo.mScrollCaptureCallback;
29885 
29886         // Try internal support for standard scrolling containers.
29887         if (callback == null) {
29888             callback = createScrollCaptureCallbackInternal(localVisibleRect, windowOffset);
29889         }
29890 
29891         // If found, then add it to the list.
29892         if (callback != null) {
29893             // Add to the list for consideration
29894             Point offset = new Point(windowOffset.x, windowOffset.y);
29895             Rect rect = new Rect(localVisibleRect);
29896             targets.add(new ScrollCaptureTarget(this, rect, offset, callback));
29897         }
29898     }
29899 
29900     /**
29901      * Dump all private flags in readable format, useful for documentation and
29902      * sanity checking.
29903      */
dumpFlags()29904     private static void dumpFlags() {
29905         final HashMap<String, String> found = Maps.newHashMap();
29906         try {
29907             for (Field field : View.class.getDeclaredFields()) {
29908                 final int modifiers = field.getModifiers();
29909                 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
29910                     if (field.getType().equals(int.class)) {
29911                         final int value = field.getInt(null);
29912                         dumpFlag(found, field.getName(), value);
29913                     } else if (field.getType().equals(int[].class)) {
29914                         final int[] values = (int[]) field.get(null);
29915                         for (int i = 0; i < values.length; i++) {
29916                             dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
29917                         }
29918                     }
29919                 }
29920             }
29921         } catch (IllegalAccessException e) {
29922             throw new RuntimeException(e);
29923         }
29924 
29925         final ArrayList<String> keys = Lists.newArrayList();
29926         keys.addAll(found.keySet());
29927         Collections.sort(keys);
29928         for (String key : keys) {
29929             Log.d(VIEW_LOG_TAG, found.get(key));
29930         }
29931     }
29932 
dumpFlag(HashMap<String, String> found, String name, int value)29933     private static void dumpFlag(HashMap<String, String> found, String name, int value) {
29934         // Sort flags by prefix, then by bits, always keeping unique keys
29935         final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
29936         final int prefix = name.indexOf('_');
29937         final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
29938         final String output = bits + " " + name;
29939         found.put(key, output);
29940     }
29941 
29942     /** {@hide} */
encode(@onNull ViewHierarchyEncoder stream)29943     public void encode(@NonNull ViewHierarchyEncoder stream) {
29944         stream.beginObject(this);
29945         encodeProperties(stream);
29946         stream.endObject();
29947     }
29948 
29949     /** {@hide} */
29950     @CallSuper
encodeProperties(@onNull ViewHierarchyEncoder stream)29951     protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
29952         Object resolveId = ViewDebug.resolveId(getContext(), mID);
29953         if (resolveId instanceof String) {
29954             stream.addProperty("id", (String) resolveId);
29955         } else {
29956             stream.addProperty("id", mID);
29957         }
29958 
29959         stream.addProperty("misc:transformation.alpha",
29960                 mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
29961         stream.addProperty("misc:transitionName", getTransitionName());
29962 
29963         // layout
29964         stream.addProperty("layout:left", mLeft);
29965         stream.addProperty("layout:right", mRight);
29966         stream.addProperty("layout:top", mTop);
29967         stream.addProperty("layout:bottom", mBottom);
29968         stream.addProperty("layout:width", getWidth());
29969         stream.addProperty("layout:height", getHeight());
29970         stream.addProperty("layout:layoutDirection", getLayoutDirection());
29971         stream.addProperty("layout:layoutRtl", isLayoutRtl());
29972         stream.addProperty("layout:hasTransientState", hasTransientState());
29973         stream.addProperty("layout:baseline", getBaseline());
29974 
29975         // layout params
29976         ViewGroup.LayoutParams layoutParams = getLayoutParams();
29977         if (layoutParams != null) {
29978             stream.addPropertyKey("layoutParams");
29979             layoutParams.encode(stream);
29980         }
29981 
29982         // scrolling
29983         stream.addProperty("scrolling:scrollX", mScrollX);
29984         stream.addProperty("scrolling:scrollY", mScrollY);
29985 
29986         // padding
29987         stream.addProperty("padding:paddingLeft", mPaddingLeft);
29988         stream.addProperty("padding:paddingRight", mPaddingRight);
29989         stream.addProperty("padding:paddingTop", mPaddingTop);
29990         stream.addProperty("padding:paddingBottom", mPaddingBottom);
29991         stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
29992         stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
29993         stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
29994         stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
29995         stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
29996 
29997         // measurement
29998         stream.addProperty("measurement:minHeight", mMinHeight);
29999         stream.addProperty("measurement:minWidth", mMinWidth);
30000         stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
30001         stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
30002 
30003         // drawing
30004         stream.addProperty("drawing:elevation", getElevation());
30005         stream.addProperty("drawing:translationX", getTranslationX());
30006         stream.addProperty("drawing:translationY", getTranslationY());
30007         stream.addProperty("drawing:translationZ", getTranslationZ());
30008         stream.addProperty("drawing:rotation", getRotation());
30009         stream.addProperty("drawing:rotationX", getRotationX());
30010         stream.addProperty("drawing:rotationY", getRotationY());
30011         stream.addProperty("drawing:scaleX", getScaleX());
30012         stream.addProperty("drawing:scaleY", getScaleY());
30013         stream.addProperty("drawing:pivotX", getPivotX());
30014         stream.addProperty("drawing:pivotY", getPivotY());
30015         stream.addProperty("drawing:clipBounds",
30016                 mClipBounds == null ? null : mClipBounds.toString());
30017         stream.addProperty("drawing:opaque", isOpaque());
30018         stream.addProperty("drawing:alpha", getAlpha());
30019         stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
30020         stream.addProperty("drawing:shadow", hasShadow());
30021         stream.addProperty("drawing:solidColor", getSolidColor());
30022         stream.addProperty("drawing:layerType", mLayerType);
30023         stream.addProperty("drawing:willNotDraw", willNotDraw());
30024         stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
30025         stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
30026         stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
30027         stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
30028         stream.addProperty("drawing:outlineAmbientShadowColor", getOutlineAmbientShadowColor());
30029         stream.addProperty("drawing:outlineSpotShadowColor", getOutlineSpotShadowColor());
30030 
30031         // focus
30032         stream.addProperty("focus:hasFocus", hasFocus());
30033         stream.addProperty("focus:isFocused", isFocused());
30034         stream.addProperty("focus:focusable", getFocusable());
30035         stream.addProperty("focus:isFocusable", isFocusable());
30036         stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
30037 
30038         stream.addProperty("misc:clickable", isClickable());
30039         stream.addProperty("misc:pressed", isPressed());
30040         stream.addProperty("misc:selected", isSelected());
30041         stream.addProperty("misc:touchMode", isInTouchMode());
30042         stream.addProperty("misc:hovered", isHovered());
30043         stream.addProperty("misc:activated", isActivated());
30044 
30045         stream.addProperty("misc:visibility", getVisibility());
30046         stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
30047         stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
30048 
30049         stream.addProperty("misc:enabled", isEnabled());
30050         stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
30051         stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
30052 
30053         // theme attributes
30054         Resources.Theme theme = getContext().getTheme();
30055         if (theme != null) {
30056             stream.addPropertyKey("theme");
30057             theme.encode(stream);
30058         }
30059 
30060         // view attribute information
30061         int n = mAttributes != null ? mAttributes.length : 0;
30062         stream.addProperty("meta:__attrCount__", n/2);
30063         for (int i = 0; i < n; i += 2) {
30064             stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
30065         }
30066 
30067         stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
30068 
30069         // text
30070         stream.addProperty("text:textDirection", getTextDirection());
30071         stream.addProperty("text:textAlignment", getTextAlignment());
30072 
30073         // accessibility
30074         CharSequence contentDescription = getContentDescription();
30075         stream.addUserProperty("accessibility:contentDescription",
30076                 contentDescription == null ? "" : contentDescription.toString());
30077         stream.addProperty("accessibility:labelFor", getLabelFor());
30078         stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
30079     }
30080 
30081     /**
30082      * Determine if this view is rendered on a round wearable device and is the main view
30083      * on the screen.
30084      */
shouldDrawRoundScrollbar()30085     boolean shouldDrawRoundScrollbar() {
30086         if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
30087             return false;
30088         }
30089 
30090         final View rootView = getRootView();
30091         final WindowInsets insets = getRootWindowInsets();
30092 
30093         int height = getHeight();
30094         int width = getWidth();
30095         int displayHeight = rootView.getHeight();
30096         int displayWidth = rootView.getWidth();
30097 
30098         if (height != displayHeight || width != displayWidth) {
30099             return false;
30100         }
30101 
30102         getLocationInWindow(mAttachInfo.mTmpLocation);
30103         return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
30104                 && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
30105     }
30106 
30107     /**
30108      * Sets the tooltip text which will be displayed in a small popup next to the view.
30109      * <p>
30110      * The tooltip will be displayed:
30111      * <ul>
30112      * <li>On long click, unless it is handled otherwise (by OnLongClickListener or a context
30113      * menu). </li>
30114      * <li>On hover, after a brief delay since the pointer has stopped moving </li>
30115      * </ul>
30116      * <p>
30117      * <strong>Note:</strong> Do not override this method, as it will have no
30118      * effect on the text displayed in the tooltip.
30119      *
30120      * @param tooltipText the tooltip text, or null if no tooltip is required
30121      * @see #getTooltipText()
30122      * @attr ref android.R.styleable#View_tooltipText
30123      */
setTooltipText(@ullable CharSequence tooltipText)30124     public void setTooltipText(@Nullable CharSequence tooltipText) {
30125         if (TextUtils.isEmpty(tooltipText)) {
30126             setFlags(0, TOOLTIP);
30127             hideTooltip();
30128             mTooltipInfo = null;
30129         } else {
30130             setFlags(TOOLTIP, TOOLTIP);
30131             if (mTooltipInfo == null) {
30132                 mTooltipInfo = new TooltipInfo();
30133                 mTooltipInfo.mShowTooltipRunnable = this::showHoverTooltip;
30134                 mTooltipInfo.mHideTooltipRunnable = this::hideTooltip;
30135                 mTooltipInfo.mHoverSlop = ViewConfiguration.get(mContext).getScaledHoverSlop();
30136                 mTooltipInfo.clearAnchorPos();
30137             }
30138             mTooltipInfo.mTooltipText = tooltipText;
30139         }
30140     }
30141 
30142     /**
30143      * @hide Binary compatibility stub. To be removed when we finalize O APIs.
30144      */
30145     @UnsupportedAppUsage
setTooltip(@ullable CharSequence tooltipText)30146     public void setTooltip(@Nullable CharSequence tooltipText) {
30147         setTooltipText(tooltipText);
30148     }
30149 
30150     /**
30151      * Returns the view's tooltip text.
30152      *
30153      * <strong>Note:</strong> Do not override this method, as it will have no
30154      * effect on the text displayed in the tooltip. You must call
30155      * {@link #setTooltipText(CharSequence)} to modify the tooltip text.
30156      *
30157      * @return the tooltip text
30158      * @see #setTooltipText(CharSequence)
30159      * @attr ref android.R.styleable#View_tooltipText
30160      */
30161     @InspectableProperty
30162     @Nullable
getTooltipText()30163     public CharSequence getTooltipText() {
30164         return mTooltipInfo != null ? mTooltipInfo.mTooltipText : null;
30165     }
30166 
30167     /**
30168      * @hide Binary compatibility stub. To be removed when we finalize O APIs.
30169      */
30170     @Nullable
getTooltip()30171     public CharSequence getTooltip() {
30172         return getTooltipText();
30173     }
30174 
showTooltip(int x, int y, boolean fromLongClick)30175     private boolean showTooltip(int x, int y, boolean fromLongClick) {
30176         if (mAttachInfo == null || mTooltipInfo == null) {
30177             return false;
30178         }
30179         if (fromLongClick && (mViewFlags & ENABLED_MASK) != ENABLED) {
30180             return false;
30181         }
30182         if (TextUtils.isEmpty(mTooltipInfo.mTooltipText)) {
30183             return false;
30184         }
30185         hideTooltip();
30186         mTooltipInfo.mTooltipFromLongClick = fromLongClick;
30187         mTooltipInfo.mTooltipPopup = new TooltipPopup(getContext());
30188         final boolean fromTouch = (mPrivateFlags3 & PFLAG3_FINGER_DOWN) == PFLAG3_FINGER_DOWN;
30189         mTooltipInfo.mTooltipPopup.show(this, x, y, fromTouch, mTooltipInfo.mTooltipText);
30190         mAttachInfo.mTooltipHost = this;
30191         // The available accessibility actions have changed
30192         notifyViewAccessibilityStateChangedIfNeeded(CONTENT_CHANGE_TYPE_UNDEFINED);
30193         return true;
30194     }
30195 
30196     @UnsupportedAppUsage
hideTooltip()30197     void hideTooltip() {
30198         if (mTooltipInfo == null) {
30199             return;
30200         }
30201         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
30202         if (mTooltipInfo.mTooltipPopup == null) {
30203             return;
30204         }
30205         mTooltipInfo.mTooltipPopup.hide();
30206         mTooltipInfo.mTooltipPopup = null;
30207         mTooltipInfo.mTooltipFromLongClick = false;
30208         mTooltipInfo.clearAnchorPos();
30209         if (mAttachInfo != null) {
30210             mAttachInfo.mTooltipHost = null;
30211         }
30212         // The available accessibility actions have changed
30213         notifyViewAccessibilityStateChangedIfNeeded(CONTENT_CHANGE_TYPE_UNDEFINED);
30214     }
30215 
showLongClickTooltip(int x, int y)30216     private boolean showLongClickTooltip(int x, int y) {
30217         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
30218         removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
30219         return showTooltip(x, y, true);
30220     }
30221 
showHoverTooltip()30222     private boolean showHoverTooltip() {
30223         return showTooltip(mTooltipInfo.mAnchorX, mTooltipInfo.mAnchorY, false);
30224     }
30225 
dispatchTooltipHoverEvent(MotionEvent event)30226     boolean dispatchTooltipHoverEvent(MotionEvent event) {
30227         if (mTooltipInfo == null) {
30228             return false;
30229         }
30230         switch(event.getAction()) {
30231             case MotionEvent.ACTION_HOVER_MOVE:
30232                 if ((mViewFlags & TOOLTIP) != TOOLTIP) {
30233                     break;
30234                 }
30235                 if (!mTooltipInfo.mTooltipFromLongClick && mTooltipInfo.updateAnchorPos(event)) {
30236                     if (mTooltipInfo.mTooltipPopup == null) {
30237                         // Schedule showing the tooltip after a timeout.
30238                         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
30239                         postDelayed(mTooltipInfo.mShowTooltipRunnable,
30240                                 ViewConfiguration.getHoverTooltipShowTimeout());
30241                     }
30242 
30243                     // Hide hover-triggered tooltip after a period of inactivity.
30244                     // Match the timeout used by NativeInputManager to hide the mouse pointer
30245                     // (depends on SYSTEM_UI_FLAG_LOW_PROFILE being set).
30246                     final int timeout;
30247                     if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LOW_PROFILE)
30248                             == SYSTEM_UI_FLAG_LOW_PROFILE) {
30249                         timeout = ViewConfiguration.getHoverTooltipHideShortTimeout();
30250                     } else {
30251                         timeout = ViewConfiguration.getHoverTooltipHideTimeout();
30252                     }
30253                     removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
30254                     postDelayed(mTooltipInfo.mHideTooltipRunnable, timeout);
30255                 }
30256                 return true;
30257 
30258             case MotionEvent.ACTION_HOVER_EXIT:
30259                 mTooltipInfo.clearAnchorPos();
30260                 if (!mTooltipInfo.mTooltipFromLongClick) {
30261                     hideTooltip();
30262                 }
30263                 break;
30264         }
30265         return false;
30266     }
30267 
handleTooltipKey(KeyEvent event)30268     void handleTooltipKey(KeyEvent event) {
30269         switch (event.getAction()) {
30270             case KeyEvent.ACTION_DOWN:
30271                 if (event.getRepeatCount() == 0) {
30272                     hideTooltip();
30273                 }
30274                 break;
30275 
30276             case KeyEvent.ACTION_UP:
30277                 handleTooltipUp();
30278                 break;
30279         }
30280     }
30281 
handleTooltipUp()30282     private void handleTooltipUp() {
30283         if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
30284             return;
30285         }
30286         removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
30287         postDelayed(mTooltipInfo.mHideTooltipRunnable,
30288                 ViewConfiguration.getLongPressTooltipHideTimeout());
30289     }
30290 
getFocusableAttribute(TypedArray attributes)30291     private int getFocusableAttribute(TypedArray attributes) {
30292         TypedValue val = new TypedValue();
30293         if (attributes.getValue(com.android.internal.R.styleable.View_focusable, val)) {
30294             if (val.type == TypedValue.TYPE_INT_BOOLEAN) {
30295                 return (val.data == 0 ? NOT_FOCUSABLE : FOCUSABLE);
30296             } else {
30297                 return val.data;
30298             }
30299         } else {
30300             return FOCUSABLE_AUTO;
30301         }
30302     }
30303 
30304     /**
30305      * @return The content view of the tooltip popup currently being shown, or null if the tooltip
30306      * is not showing.
30307      * @hide
30308      */
30309     @TestApi
getTooltipView()30310     public View getTooltipView() {
30311         if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
30312             return null;
30313         }
30314         return mTooltipInfo.mTooltipPopup.getContentView();
30315     }
30316 
30317     /**
30318      * @return {@code true} if the default focus highlight is enabled, {@code false} otherwies.
30319      * @hide
30320      */
30321     @TestApi
isDefaultFocusHighlightEnabled()30322     public static boolean isDefaultFocusHighlightEnabled() {
30323         return sUseDefaultFocusHighlight;
30324     }
30325 
30326     /**
30327      * Dispatch a previously unhandled {@link KeyEvent} to this view. Unlike normal key dispatch,
30328      * this dispatches to ALL child views until it is consumed. The dispatch order is z-order
30329      * (visually on-top views first).
30330      *
30331      * @param evt the previously unhandled {@link KeyEvent}.
30332      * @return the {@link View} which consumed the event or {@code null} if not consumed.
30333      */
dispatchUnhandledKeyEvent(KeyEvent evt)30334     View dispatchUnhandledKeyEvent(KeyEvent evt) {
30335         if (onUnhandledKeyEvent(evt)) {
30336             return this;
30337         }
30338         return null;
30339     }
30340 
30341     /**
30342      * Allows this view to handle {@link KeyEvent}s which weren't handled by normal dispatch. This
30343      * occurs after the normal view hierarchy dispatch, but before the window callback. By default,
30344      * this will dispatch into all the listeners registered via
30345      * {@link #addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener)} in last-in-first-out
30346      * order (most recently added will receive events first).
30347      *
30348      * @param event An unhandled event.
30349      * @return {@code true} if the event was handled, {@code false} otherwise.
30350      * @see #addOnUnhandledKeyEventListener
30351      */
onUnhandledKeyEvent(@onNull KeyEvent event)30352     boolean onUnhandledKeyEvent(@NonNull KeyEvent event) {
30353         if (mListenerInfo != null && mListenerInfo.mUnhandledKeyListeners != null) {
30354             for (int i = mListenerInfo.mUnhandledKeyListeners.size() - 1; i >= 0; --i) {
30355                 if (mListenerInfo.mUnhandledKeyListeners.get(i).onUnhandledKeyEvent(this, event)) {
30356                     return true;
30357                 }
30358             }
30359         }
30360         return false;
30361     }
30362 
hasUnhandledKeyListener()30363     boolean hasUnhandledKeyListener() {
30364         return (mListenerInfo != null && mListenerInfo.mUnhandledKeyListeners != null
30365                 && !mListenerInfo.mUnhandledKeyListeners.isEmpty());
30366     }
30367 
30368     /**
30369      * Adds a listener which will receive unhandled {@link KeyEvent}s. This must be called on the
30370      * UI thread.
30371      *
30372      * @param listener a receiver of unhandled {@link KeyEvent}s.
30373      * @see #removeOnUnhandledKeyEventListener
30374      */
addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener)30375     public void addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener) {
30376         ArrayList<OnUnhandledKeyEventListener> listeners = getListenerInfo().mUnhandledKeyListeners;
30377         if (listeners == null) {
30378             listeners = new ArrayList<>();
30379             getListenerInfo().mUnhandledKeyListeners = listeners;
30380         }
30381         listeners.add(listener);
30382         if (listeners.size() == 1 && mParent instanceof ViewGroup) {
30383             ((ViewGroup) mParent).incrementChildUnhandledKeyListeners();
30384         }
30385     }
30386 
30387     /**
30388      * Removes a listener which will receive unhandled {@link KeyEvent}s. This must be called on the
30389      * UI thread.
30390      *
30391      * @param listener a receiver of unhandled {@link KeyEvent}s.
30392      * @see #addOnUnhandledKeyEventListener
30393      */
removeOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener)30394     public void removeOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener) {
30395         if (mListenerInfo != null) {
30396             if (mListenerInfo.mUnhandledKeyListeners != null
30397                     && !mListenerInfo.mUnhandledKeyListeners.isEmpty()) {
30398                 mListenerInfo.mUnhandledKeyListeners.remove(listener);
30399                 if (mListenerInfo.mUnhandledKeyListeners.isEmpty()) {
30400                     mListenerInfo.mUnhandledKeyListeners = null;
30401                     if (mParent instanceof ViewGroup) {
30402                         ((ViewGroup) mParent).decrementChildUnhandledKeyListeners();
30403                     }
30404                 }
30405             }
30406         }
30407     }
30408 }
30409