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.os.Trace.TRACE_TAG_APP;
21 import static android.view.ContentInfo.SOURCE_DRAG_AND_DROP;
22 import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED;
23 import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_INVALID_BOUNDS;
24 import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_MISSING_WINDOW;
25 import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN;
26 import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_UNKNOWN;
27 import static android.view.displayhash.DisplayHashResultCallback.EXTRA_DISPLAY_HASH;
28 import static android.view.displayhash.DisplayHashResultCallback.EXTRA_DISPLAY_HASH_ERROR_CODE;
29 
30 import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS;
31 import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS;
32 import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP;
33 import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION;
34 
35 import static java.lang.Math.max;
36 
37 import android.animation.AnimatorInflater;
38 import android.animation.StateListAnimator;
39 import android.annotation.AttrRes;
40 import android.annotation.CallSuper;
41 import android.annotation.ColorInt;
42 import android.annotation.DrawableRes;
43 import android.annotation.FloatRange;
44 import android.annotation.IdRes;
45 import android.annotation.IntDef;
46 import android.annotation.IntRange;
47 import android.annotation.LayoutRes;
48 import android.annotation.NonNull;
49 import android.annotation.Nullable;
50 import android.annotation.RequiresPermission;
51 import android.annotation.Size;
52 import android.annotation.StyleRes;
53 import android.annotation.SuppressLint;
54 import android.annotation.SystemApi;
55 import android.annotation.TestApi;
56 import android.annotation.UiContext;
57 import android.annotation.UiThread;
58 import android.compat.annotation.UnsupportedAppUsage;
59 import android.content.AutofillOptions;
60 import android.content.ClipData;
61 import android.content.ClipDescription;
62 import android.content.Context;
63 import android.content.ContextWrapper;
64 import android.content.Intent;
65 import android.content.res.ColorStateList;
66 import android.content.res.CompatibilityInfo;
67 import android.content.res.Configuration;
68 import android.content.res.Resources;
69 import android.content.res.TypedArray;
70 import android.graphics.Bitmap;
71 import android.graphics.BlendMode;
72 import android.graphics.Canvas;
73 import android.graphics.Color;
74 import android.graphics.Insets;
75 import android.graphics.Interpolator;
76 import android.graphics.LinearGradient;
77 import android.graphics.Matrix;
78 import android.graphics.Outline;
79 import android.graphics.Paint;
80 import android.graphics.PixelFormat;
81 import android.graphics.Point;
82 import android.graphics.PorterDuff;
83 import android.graphics.PorterDuffXfermode;
84 import android.graphics.RecordingCanvas;
85 import android.graphics.Rect;
86 import android.graphics.RectF;
87 import android.graphics.Region;
88 import android.graphics.RenderEffect;
89 import android.graphics.RenderNode;
90 import android.graphics.Shader;
91 import android.graphics.drawable.ColorDrawable;
92 import android.graphics.drawable.Drawable;
93 import android.graphics.drawable.GradientDrawable;
94 import android.hardware.display.DisplayManagerGlobal;
95 import android.hardware.input.InputManager;
96 import android.net.Uri;
97 import android.os.Build;
98 import android.os.Bundle;
99 import android.os.Handler;
100 import android.os.IBinder;
101 import android.os.Message;
102 import android.os.Parcel;
103 import android.os.Parcelable;
104 import android.os.RemoteCallback;
105 import android.os.RemoteException;
106 import android.os.SystemClock;
107 import android.os.Trace;
108 import android.sysprop.DisplayProperties;
109 import android.text.InputType;
110 import android.text.TextUtils;
111 import android.util.AttributeSet;
112 import android.util.FloatProperty;
113 import android.util.LayoutDirection;
114 import android.util.Log;
115 import android.util.LongSparseArray;
116 import android.util.LongSparseLongArray;
117 import android.util.Pair;
118 import android.util.Pools.SynchronizedPool;
119 import android.util.Property;
120 import android.util.SparseArray;
121 import android.util.SparseIntArray;
122 import android.util.StateSet;
123 import android.util.SuperNotCalledException;
124 import android.util.TypedValue;
125 import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
126 import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
127 import android.view.AccessibilityIterators.TextSegmentIterator;
128 import android.view.AccessibilityIterators.WordTextSegmentIterator;
129 import android.view.ContextMenu.ContextMenuInfo;
130 import android.view.InputDevice.InputSourceClass;
131 import android.view.Window.OnContentApplyWindowInsetsListener;
132 import android.view.WindowInsets.Type;
133 import android.view.WindowInsetsAnimation.Bounds;
134 import android.view.WindowManager.LayoutParams;
135 import android.view.accessibility.AccessibilityEvent;
136 import android.view.accessibility.AccessibilityEventSource;
137 import android.view.accessibility.AccessibilityManager;
138 import android.view.accessibility.AccessibilityNodeIdManager;
139 import android.view.accessibility.AccessibilityNodeInfo;
140 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
141 import android.view.accessibility.AccessibilityNodeProvider;
142 import android.view.accessibility.AccessibilityWindowInfo;
143 import android.view.animation.Animation;
144 import android.view.animation.AnimationUtils;
145 import android.view.animation.Transformation;
146 import android.view.autofill.AutofillId;
147 import android.view.autofill.AutofillManager;
148 import android.view.autofill.AutofillValue;
149 import android.view.contentcapture.ContentCaptureContext;
150 import android.view.contentcapture.ContentCaptureManager;
151 import android.view.contentcapture.ContentCaptureSession;
152 import android.view.displayhash.DisplayHash;
153 import android.view.displayhash.DisplayHashManager;
154 import android.view.displayhash.DisplayHashResultCallback;
155 import android.view.inputmethod.EditorInfo;
156 import android.view.inputmethod.InputConnection;
157 import android.view.inputmethod.InputMethodManager;
158 import android.view.inspector.InspectableProperty;
159 import android.view.inspector.InspectableProperty.EnumEntry;
160 import android.view.inspector.InspectableProperty.FlagEntry;
161 import android.view.translation.TranslationCapability;
162 import android.view.translation.TranslationSpec.DataFormat;
163 import android.view.translation.ViewTranslationCallback;
164 import android.view.translation.ViewTranslationRequest;
165 import android.view.translation.ViewTranslationResponse;
166 import android.widget.Checkable;
167 import android.widget.FrameLayout;
168 import android.widget.ScrollBarDrawable;
169 import android.window.OnBackInvokedDispatcher;
170 
171 import com.android.internal.R;
172 import com.android.internal.util.ArrayUtils;
173 import com.android.internal.util.FrameworkStatsLog;
174 import com.android.internal.util.Preconditions;
175 import com.android.internal.view.ScrollCaptureInternal;
176 import com.android.internal.view.TooltipPopup;
177 import com.android.internal.view.menu.MenuBuilder;
178 import com.android.internal.widget.ScrollBarUtils;
179 
180 import com.google.android.collect.Lists;
181 import com.google.android.collect.Maps;
182 
183 import java.io.PrintWriter;
184 import java.lang.annotation.Retention;
185 import java.lang.annotation.RetentionPolicy;
186 import java.lang.ref.WeakReference;
187 import java.lang.reflect.Field;
188 import java.lang.reflect.InvocationTargetException;
189 import java.lang.reflect.Method;
190 import java.lang.reflect.Modifier;
191 import java.util.ArrayList;
192 import java.util.Arrays;
193 import java.util.Calendar;
194 import java.util.Collection;
195 import java.util.Collections;
196 import java.util.HashMap;
197 import java.util.List;
198 import java.util.Locale;
199 import java.util.Map;
200 import java.util.concurrent.CopyOnWriteArrayList;
201 import java.util.concurrent.Executor;
202 import java.util.concurrent.atomic.AtomicInteger;
203 import java.util.function.Consumer;
204 import java.util.function.Predicate;
205 
206 /**
207  * <p>
208  * This class represents the basic building block for user interface components. A View
209  * occupies a rectangular area on the screen and is responsible for drawing and
210  * event handling. View is the base class for <em>widgets</em>, which are
211  * used to create interactive UI components (buttons, text fields, etc.). The
212  * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
213  * are invisible containers that hold other Views (or other ViewGroups) and define
214  * their layout properties.
215  * </p>
216  *
217  * <div class="special reference">
218  * <h3>Developer Guides</h3>
219  * <p>For information about using this class to develop your application's user interface,
220  * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
221  * </div>
222  *
223  * <a name="Using"></a>
224  * <h3>Using Views</h3>
225  * <p>
226  * All of the views in a window are arranged in a single tree. You can add views
227  * either from code or by specifying a tree of views in one or more XML layout
228  * files. There are many specialized subclasses of views that act as controls or
229  * are capable of displaying text, images, or other content.
230  * </p>
231  * <p>
232  * Once you have created a tree of views, there are typically a few types of
233  * common operations you may wish to perform:
234  * <ul>
235  * <li><strong>Set properties:</strong> for example setting the text of a
236  * {@link android.widget.TextView}. The available properties and the methods
237  * that set them will vary among the different subclasses of views. Note that
238  * properties that are known at build time can be set in the XML layout
239  * files.</li>
240  * <li><strong>Set focus:</strong> The framework will handle moving focus in
241  * response to user input. To force focus to a specific view, call
242  * {@link #requestFocus}.</li>
243  * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
244  * that will be notified when something interesting happens to the view. For
245  * example, all views will let you set a listener to be notified when the view
246  * gains or loses focus. You can register such a listener using
247  * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
248  * Other view subclasses offer more specialized listeners. For example, a Button
249  * exposes a listener to notify clients when the button is clicked.</li>
250  * <li><strong>Set visibility:</strong> You can hide or show views using
251  * {@link #setVisibility(int)}.</li>
252  * </ul>
253  * </p>
254  * <p><em>
255  * Note: The Android framework is responsible for measuring, laying out and
256  * drawing views. You should not call methods that perform these actions on
257  * views yourself unless you are actually implementing a
258  * {@link android.view.ViewGroup}.
259  * </em></p>
260  *
261  * <a name="Lifecycle"></a>
262  * <h3>Implementing a Custom View</h3>
263  *
264  * <p>
265  * To implement a custom view, you will usually begin by providing overrides for
266  * some of the standard methods that the framework calls on all views. You do
267  * not need to override all of these methods. In fact, you can start by just
268  * overriding {@link #onDraw(android.graphics.Canvas)}.
269  * <table border="2" width="85%" align="center" cellpadding="5">
270  *     <thead>
271  *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
272  *     </thead>
273  *
274  *     <tbody>
275  *     <tr>
276  *         <td rowspan="2">Creation</td>
277  *         <td>Constructors</td>
278  *         <td>There is a form of the constructor that are called when the view
279  *         is created from code and a form that is called when the view is
280  *         inflated from a layout file. The second form should parse and apply
281  *         any attributes defined in the layout file.
282  *         </td>
283  *     </tr>
284  *     <tr>
285  *         <td><code>{@link #onFinishInflate()}</code></td>
286  *         <td>Called after a view and all of its children has been inflated
287  *         from XML.</td>
288  *     </tr>
289  *
290  *     <tr>
291  *         <td rowspan="3">Layout</td>
292  *         <td><code>{@link #onMeasure(int, int)}</code></td>
293  *         <td>Called to determine the size requirements for this view and all
294  *         of its children.
295  *         </td>
296  *     </tr>
297  *     <tr>
298  *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
299  *         <td>Called when this view should assign a size and position to all
300  *         of its children.
301  *         </td>
302  *     </tr>
303  *     <tr>
304  *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
305  *         <td>Called when the size of this view has changed.
306  *         </td>
307  *     </tr>
308  *
309  *     <tr>
310  *         <td>Drawing</td>
311  *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
312  *         <td>Called when the view should render its content.
313  *         </td>
314  *     </tr>
315  *
316  *     <tr>
317  *         <td rowspan="6">Event processing</td>
318  *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
319  *         <td>Called when a new hardware key event occurs.
320  *         </td>
321  *     </tr>
322  *     <tr>
323  *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
324  *         <td>Called when a hardware key up event occurs.
325  *         </td>
326  *     </tr>
327  *     <tr>
328  *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
329  *         <td>Called when a trackball motion event occurs.
330  *         </td>
331  *     </tr>
332  *     <tr>
333  *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
334  *         <td>Called when a touch screen motion event occurs.
335  *         </td>
336  *     </tr>
337  *     <tr>
338  *         <td><code>{@link #onGenericMotionEvent(MotionEvent)}</code></td>
339  *         <td>Called when a generic motion event occurs.
340  *         </td>
341  *     </tr>
342  *     <tr>
343  *         <td><code>{@link #onHoverEvent(MotionEvent)}</code></td>
344  *         <td>Called when a hover motion event occurs.
345  *         </td>
346  *     </tr>
347  *
348  *     <tr>
349  *         <td rowspan="2">Focus</td>
350  *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
351  *         <td>Called when the view gains or loses focus.
352  *         </td>
353  *     </tr>
354  *
355  *     <tr>
356  *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
357  *         <td>Called when the window containing the view gains or loses focus.
358  *         </td>
359  *     </tr>
360  *
361  *     <tr>
362  *         <td rowspan="3">Attaching</td>
363  *         <td><code>{@link #onAttachedToWindow()}</code></td>
364  *         <td>Called when the view is attached to a window.
365  *         </td>
366  *     </tr>
367  *
368  *     <tr>
369  *         <td><code>{@link #onDetachedFromWindow}</code></td>
370  *         <td>Called when the view is detached from its window.
371  *         </td>
372  *     </tr>
373  *
374  *     <tr>
375  *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
376  *         <td>Called when the visibility of the window containing the view
377  *         has changed.
378  *         </td>
379  *     </tr>
380  *     </tbody>
381  *
382  * </table>
383  * </p>
384  *
385  * <a name="IDs"></a>
386  * <h3>IDs</h3>
387  * Views may have an integer id associated with them. These ids are typically
388  * assigned in the layout XML files, and are used to find specific views within
389  * the view tree. A common pattern is to:
390  * <ul>
391  * <li>Define a Button in the layout file and assign it a unique ID.
392  * <pre>
393  * &lt;Button
394  *     android:id="@+id/my_button"
395  *     android:layout_width="wrap_content"
396  *     android:layout_height="wrap_content"
397  *     android:text="@string/my_button_text"/&gt;
398  * </pre></li>
399  * <li>From the onCreate method of an Activity, find the Button
400  * <pre class="prettyprint">
401  *      Button myButton = findViewById(R.id.my_button);
402  * </pre></li>
403  * </ul>
404  * <p>
405  * View IDs need not be unique throughout the tree, but it is good practice to
406  * ensure that they are at least unique within the part of the tree you are
407  * searching.
408  * </p>
409  *
410  * <a name="Position"></a>
411  * <h3>Position</h3>
412  * <p>
413  * The geometry of a view is that of a rectangle. A view has a location,
414  * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
415  * two dimensions, expressed as a width and a height. The unit for location
416  * and dimensions is the pixel.
417  * </p>
418  *
419  * <p>
420  * It is possible to retrieve the location of a view by invoking the methods
421  * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
422  * coordinate of the rectangle representing the view. The latter returns the
423  * top, or Y, coordinate of the rectangle representing the view. These methods
424  * both return the location of the view relative to its parent. For instance,
425  * when getLeft() returns 20, that means the view is located 20 pixels to the
426  * right of the left edge of its direct parent.
427  * </p>
428  *
429  * <p>
430  * In addition, several convenience methods are offered to avoid unnecessary
431  * computations, namely {@link #getRight()} and {@link #getBottom()}.
432  * These methods return the coordinates of the right and bottom edges of the
433  * rectangle representing the view. For instance, calling {@link #getRight()}
434  * is similar to the following computation: <code>getLeft() + getWidth()</code>
435  * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
436  * </p>
437  *
438  * <a name="SizePaddingMargins"></a>
439  * <h3>Size, padding and margins</h3>
440  * <p>
441  * The size of a view is expressed with a width and a height. A view actually
442  * possess two pairs of width and height values.
443  * </p>
444  *
445  * <p>
446  * The first pair is known as <em>measured width</em> and
447  * <em>measured height</em>. These dimensions define how big a view wants to be
448  * within its parent (see <a href="#Layout">Layout</a> for more details.) The
449  * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
450  * and {@link #getMeasuredHeight()}.
451  * </p>
452  *
453  * <p>
454  * The second pair is simply known as <em>width</em> and <em>height</em>, or
455  * sometimes <em>drawing width</em> and <em>drawing height</em>. These
456  * dimensions define the actual size of the view on screen, at drawing time and
457  * after layout. These values may, but do not have to, be different from the
458  * measured width and height. The width and height can be obtained by calling
459  * {@link #getWidth()} and {@link #getHeight()}.
460  * </p>
461  *
462  * <p>
463  * To measure its dimensions, a view takes into account its padding. The padding
464  * is expressed in pixels for the left, top, right and bottom parts of the view.
465  * Padding can be used to offset the content of the view by a specific amount of
466  * pixels. For instance, a left padding of 2 will push the view's content by
467  * 2 pixels to the right of the left edge. Padding can be set using the
468  * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
469  * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
470  * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
471  * {@link #getPaddingEnd()}.
472  * </p>
473  *
474  * <p>
475  * Even though a view can define a padding, it does not provide any support for
476  * margins. However, view groups provide such a support. Refer to
477  * {@link android.view.ViewGroup} and
478  * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
479  * </p>
480  *
481  * <a name="Layout"></a>
482  * <h3>Layout</h3>
483  * <p>
484  * Layout is a two pass process: a measure pass and a layout pass. The measuring
485  * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
486  * of the view tree. Each view pushes dimension specifications down the tree
487  * during the recursion. At the end of the measure pass, every view has stored
488  * its measurements. The second pass happens in
489  * {@link #layout(int,int,int,int)} and is also top-down. During
490  * this pass each parent is responsible for positioning all of its children
491  * using the sizes computed in the measure pass.
492  * </p>
493  *
494  * <p>
495  * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
496  * {@link #getMeasuredHeight()} values must be set, along with those for all of
497  * that view's descendants. A view's measured width and measured height values
498  * must respect the constraints imposed by the view's parents. This guarantees
499  * that at the end of the measure pass, all parents accept all of their
500  * children's measurements. A parent view may call measure() more than once on
501  * its children. For example, the parent may measure each child once with
502  * unspecified dimensions to find out how big they want to be, then call
503  * measure() on them again with actual numbers if the sum of all the children's
504  * unconstrained sizes is too big or too small.
505  * </p>
506  *
507  * <p>
508  * The measure pass uses two classes to communicate dimensions. The
509  * {@link MeasureSpec} class is used by views to tell their parents how they
510  * want to be measured and positioned. The base LayoutParams class just
511  * describes how big the view wants to be for both width and height. For each
512  * dimension, it can specify one of:
513  * <ul>
514  * <li> an exact number
515  * <li>MATCH_PARENT, which means the view wants to be as big as its parent
516  * (minus padding)
517  * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
518  * enclose its content (plus padding).
519  * </ul>
520  * There are subclasses of LayoutParams for different subclasses of ViewGroup.
521  * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
522  * an X and Y value.
523  * </p>
524  *
525  * <p>
526  * MeasureSpecs are used to push requirements down the tree from parent to
527  * child. A MeasureSpec can be in one of three modes:
528  * <ul>
529  * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
530  * of a child view. For example, a LinearLayout may call measure() on its child
531  * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
532  * tall the child view wants to be given a width of 240 pixels.
533  * <li>EXACTLY: This is used by the parent to impose an exact size on the
534  * child. The child must use this size, and guarantee that all of its
535  * descendants will fit within this size.
536  * <li>AT_MOST: This is used by the parent to impose a maximum size on the
537  * child. The child must guarantee that it and all of its descendants will fit
538  * within this size.
539  * </ul>
540  * </p>
541  *
542  * <p>
543  * To initiate a layout, call {@link #requestLayout}. This method is typically
544  * called by a view on itself when it believes that it can no longer fit within
545  * its current bounds.
546  * </p>
547  *
548  * <a name="Drawing"></a>
549  * <h3>Drawing</h3>
550  * <p>
551  * Drawing is handled by walking the tree and recording the drawing commands of
552  * any View that needs to update. After this, the drawing commands of the
553  * entire tree are issued to screen, clipped to the newly damaged area.
554  * </p>
555  *
556  * <p>
557  * The tree is largely recorded and drawn in order, with parents drawn before
558  * (i.e., behind) their children, with siblings drawn in the order they appear
559  * in the tree. If you set a background drawable for a View, then the View will
560  * draw it before calling back to its <code>onDraw()</code> method. The child
561  * drawing order can be overridden with
562  * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
563  * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
564  * </p>
565  *
566  * <p>
567  * To force a view to draw, call {@link #invalidate()}.
568  * </p>
569  *
570  * <a name="EventHandlingThreading"></a>
571  * <h3>Event Handling and Threading</h3>
572  * <p>
573  * The basic cycle of a view is as follows:
574  * <ol>
575  * <li>An event comes in and is dispatched to the appropriate view. The view
576  * handles the event and notifies any listeners.</li>
577  * <li>If in the course of processing the event, the view's bounds may need
578  * to be changed, the view will call {@link #requestLayout()}.</li>
579  * <li>Similarly, if in the course of processing the event the view's appearance
580  * may need to be changed, the view will call {@link #invalidate()}.</li>
581  * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
582  * the framework will take care of measuring, laying out, and drawing the tree
583  * as appropriate.</li>
584  * </ol>
585  * </p>
586  *
587  * <p><em>Note: The entire view tree is single threaded. You must always be on
588  * the UI thread when calling any method on any view.</em>
589  * If you are doing work on other threads and want to update the state of a view
590  * from that thread, you should use a {@link Handler}.
591  * </p>
592  *
593  * <a name="FocusHandling"></a>
594  * <h3>Focus Handling</h3>
595  * <p>
596  * The framework will handle routine focus movement in response to user input.
597  * This includes changing the focus as views are removed or hidden, or as new
598  * views become available. Views indicate their willingness to take focus
599  * through the {@link #isFocusable} method. To change whether a view can take
600  * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
601  * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
602  * and can change this via {@link #setFocusableInTouchMode(boolean)}.
603  * </p>
604  * <p>
605  * Focus movement is based on an algorithm which finds the nearest neighbor in a
606  * given direction. In rare cases, the default algorithm may not match the
607  * intended behavior of the developer. In these situations, you can provide
608  * explicit overrides by using these XML attributes in the layout file:
609  * <pre>
610  * nextFocusDown
611  * nextFocusLeft
612  * nextFocusRight
613  * nextFocusUp
614  * </pre>
615  * </p>
616  *
617  *
618  * <p>
619  * To get a particular view to take focus, call {@link #requestFocus()}.
620  * </p>
621  *
622  * <a name="TouchMode"></a>
623  * <h3>Touch Mode</h3>
624  * <p>
625  * When a user is navigating a user interface via directional keys such as a D-pad, it is
626  * necessary to give focus to actionable items such as buttons so the user can see
627  * what will take input.  If the device has touch capabilities, however, and the user
628  * begins interacting with the interface by touching it, it is no longer necessary to
629  * always highlight, or give focus to, a particular view.  This motivates a mode
630  * for interaction named 'touch mode'.
631  * </p>
632  * <p>
633  * For a touch capable device, once the user touches the screen, the device
634  * will enter touch mode.  From this point onward, only views for which
635  * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
636  * Other views that are touchable, like buttons, will not take focus when touched; they will
637  * only fire the on click listeners.
638  * </p>
639  * <p>
640  * Any time a user hits a directional key, such as a D-pad direction, the view device will
641  * exit touch mode, and find a view to take focus, so that the user may resume interacting
642  * with the user interface without touching the screen again.
643  * </p>
644  * <p>
645  * The touch mode state is maintained across {@link android.app.Activity}s.  Call
646  * {@link #isInTouchMode} to see whether the device is currently in touch mode.
647  * </p>
648  *
649  * <a name="Scrolling"></a>
650  * <h3>Scrolling</h3>
651  * <p>
652  * The framework provides basic support for views that wish to internally
653  * scroll their content. This includes keeping track of the X and Y scroll
654  * offset as well as mechanisms for drawing scrollbars. See
655  * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
656  * {@link #awakenScrollBars()} for more details.
657  * </p>
658  *
659  * <a name="Tags"></a>
660  * <h3>Tags</h3>
661  * <p>
662  * Unlike IDs, tags are not used to identify views. Tags are essentially an
663  * extra piece of information that can be associated with a view. They are most
664  * often used as a convenience to store data related to views in the views
665  * themselves rather than by putting them in a separate structure.
666  * </p>
667  * <p>
668  * Tags may be specified with character sequence values in layout XML as either
669  * a single tag using the {@link android.R.styleable#View_tag android:tag}
670  * attribute or multiple tags using the {@code <tag>} child element:
671  * <pre>
672  *     &lt;View ...
673  *           android:tag="@string/mytag_value" /&gt;
674  *     &lt;View ...&gt;
675  *         &lt;tag android:id="@+id/mytag"
676  *              android:value="@string/mytag_value" /&gt;
677  *     &lt;/View>
678  * </pre>
679  * </p>
680  * <p>
681  * Tags may also be specified with arbitrary objects from code using
682  * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
683  * </p>
684  *
685  * <a name="Themes"></a>
686  * <h3>Themes</h3>
687  * <p>
688  * By default, Views are created using the theme of the Context object supplied
689  * to their constructor; however, a different theme may be specified by using
690  * the {@link android.R.styleable#View_theme android:theme} attribute in layout
691  * XML or by passing a {@link ContextThemeWrapper} to the constructor from
692  * code.
693  * </p>
694  * <p>
695  * When the {@link android.R.styleable#View_theme android:theme} attribute is
696  * used in XML, the specified theme is applied on top of the inflation
697  * context's theme (see {@link LayoutInflater}) and used for the view itself as
698  * well as any child elements.
699  * </p>
700  * <p>
701  * In the following example, both views will be created using the Material dark
702  * color scheme; however, because an overlay theme is used which only defines a
703  * subset of attributes, the value of
704  * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
705  * the inflation context's theme (e.g. the Activity theme) will be preserved.
706  * <pre>
707  *     &lt;LinearLayout
708  *             ...
709  *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
710  *         &lt;View ...&gt;
711  *     &lt;/LinearLayout&gt;
712  * </pre>
713  * </p>
714  *
715  * <a name="Properties"></a>
716  * <h3>Properties</h3>
717  * <p>
718  * The View class exposes an {@link #ALPHA} property, as well as several transform-related
719  * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
720  * available both in the {@link Property} form as well as in similarly-named setter/getter
721  * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
722  * be used to set persistent state associated with these rendering-related properties on the view.
723  * The properties and methods can also be used in conjunction with
724  * {@link android.animation.Animator Animator}-based animations, described more in the
725  * <a href="#Animation">Animation</a> section.
726  * </p>
727  *
728  * <a name="Animation"></a>
729  * <h3>Animation</h3>
730  * <p>
731  * Starting with Android 3.0, the preferred way of animating views is to use the
732  * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
733  * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
734  * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
735  * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
736  * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
737  * makes animating these View properties particularly easy and efficient.
738  * </p>
739  * <p>
740  * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
741  * You can attach an {@link Animation} object to a view using
742  * {@link #setAnimation(Animation)} or
743  * {@link #startAnimation(Animation)}. The animation can alter the scale,
744  * rotation, translation and alpha of a view over time. If the animation is
745  * attached to a view that has children, the animation will affect the entire
746  * subtree rooted by that node. When an animation is started, the framework will
747  * take care of redrawing the appropriate views until the animation completes.
748  * </p>
749  *
750  * <a name="Security"></a>
751  * <h3>Security</h3>
752  * <p>
753  * Sometimes it is essential that an application be able to verify that an action
754  * is being performed with the full knowledge and consent of the user, such as
755  * granting a permission request, making a purchase or clicking on an advertisement.
756  * Unfortunately, a malicious application could try to spoof the user into
757  * performing these actions, unaware, by concealing the intended purpose of the view.
758  * As a remedy, the framework offers a touch filtering mechanism that can be used to
759  * improve the security of views that provide access to sensitive functionality.
760  * </p><p>
761  * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
762  * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
763  * will discard touches that are received whenever the view's window is obscured by
764  * another visible window at the touched location.  As a result, the view will not receive touches
765  * whenever the touch passed through a toast, dialog or other window that appears above the view's
766  * window.
767  * </p><p>
768  * For more fine-grained control over security, consider overriding the
769  * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
770  * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
771  * </p>
772  *
773  * @attr ref android.R.styleable#View_accessibilityHeading
774  * @attr ref android.R.styleable#View_allowClickWhenDisabled
775  * @attr ref android.R.styleable#View_alpha
776  * @attr ref android.R.styleable#View_background
777  * @attr ref android.R.styleable#View_clickable
778  * @attr ref android.R.styleable#View_clipToOutline
779  * @attr ref android.R.styleable#View_contentDescription
780  * @attr ref android.R.styleable#View_drawingCacheQuality
781  * @attr ref android.R.styleable#View_duplicateParentState
782  * @attr ref android.R.styleable#View_id
783  * @attr ref android.R.styleable#View_requiresFadingEdge
784  * @attr ref android.R.styleable#View_fadeScrollbars
785  * @attr ref android.R.styleable#View_fadingEdgeLength
786  * @attr ref android.R.styleable#View_filterTouchesWhenObscured
787  * @attr ref android.R.styleable#View_fitsSystemWindows
788  * @attr ref android.R.styleable#View_isScrollContainer
789  * @attr ref android.R.styleable#View_focusable
790  * @attr ref android.R.styleable#View_focusableInTouchMode
791  * @attr ref android.R.styleable#View_focusedByDefault
792  * @attr ref android.R.styleable#View_hapticFeedbackEnabled
793  * @attr ref android.R.styleable#View_keepScreenOn
794  * @attr ref android.R.styleable#View_keyboardNavigationCluster
795  * @attr ref android.R.styleable#View_layerType
796  * @attr ref android.R.styleable#View_layoutDirection
797  * @attr ref android.R.styleable#View_longClickable
798  * @attr ref android.R.styleable#View_minHeight
799  * @attr ref android.R.styleable#View_minWidth
800  * @attr ref android.R.styleable#View_nextClusterForward
801  * @attr ref android.R.styleable#View_nextFocusDown
802  * @attr ref android.R.styleable#View_nextFocusLeft
803  * @attr ref android.R.styleable#View_nextFocusRight
804  * @attr ref android.R.styleable#View_nextFocusUp
805  * @attr ref android.R.styleable#View_onClick
806  * @attr ref android.R.styleable#View_outlineSpotShadowColor
807  * @attr ref android.R.styleable#View_outlineAmbientShadowColor
808  * @attr ref android.R.styleable#View_padding
809  * @attr ref android.R.styleable#View_paddingHorizontal
810  * @attr ref android.R.styleable#View_paddingVertical
811  * @attr ref android.R.styleable#View_paddingBottom
812  * @attr ref android.R.styleable#View_paddingLeft
813  * @attr ref android.R.styleable#View_paddingRight
814  * @attr ref android.R.styleable#View_paddingTop
815  * @attr ref android.R.styleable#View_paddingStart
816  * @attr ref android.R.styleable#View_paddingEnd
817  * @attr ref android.R.styleable#View_saveEnabled
818  * @attr ref android.R.styleable#View_rotation
819  * @attr ref android.R.styleable#View_rotationX
820  * @attr ref android.R.styleable#View_rotationY
821  * @attr ref android.R.styleable#View_scaleX
822  * @attr ref android.R.styleable#View_scaleY
823  * @attr ref android.R.styleable#View_scrollX
824  * @attr ref android.R.styleable#View_scrollY
825  * @attr ref android.R.styleable#View_scrollbarSize
826  * @attr ref android.R.styleable#View_scrollbarStyle
827  * @attr ref android.R.styleable#View_scrollbars
828  * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
829  * @attr ref android.R.styleable#View_scrollbarFadeDuration
830  * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
831  * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
832  * @attr ref android.R.styleable#View_scrollbarThumbVertical
833  * @attr ref android.R.styleable#View_scrollbarTrackVertical
834  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
835  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
836  * @attr ref android.R.styleable#View_stateListAnimator
837  * @attr ref android.R.styleable#View_transitionName
838  * @attr ref android.R.styleable#View_soundEffectsEnabled
839  * @attr ref android.R.styleable#View_tag
840  * @attr ref android.R.styleable#View_textAlignment
841  * @attr ref android.R.styleable#View_textDirection
842  * @attr ref android.R.styleable#View_transformPivotX
843  * @attr ref android.R.styleable#View_transformPivotY
844  * @attr ref android.R.styleable#View_translationX
845  * @attr ref android.R.styleable#View_translationY
846  * @attr ref android.R.styleable#View_translationZ
847  * @attr ref android.R.styleable#View_visibility
848  * @attr ref android.R.styleable#View_theme
849  *
850  * @see android.view.ViewGroup
851  */
852 @UiThread
853 public class View implements Drawable.Callback, KeyEvent.Callback,
854         AccessibilityEventSource {
855     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
856     private static final boolean DBG = false;
857 
858     /** @hide */
859     public static boolean DEBUG_DRAW = false;
860 
861     /**
862      * The logging tag used by this class with android.util.Log.
863      */
864     protected static final String VIEW_LOG_TAG = "View";
865 
866     /**
867      * The logging tag used by this class when logging verbose, autofill-related messages.
868      */
869     // NOTE: We cannot use android.view.autofill.Helper.sVerbose because that variable is not
870     // set if a session is not started.
871     private static final String AUTOFILL_LOG_TAG = "View.Autofill";
872 
873     /**
874      * The logging tag used by this class when logging content capture-related messages.
875      */
876     private static final String CONTENT_CAPTURE_LOG_TAG = "View.ContentCapture";
877 
878     private static final boolean DEBUG_CONTENT_CAPTURE = false;
879 
880     /**
881      * When set to true, this view will save its attribute data.
882      *
883      * @hide
884      */
885     public static boolean sDebugViewAttributes = false;
886 
887     /**
888      * When set to this application package view will save its attribute data.
889      *
890      * @hide
891      */
892     public static String sDebugViewAttributesApplicationPackage;
893 
894     /**
895      * Used to mark a View that has no ID.
896      */
897     public static final int NO_ID = -1;
898 
899     /**
900      * Last ID that is given to Views that are no part of activities.
901      *
902      * {@hide}
903      */
904     public static final int LAST_APP_AUTOFILL_ID = Integer.MAX_VALUE / 2;
905 
906     /**
907      * Attribute to find the autofilled highlight
908      *
909      * @see #getAutofilledDrawable()
910      */
911     private static final int[] AUTOFILL_HIGHLIGHT_ATTR =
912             new int[]{android.R.attr.autofilledHighlight};
913 
914     /**
915      * Signals that compatibility booleans have been initialized according to
916      * target SDK versions.
917      */
918     private static boolean sCompatibilityDone = false;
919 
920     /**
921      * Use the old (broken) way of building MeasureSpecs.
922      */
923     private static boolean sUseBrokenMakeMeasureSpec = false;
924 
925     /**
926      * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
927      */
928     static boolean sUseZeroUnspecifiedMeasureSpec = false;
929 
930     /**
931      * Ignore any optimizations using the measure cache.
932      */
933     private static boolean sIgnoreMeasureCache = false;
934 
935     /**
936      * Ignore an optimization that skips unnecessary EXACTLY layout passes.
937      */
938     private static boolean sAlwaysRemeasureExactly = false;
939 
940     /**
941      * Allow setForeground/setBackground to be called (and ignored) on a textureview,
942      * without throwing
943      */
944     static boolean sTextureViewIgnoresDrawableSetters = false;
945 
946     /**
947      * Prior to N, some ViewGroups would not convert LayoutParams properly even though both extend
948      * MarginLayoutParams. For instance, converting LinearLayout.LayoutParams to
949      * RelativeLayout.LayoutParams would lose margin information. This is fixed on N but target API
950      * check is implemented for backwards compatibility.
951      *
952      * {@hide}
953      */
954     protected static boolean sPreserveMarginParamsInLayoutParamConversion;
955 
956     /**
957      * Prior to N, when drag enters into child of a view that has already received an
958      * ACTION_DRAG_ENTERED event, the parent doesn't get a ACTION_DRAG_EXITED event.
959      * ACTION_DRAG_LOCATION and ACTION_DROP were delivered to the parent of a view that returned
960      * false from its event handler for these events.
961      * Starting from N, the parent will get ACTION_DRAG_EXITED event before the child gets its
962      * ACTION_DRAG_ENTERED. ACTION_DRAG_LOCATION and ACTION_DROP are never propagated to the parent.
963      * sCascadedDragDrop is true for pre-N apps for backwards compatibility implementation.
964      */
965     static boolean sCascadedDragDrop;
966 
967     /**
968      * Prior to O, auto-focusable didn't exist and widgets such as ListView use hasFocusable
969      * to determine things like whether or not to permit item click events. We can't break
970      * apps that do this just because more things (clickable things) are now auto-focusable
971      * and they would get different results, so give old behavior to old apps.
972      */
973     static boolean sHasFocusableExcludeAutoFocusable;
974 
975     /**
976      * Prior to O, auto-focusable didn't exist and views marked as clickable weren't implicitly
977      * made focusable by default. As a result, apps could (incorrectly) change the clickable
978      * setting of views off the UI thread. Now that clickable can effect the focusable state,
979      * changing the clickable attribute off the UI thread will cause an exception (since changing
980      * the focusable state checks). In order to prevent apps from crashing, we will handle this
981      * specific case and just not notify parents on new focusables resulting from marking views
982      * clickable from outside the UI thread.
983      */
984     private static boolean sAutoFocusableOffUIThreadWontNotifyParents;
985 
986     /**
987      * Prior to P things like setScaleX() allowed passing float values that were bogus such as
988      * Float.NaN. If the app is targetting P or later then passing these values will result in an
989      * exception being thrown. If the app is targetting an earlier SDK version, then we will
990      * silently clamp these values to avoid crashes elsewhere when the rendering code hits
991      * these bogus values.
992      */
993     private static boolean sThrowOnInvalidFloatProperties;
994 
995     /**
996      * Prior to P, {@code #startDragAndDrop} accepts a builder which produces an empty drag shadow.
997      * Currently zero size SurfaceControl cannot be created thus we create a 1x1 surface instead.
998      */
999     private static boolean sAcceptZeroSizeDragShadow;
1000 
1001     /**
1002      * When true, measure and layout passes of all the newly attached views will be logged with
1003      * {@link Trace}, so we can better debug jank due to complex view hierarchies.
1004      */
1005     private static boolean sTraceLayoutSteps;
1006 
1007     /**
1008      * When not null, emits a {@link Trace} instant event and the stacktrace every time a relayout
1009      * of a class having this name happens.
1010      */
1011     private static String sTraceRequestLayoutClass;
1012 
1013     /** Used to avoid computing the full strings each time when layout tracing is enabled. */
1014     @Nullable
1015     private ViewTraversalTracingStrings mTracingStrings;
1016 
1017     /**
1018      * Prior to R, {@link #dispatchApplyWindowInsets} had an issue:
1019      * <p>The modified insets changed by {@link #onApplyWindowInsets} were passed to the
1020      * entire view hierarchy in prefix order, including siblings as well as siblings of parents
1021      * further down the hierarchy. This violates the basic concepts of the view hierarchy, and
1022      * thus, the hierarchical dispatching mechanism was hard to use for apps.
1023      * <p>
1024      * In order to make window inset dispatching work properly, we dispatch window insets
1025      * in the view hierarchy in a proper hierarchical manner if this flag is set to {@code false}.
1026      */
1027     static boolean sBrokenInsetsDispatch;
1028 
1029     /**
1030      * Prior to Q, calling
1031      * {@link com.android.internal.policy.DecorView#setBackgroundDrawable(Drawable)}
1032      * did not call update the window format so the opacity of the background was not correctly
1033      * applied to the window. Some applications rely on this misbehavior to work properly.
1034      * <p>
1035      * From Q, {@link com.android.internal.policy.DecorView#setBackgroundDrawable(Drawable)} is
1036      * the same as {@link com.android.internal.policy.DecorView#setWindowBackground(Drawable)}
1037      * which updates the window format.
1038      * @hide
1039      */
1040     protected static boolean sBrokenWindowBackground;
1041 
1042     /**
1043      * Prior to R, we were always forcing a layout of the entire hierarchy when insets changed from
1044      * the server. This is inefficient and not all apps use it. Instead, we want to rely on apps
1045      * calling {@link #requestLayout} when they need to relayout based on an insets change.
1046      */
1047     static boolean sForceLayoutWhenInsetsChanged;
1048 
1049     /** @hide */
1050     @IntDef({NOT_FOCUSABLE, FOCUSABLE, FOCUSABLE_AUTO})
1051     @Retention(RetentionPolicy.SOURCE)
1052     public @interface Focusable {}
1053 
1054     /**
1055      * This view does not want keystrokes.
1056      * <p>
1057      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
1058      * android:focusable}.
1059      */
1060     public static final int NOT_FOCUSABLE = 0x00000000;
1061 
1062     /**
1063      * This view wants keystrokes.
1064      * <p>
1065      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
1066      * android:focusable}.
1067      */
1068     public static final int FOCUSABLE = 0x00000001;
1069 
1070     /**
1071      * This view determines focusability automatically. This is the default.
1072      * <p>
1073      * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
1074      * android:focusable}.
1075      */
1076     public static final int FOCUSABLE_AUTO = 0x00000010;
1077 
1078     /**
1079      * Mask for use with setFlags indicating bits used for focus.
1080      */
1081     private static final int FOCUSABLE_MASK = 0x00000011;
1082 
1083     /**
1084      * This view will adjust its padding to fit sytem windows (e.g. status bar)
1085      */
1086     private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
1087 
1088     /** @hide */
1089     @IntDef({VISIBLE, INVISIBLE, GONE})
1090     @Retention(RetentionPolicy.SOURCE)
1091     public @interface Visibility {}
1092 
1093     /**
1094      * This view is visible.
1095      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
1096      * android:visibility}.
1097      */
1098     public static final int VISIBLE = 0x00000000;
1099 
1100     /**
1101      * This view is invisible, but it still takes up space for layout purposes.
1102      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
1103      * android:visibility}.
1104      */
1105     public static final int INVISIBLE = 0x00000004;
1106 
1107     /**
1108      * This view is invisible, and it doesn't take any space for layout
1109      * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
1110      * android:visibility}.
1111      */
1112     public static final int GONE = 0x00000008;
1113 
1114     /**
1115      * Mask for use with setFlags indicating bits used for visibility.
1116      * {@hide}
1117      */
1118     static final int VISIBILITY_MASK = 0x0000000C;
1119 
1120     private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
1121 
1122     /**
1123      * Hint indicating that this view can be autofilled with an email address.
1124      *
1125      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1126      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1127      * value should be <code>{@value #AUTOFILL_HINT_EMAIL_ADDRESS}</code>).
1128      *
1129      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1130      */
1131     public static final String AUTOFILL_HINT_EMAIL_ADDRESS = "emailAddress";
1132 
1133     /**
1134      * Hint indicating that this view can be autofilled with a user's real name.
1135      *
1136      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1137      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1138      * value should be <code>{@value #AUTOFILL_HINT_NAME}</code>).
1139      *
1140      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1141      */
1142     public static final String AUTOFILL_HINT_NAME = "name";
1143 
1144     /**
1145      * Hint indicating that this view can be autofilled with a username.
1146      *
1147      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1148      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1149      * value should be <code>{@value #AUTOFILL_HINT_USERNAME}</code>).
1150      *
1151      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1152      */
1153     public static final String AUTOFILL_HINT_USERNAME = "username";
1154 
1155     /**
1156      * Hint indicating that this view can be autofilled with a password.
1157      *
1158      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1159      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1160      * value should be <code>{@value #AUTOFILL_HINT_PASSWORD}</code>).
1161      *
1162      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1163      */
1164     public static final String AUTOFILL_HINT_PASSWORD = "password";
1165 
1166     /**
1167      * Hint indicating that this view can be autofilled with a phone number.
1168      *
1169      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1170      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1171      * value should be <code>{@value #AUTOFILL_HINT_PHONE}</code>).
1172      *
1173      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1174      */
1175     public static final String AUTOFILL_HINT_PHONE = "phone";
1176 
1177     /**
1178      * Hint indicating that this view can be autofilled with a postal address.
1179      *
1180      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1181      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1182      * value should be <code>{@value #AUTOFILL_HINT_POSTAL_ADDRESS}</code>).
1183      *
1184      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1185      */
1186     public static final String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress";
1187 
1188     /**
1189      * Hint indicating that this view can be autofilled with a postal code.
1190      *
1191      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1192      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1193      * value should be <code>{@value #AUTOFILL_HINT_POSTAL_CODE}</code>).
1194      *
1195      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1196      */
1197     public static final String AUTOFILL_HINT_POSTAL_CODE = "postalCode";
1198 
1199     /**
1200      * Hint indicating that this view can be autofilled with a credit card number.
1201      *
1202      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1203      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1204      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_NUMBER}</code>).
1205      *
1206      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1207      */
1208     public static final String AUTOFILL_HINT_CREDIT_CARD_NUMBER = "creditCardNumber";
1209 
1210     /**
1211      * Hint indicating that this view can be autofilled with a credit card security code.
1212      *
1213      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1214      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1215      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE}</code>).
1216      *
1217      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1218      */
1219     public static final String AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE = "creditCardSecurityCode";
1220 
1221     /**
1222      * Hint indicating that this view can be autofilled with a credit card expiration date.
1223      *
1224      * <p>It should be used when the credit card expiration date is represented by just one view;
1225      * if it is represented by more than one (for example, one view for the month and another view
1226      * for the year), then each of these views should use the hint specific for the unit
1227      * ({@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
1228      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH},
1229      * or {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}).
1230      *
1231      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1232      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1233      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE}</code>).
1234      *
1235      * <p>When annotating a view with this hint, it's recommended to use a date autofill value to
1236      * avoid ambiguity when the autofill service provides a value for it. To understand why a
1237      * value can be ambiguous, consider "April of 2020", which could be represented as either of
1238      * the following options:
1239      *
1240      * <ul>
1241      *   <li>{@code "04/2020"}
1242      *   <li>{@code "4/2020"}
1243      *   <li>{@code "2020/04"}
1244      *   <li>{@code "2020/4"}
1245      *   <li>{@code "April/2020"}
1246      *   <li>{@code "Apr/2020"}
1247      * </ul>
1248      *
1249      * <p>You define a date autofill value for the view by overriding the following methods:
1250      *
1251      * <ol>
1252      *   <li>{@link #getAutofillType()} to return {@link #AUTOFILL_TYPE_DATE}.
1253      *   <li>{@link #getAutofillValue()} to return a
1254      *       {@link AutofillValue#forDate(long) date autofillvalue}.
1255      *   <li>{@link #autofill(AutofillValue)} to expect a data autofillvalue.
1256      * </ol>
1257      *
1258      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1259      */
1260     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE =
1261             "creditCardExpirationDate";
1262 
1263     /**
1264      * Hint indicating that this view can be autofilled with a credit card expiration month.
1265      *
1266      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1267      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1268      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH}</code>).
1269      *
1270      * <p>When annotating a view with this hint, it's recommended to use a text autofill value
1271      * whose value is the numerical representation of the month, starting on {@code 1} to avoid
1272      * ambiguity when the autofill service provides a value for it. To understand why a
1273      * value can be ambiguous, consider "January", which could be represented as either of
1274      *
1275      * <ul>
1276      *   <li>{@code "1"}: recommended way.
1277      *   <li>{@code "0"}: if following the {@link Calendar#MONTH} convention.
1278      *   <li>{@code "January"}: full name, in English.
1279      *   <li>{@code "jan"}: abbreviated name, in English.
1280      *   <li>{@code "Janeiro"}: full name, in another language.
1281      * </ul>
1282      *
1283      * <p>Another recommended approach is to use a date autofill value - see
1284      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE} for more details.
1285      *
1286      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1287      */
1288     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH =
1289             "creditCardExpirationMonth";
1290 
1291     /**
1292      * Hint indicating that this view can be autofilled with a credit card expiration year.
1293      *
1294      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1295      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1296      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}</code>).
1297      *
1298      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1299      */
1300     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR =
1301             "creditCardExpirationYear";
1302 
1303     /**
1304      * Hint indicating that this view can be autofilled with a credit card expiration day.
1305      *
1306      * <p>Can be used with either {@link #setAutofillHints(String[])} or
1307      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1308      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY}</code>).
1309      *
1310      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1311      */
1312     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY = "creditCardExpirationDay";
1313 
1314     /**
1315      * A hint indicating that this view can be autofilled with a password.
1316      *
1317      * This is a heuristic-based hint that is meant to be used by UI Toolkit developers when a
1318      * view is a password field but doesn't specify a
1319      * <code>{@value View#AUTOFILL_HINT_PASSWORD}</code>.
1320      * @hide
1321      */
1322     // TODO(229765029): unhide this for UI toolkit
1323     public static final String AUTOFILL_HINT_PASSWORD_AUTO = "passwordAuto";
1324 
1325     /**
1326      * Hints for the autofill services that describes the content of the view.
1327      */
1328     private @Nullable String[] mAutofillHints;
1329 
1330     /**
1331      * Autofill id, lazily created on calls to {@link #getAutofillId()}.
1332      */
1333     private AutofillId mAutofillId;
1334 
1335     /** @hide */
1336     @IntDef(prefix = { "AUTOFILL_TYPE_" }, value = {
1337             AUTOFILL_TYPE_NONE,
1338             AUTOFILL_TYPE_TEXT,
1339             AUTOFILL_TYPE_TOGGLE,
1340             AUTOFILL_TYPE_LIST,
1341             AUTOFILL_TYPE_DATE,
1342     })
1343     @Retention(RetentionPolicy.SOURCE)
1344     public @interface AutofillType {}
1345 
1346     /**
1347      * Autofill type for views that cannot be autofilled.
1348      *
1349      * <p>Typically used when the view is read-only; for example, a text label.
1350      *
1351      * @see #getAutofillType()
1352      */
1353     public static final int AUTOFILL_TYPE_NONE = 0;
1354 
1355     /**
1356      * Autofill type for a text field, which is filled by a {@link CharSequence}.
1357      *
1358      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1359      * {@link AutofillValue#forText(CharSequence)}, and the value passed to autofill a
1360      * {@link View} can be fetched through {@link AutofillValue#getTextValue()}.
1361      *
1362      * @see #getAutofillType()
1363      */
1364     public static final int AUTOFILL_TYPE_TEXT = 1;
1365 
1366     /**
1367      * Autofill type for a togglable field, which is filled by a {@code boolean}.
1368      *
1369      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1370      * {@link AutofillValue#forToggle(boolean)}, and the value passed to autofill a
1371      * {@link View} can be fetched through {@link AutofillValue#getToggleValue()}.
1372      *
1373      * @see #getAutofillType()
1374      */
1375     public static final int AUTOFILL_TYPE_TOGGLE = 2;
1376 
1377     /**
1378      * Autofill type for a selection list field, which is filled by an {@code int}
1379      * representing the element index inside the list (starting at {@code 0}).
1380      *
1381      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1382      * {@link AutofillValue#forList(int)}, and the value passed to autofill a
1383      * {@link View} can be fetched through {@link AutofillValue#getListValue()}.
1384      *
1385      * <p>The available options in the selection list are typically provided by
1386      * {@link android.app.assist.AssistStructure.ViewNode#getAutofillOptions()}.
1387      *
1388      * @see #getAutofillType()
1389      */
1390     public static final int AUTOFILL_TYPE_LIST = 3;
1391 
1392     /**
1393      * Autofill type for a field that contains a date, which is represented by a long representing
1394      * the number of milliseconds since the standard base time known as "the epoch", namely
1395      * January 1, 1970, 00:00:00 GMT (see {@link java.util.Date#getTime()}.
1396      *
1397      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1398      * {@link AutofillValue#forDate(long)}, and the values passed to
1399      * autofill a {@link View} can be fetched through {@link AutofillValue#getDateValue()}.
1400      *
1401      * @see #getAutofillType()
1402      */
1403     public static final int AUTOFILL_TYPE_DATE = 4;
1404 
1405 
1406     /** @hide */
1407     @IntDef(prefix = { "IMPORTANT_FOR_AUTOFILL_" }, value = {
1408             IMPORTANT_FOR_AUTOFILL_AUTO,
1409             IMPORTANT_FOR_AUTOFILL_YES,
1410             IMPORTANT_FOR_AUTOFILL_NO,
1411             IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
1412             IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
1413     })
1414     @Retention(RetentionPolicy.SOURCE)
1415     public @interface AutofillImportance {}
1416 
1417     /**
1418      * Automatically determine whether a view is important for autofill.
1419      *
1420      * @see #isImportantForAutofill()
1421      * @see #setImportantForAutofill(int)
1422      */
1423     public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0x0;
1424 
1425     /**
1426      * The view is important for autofill, and its children (if any) will be traversed.
1427      *
1428      * @see #isImportantForAutofill()
1429      * @see #setImportantForAutofill(int)
1430      */
1431     public static final int IMPORTANT_FOR_AUTOFILL_YES = 0x1;
1432 
1433     /**
1434      * The view is not important for autofill, but its children (if any) will be traversed.
1435      *
1436      * @see #isImportantForAutofill()
1437      * @see #setImportantForAutofill(int)
1438      */
1439     public static final int IMPORTANT_FOR_AUTOFILL_NO = 0x2;
1440 
1441     /**
1442      * The view is important for autofill, but its children (if any) will not be traversed.
1443      *
1444      * @see #isImportantForAutofill()
1445      * @see #setImportantForAutofill(int)
1446      */
1447     public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 0x4;
1448 
1449     /**
1450      * The view is not important for autofill, and its children (if any) will not be traversed.
1451      *
1452      * @see #isImportantForAutofill()
1453      * @see #setImportantForAutofill(int)
1454      */
1455     public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 0x8;
1456 
1457     /** @hide */
1458     @IntDef(flag = true, prefix = { "AUTOFILL_FLAG_" }, value = {
1459             AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
1460     })
1461     @Retention(RetentionPolicy.SOURCE)
1462     public @interface AutofillFlags {}
1463 
1464     /**
1465      * Flag requesting you to add views that are marked as not important for autofill
1466      * (see {@link #setImportantForAutofill(int)}) to a {@link ViewStructure}.
1467      */
1468     public static final int AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x1;
1469 
1470     /** @hide */
1471     @IntDef(prefix = { "IMPORTANT_FOR_CONTENT_CAPTURE_" }, value = {
1472             IMPORTANT_FOR_CONTENT_CAPTURE_AUTO,
1473             IMPORTANT_FOR_CONTENT_CAPTURE_YES,
1474             IMPORTANT_FOR_CONTENT_CAPTURE_NO,
1475             IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
1476             IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
1477     })
1478     @Retention(RetentionPolicy.SOURCE)
1479     public @interface ContentCaptureImportance {}
1480 
1481     /**
1482      * Automatically determine whether a view is important for content capture.
1483      *
1484      * @see #isImportantForContentCapture()
1485      * @see #setImportantForContentCapture(int)
1486      */
1487     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_AUTO = 0x0;
1488 
1489     /**
1490      * The view is important for content capture, and its children (if any) will be traversed.
1491      *
1492      * @see #isImportantForContentCapture()
1493      * @see #setImportantForContentCapture(int)
1494      */
1495     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES = 0x1;
1496 
1497     /**
1498      * The view is not important for content capture, but its children (if any) will be traversed.
1499      *
1500      * @see #isImportantForContentCapture()
1501      * @see #setImportantForContentCapture(int)
1502      */
1503     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO = 0x2;
1504 
1505     /**
1506      * The view is important for content capture, but its children (if any) will not be traversed.
1507      *
1508      * @see #isImportantForContentCapture()
1509      * @see #setImportantForContentCapture(int)
1510      */
1511     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS = 0x4;
1512 
1513     /**
1514      * The view is not important for content capture, and its children (if any) will not be
1515      * traversed.
1516      *
1517      * @see #isImportantForContentCapture()
1518      * @see #setImportantForContentCapture(int)
1519      */
1520     public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS = 0x8;
1521 
1522     /** {@hide} */
1523     @IntDef(flag = true, prefix = {"SCROLL_CAPTURE_HINT_"},
1524             value = {
1525                     SCROLL_CAPTURE_HINT_AUTO,
1526                     SCROLL_CAPTURE_HINT_EXCLUDE,
1527                     SCROLL_CAPTURE_HINT_INCLUDE,
1528                     SCROLL_CAPTURE_HINT_EXCLUDE_DESCENDANTS
1529     })
1530     @Retention(RetentionPolicy.SOURCE)
1531     public @interface ScrollCaptureHint {}
1532 
1533     /**
1534      * The content of this view will be considered for scroll capture if scrolling is possible.
1535      *
1536      * @see #getScrollCaptureHint()
1537      * @see #setScrollCaptureHint(int)
1538      */
1539     public static final int SCROLL_CAPTURE_HINT_AUTO = 0;
1540 
1541     /**
1542      * Explicitly exclude this view as a potential scroll capture target. The system will not
1543      * consider it. Mutually exclusive with {@link #SCROLL_CAPTURE_HINT_INCLUDE}, which this flag
1544      * takes precedence over.
1545      *
1546      * @see #getScrollCaptureHint()
1547      * @see #setScrollCaptureHint(int)
1548      */
1549     public static final int SCROLL_CAPTURE_HINT_EXCLUDE = 0x1;
1550 
1551     /**
1552      * Explicitly include this view as a potential scroll capture target. When locating a scroll
1553      * capture target, this view will be prioritized before others without this flag. Mutually
1554      * exclusive with {@link #SCROLL_CAPTURE_HINT_EXCLUDE}, which takes precedence.
1555      *
1556      * @see #getScrollCaptureHint()
1557      * @see #setScrollCaptureHint(int)
1558      */
1559     public static final int SCROLL_CAPTURE_HINT_INCLUDE = 0x2;
1560 
1561     /**
1562      * Explicitly exclude all children of this view as potential scroll capture targets. This view
1563      * is unaffected. Note: Excluded children are not considered, regardless of {@link
1564      * #SCROLL_CAPTURE_HINT_INCLUDE}.
1565      *
1566      * @see #getScrollCaptureHint()
1567      * @see #setScrollCaptureHint(int)
1568      */
1569     public static final int SCROLL_CAPTURE_HINT_EXCLUDE_DESCENDANTS = 0x4;
1570 
1571     /**
1572      * This view is enabled. Interpretation varies by subclass.
1573      * Use with ENABLED_MASK when calling setFlags.
1574      * {@hide}
1575      */
1576     static final int ENABLED = 0x00000000;
1577 
1578     /**
1579      * This view is disabled. Interpretation varies by subclass.
1580      * Use with ENABLED_MASK when calling setFlags.
1581      * {@hide}
1582      */
1583     static final int DISABLED = 0x00000020;
1584 
1585    /**
1586     * Mask for use with setFlags indicating bits used for indicating whether
1587     * this view is enabled
1588     * {@hide}
1589     */
1590     static final int ENABLED_MASK = 0x00000020;
1591 
1592     /**
1593      * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
1594      * called and further optimizations will be performed. It is okay to have
1595      * this flag set and a background. Use with DRAW_MASK when calling setFlags.
1596      * {@hide}
1597      */
1598     static final int WILL_NOT_DRAW = 0x00000080;
1599 
1600     /**
1601      * Mask for use with setFlags indicating bits used for indicating whether
1602      * this view is will draw
1603      * {@hide}
1604      */
1605     static final int DRAW_MASK = 0x00000080;
1606 
1607     /**
1608      * <p>This view doesn't show scrollbars.</p>
1609      * {@hide}
1610      */
1611     static final int SCROLLBARS_NONE = 0x00000000;
1612 
1613     /**
1614      * <p>This view shows horizontal scrollbars.</p>
1615      * {@hide}
1616      */
1617     static final int SCROLLBARS_HORIZONTAL = 0x00000100;
1618 
1619     /**
1620      * <p>This view shows vertical scrollbars.</p>
1621      * {@hide}
1622      */
1623     static final int SCROLLBARS_VERTICAL = 0x00000200;
1624 
1625     /**
1626      * <p>Mask for use with setFlags indicating bits used for indicating which
1627      * scrollbars are enabled.</p>
1628      * {@hide}
1629      */
1630     static final int SCROLLBARS_MASK = 0x00000300;
1631 
1632     /**
1633      * Indicates that the view should filter touches when its window is obscured.
1634      * Refer to the class comments for more information about this security feature.
1635      * {@hide}
1636      */
1637     static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
1638 
1639     /**
1640      * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
1641      * that they are optional and should be skipped if the window has
1642      * requested system UI flags that ignore those insets for layout.
1643      * <p>
1644      * This is only used for support library as of Android R. The framework now uses
1645      * {@link #PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS} such that it can skip the legacy
1646      * insets path that loses insets information.
1647      */
1648     static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
1649 
1650     /**
1651      * <p>This view doesn't show fading edges.</p>
1652      * {@hide}
1653      */
1654     static final int FADING_EDGE_NONE = 0x00000000;
1655 
1656     /**
1657      * <p>This view shows horizontal fading edges.</p>
1658      * {@hide}
1659      */
1660     static final int FADING_EDGE_HORIZONTAL = 0x00001000;
1661 
1662     /**
1663      * <p>This view shows vertical fading edges.</p>
1664      * {@hide}
1665      */
1666     static final int FADING_EDGE_VERTICAL = 0x00002000;
1667 
1668     /**
1669      * <p>Mask for use with setFlags indicating bits used for indicating which
1670      * fading edges are enabled.</p>
1671      * {@hide}
1672      */
1673     static final int FADING_EDGE_MASK = 0x00003000;
1674 
1675     /**
1676      * <p>Indicates this view can be clicked. When clickable, a View reacts
1677      * to clicks by notifying the OnClickListener.<p>
1678      * {@hide}
1679      */
1680     static final int CLICKABLE = 0x00004000;
1681 
1682     /**
1683      * <p>Indicates this view is caching its drawing into a bitmap.</p>
1684      * {@hide}
1685      */
1686     static final int DRAWING_CACHE_ENABLED = 0x00008000;
1687 
1688     /**
1689      * <p>Indicates that no icicle should be saved for this view.<p>
1690      * {@hide}
1691      */
1692     static final int SAVE_DISABLED = 0x000010000;
1693 
1694     /**
1695      * <p>Mask for use with setFlags indicating bits used for the saveEnabled
1696      * property.</p>
1697      * {@hide}
1698      */
1699     static final int SAVE_DISABLED_MASK = 0x000010000;
1700 
1701     /**
1702      * <p>Indicates that no drawing cache should ever be created for this view.<p>
1703      * {@hide}
1704      */
1705     static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
1706 
1707     /**
1708      * <p>Indicates this view can take / keep focus when int touch mode.</p>
1709      * {@hide}
1710      */
1711     static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
1712 
1713     /** @hide */
1714     @Retention(RetentionPolicy.SOURCE)
1715     @IntDef(prefix = { "DRAWING_CACHE_QUALITY_" }, value = {
1716             DRAWING_CACHE_QUALITY_LOW,
1717             DRAWING_CACHE_QUALITY_HIGH,
1718             DRAWING_CACHE_QUALITY_AUTO
1719     })
1720     public @interface DrawingCacheQuality {}
1721 
1722     /**
1723      * <p>Enables low quality mode for the drawing cache.</p>
1724      *
1725      * @deprecated The view drawing cache was largely made obsolete with the introduction of
1726      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
1727      * layers are largely unnecessary and can easily result in a net loss in performance due to the
1728      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
1729      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
1730      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
1731      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
1732      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
1733      * software-rendered usages are discouraged and have compatibility issues with hardware-only
1734      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
1735      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
1736      * reports or unit testing the {@link PixelCopy} API is recommended.
1737      */
1738     @Deprecated
1739     public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
1740 
1741     /**
1742      * <p>Enables high quality mode for the drawing cache.</p>
1743      *
1744      * @deprecated The view drawing cache was largely made obsolete with the introduction of
1745      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
1746      * layers are largely unnecessary and can easily result in a net loss in performance due to the
1747      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
1748      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
1749      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
1750      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
1751      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
1752      * software-rendered usages are discouraged and have compatibility issues with hardware-only
1753      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
1754      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
1755      * reports or unit testing the {@link PixelCopy} API is recommended.
1756      */
1757     @Deprecated
1758     public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
1759 
1760     /**
1761      * <p>Enables automatic quality mode for the drawing cache.</p>
1762      *
1763      * @deprecated The view drawing cache was largely made obsolete with the introduction of
1764      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
1765      * layers are largely unnecessary and can easily result in a net loss in performance due to the
1766      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
1767      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
1768      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
1769      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
1770      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
1771      * software-rendered usages are discouraged and have compatibility issues with hardware-only
1772      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
1773      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
1774      * reports or unit testing the {@link PixelCopy} API is recommended.
1775      */
1776     @Deprecated
1777     public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
1778 
1779     private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
1780             DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
1781     };
1782 
1783     /**
1784      * <p>Mask for use with setFlags indicating bits used for the cache
1785      * quality property.</p>
1786      * {@hide}
1787      */
1788     static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
1789 
1790     /**
1791      * <p>
1792      * Indicates this view can be long clicked. When long clickable, a View
1793      * reacts to long clicks by notifying the OnLongClickListener or showing a
1794      * context menu.
1795      * </p>
1796      * {@hide}
1797      */
1798     static final int LONG_CLICKABLE = 0x00200000;
1799 
1800     /**
1801      * <p>Indicates that this view gets its drawable states from its direct parent
1802      * and ignores its original internal states.</p>
1803      *
1804      * @hide
1805      */
1806     static final int DUPLICATE_PARENT_STATE = 0x00400000;
1807 
1808     /**
1809      * <p>
1810      * Indicates this view can be context clicked. When context clickable, a View reacts to a
1811      * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1812      * OnContextClickListener.
1813      * </p>
1814      * {@hide}
1815      */
1816     static final int CONTEXT_CLICKABLE = 0x00800000;
1817 
1818     /** @hide */
1819     @IntDef(prefix = { "SCROLLBARS_" }, value = {
1820             SCROLLBARS_INSIDE_OVERLAY,
1821             SCROLLBARS_INSIDE_INSET,
1822             SCROLLBARS_OUTSIDE_OVERLAY,
1823             SCROLLBARS_OUTSIDE_INSET
1824     })
1825     @Retention(RetentionPolicy.SOURCE)
1826     public @interface ScrollBarStyle {}
1827 
1828     /**
1829      * The scrollbar style to display the scrollbars inside the content area,
1830      * without increasing the padding. The scrollbars will be overlaid with
1831      * translucency on the view's content.
1832      */
1833     public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1834 
1835     /**
1836      * The scrollbar style to display the scrollbars inside the padded area,
1837      * increasing the padding of the view. The scrollbars will not overlap the
1838      * content area of the view.
1839      */
1840     public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1841 
1842     /**
1843      * The scrollbar style to display the scrollbars at the edge of the view,
1844      * without increasing the padding. The scrollbars will be overlaid with
1845      * translucency.
1846      */
1847     public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1848 
1849     /**
1850      * The scrollbar style to display the scrollbars at the edge of the view,
1851      * increasing the padding of the view. The scrollbars will only overlap the
1852      * background, if any.
1853      */
1854     public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1855 
1856     /**
1857      * Mask to check if the scrollbar style is overlay or inset.
1858      * {@hide}
1859      */
1860     static final int SCROLLBARS_INSET_MASK = 0x01000000;
1861 
1862     /**
1863      * Mask to check if the scrollbar style is inside or outside.
1864      * {@hide}
1865      */
1866     static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1867 
1868     /**
1869      * Mask for scrollbar style.
1870      * {@hide}
1871      */
1872     static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1873 
1874     /**
1875      * View flag indicating that the screen should remain on while the
1876      * window containing this view is visible to the user.  This effectively
1877      * takes care of automatically setting the WindowManager's
1878      * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1879      */
1880     public static final int KEEP_SCREEN_ON = 0x04000000;
1881 
1882     /**
1883      * View flag indicating whether this view should have sound effects enabled
1884      * for events such as clicking and touching.
1885      */
1886     public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1887 
1888     /**
1889      * View flag indicating whether this view should have haptic feedback
1890      * enabled for events such as long presses.
1891      */
1892     public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1893 
1894     /**
1895      * <p>Indicates that the view hierarchy should stop saving state when
1896      * it reaches this view.  If state saving is initiated immediately at
1897      * the view, it will be allowed.
1898      * {@hide}
1899      */
1900     static final int PARENT_SAVE_DISABLED = 0x20000000;
1901 
1902     /**
1903      * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1904      * {@hide}
1905      */
1906     static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1907 
1908     private static Paint sDebugPaint;
1909 
1910     /**
1911      * <p>Indicates this view can display a tooltip on hover or long press.</p>
1912      * {@hide}
1913      */
1914     static final int TOOLTIP = 0x40000000;
1915 
1916     /** @hide */
1917     @IntDef(flag = true, prefix = { "FOCUSABLES_" }, value = {
1918             FOCUSABLES_ALL,
1919             FOCUSABLES_TOUCH_MODE
1920     })
1921     @Retention(RetentionPolicy.SOURCE)
1922     public @interface FocusableMode {}
1923 
1924     /**
1925      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1926      * should add all focusable Views regardless if they are focusable in touch mode.
1927      */
1928     public static final int FOCUSABLES_ALL = 0x00000000;
1929 
1930     /**
1931      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1932      * should add only Views focusable in touch mode.
1933      */
1934     public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1935 
1936     /** @hide */
1937     @IntDef(prefix = { "FOCUS_" }, value = {
1938             FOCUS_BACKWARD,
1939             FOCUS_FORWARD,
1940             FOCUS_LEFT,
1941             FOCUS_UP,
1942             FOCUS_RIGHT,
1943             FOCUS_DOWN
1944     })
1945     @Retention(RetentionPolicy.SOURCE)
1946     public @interface FocusDirection {}
1947 
1948     /** @hide */
1949     @IntDef(prefix = { "FOCUS_" }, value = {
1950             FOCUS_LEFT,
1951             FOCUS_UP,
1952             FOCUS_RIGHT,
1953             FOCUS_DOWN
1954     })
1955     @Retention(RetentionPolicy.SOURCE)
1956     public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1957 
1958     /**
1959      * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1960      * item.
1961      */
1962     public static final int FOCUS_BACKWARD = 0x00000001;
1963 
1964     /**
1965      * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1966      * item.
1967      */
1968     public static final int FOCUS_FORWARD = 0x00000002;
1969 
1970     /**
1971      * Use with {@link #focusSearch(int)}. Move focus to the left.
1972      */
1973     public static final int FOCUS_LEFT = 0x00000011;
1974 
1975     /**
1976      * Use with {@link #focusSearch(int)}. Move focus up.
1977      */
1978     public static final int FOCUS_UP = 0x00000021;
1979 
1980     /**
1981      * Use with {@link #focusSearch(int)}. Move focus to the right.
1982      */
1983     public static final int FOCUS_RIGHT = 0x00000042;
1984 
1985     /**
1986      * Use with {@link #focusSearch(int)}. Move focus down.
1987      */
1988     public static final int FOCUS_DOWN = 0x00000082;
1989 
1990     /**
1991      * Bits of {@link #getMeasuredWidthAndState()} and
1992      * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1993      */
1994     public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1995 
1996     /**
1997      * Bits of {@link #getMeasuredWidthAndState()} and
1998      * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1999      */
2000     public static final int MEASURED_STATE_MASK = 0xff000000;
2001 
2002     /**
2003      * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
2004      * for functions that combine both width and height into a single int,
2005      * such as {@link #getMeasuredState()} and the childState argument of
2006      * {@link #resolveSizeAndState(int, int, int)}.
2007      */
2008     public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
2009 
2010     /**
2011      * Bit of {@link #getMeasuredWidthAndState()} and
2012      * {@link #getMeasuredWidthAndState()} that indicates the measured size
2013      * is smaller that the space the view would like to have.
2014      */
2015     public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
2016 
2017     /**
2018      * Base View state sets
2019      */
2020     // Singles
2021     /**
2022      * Indicates the view has no states set. States are used with
2023      * {@link android.graphics.drawable.Drawable} to change the drawing of the
2024      * view depending on its state.
2025      *
2026      * @see android.graphics.drawable.Drawable
2027      * @see #getDrawableState()
2028      */
2029     protected static final int[] EMPTY_STATE_SET;
2030     /**
2031      * Indicates the view is enabled. States are used with
2032      * {@link android.graphics.drawable.Drawable} to change the drawing of the
2033      * view depending on its state.
2034      *
2035      * @see android.graphics.drawable.Drawable
2036      * @see #getDrawableState()
2037      */
2038     protected static final int[] ENABLED_STATE_SET;
2039     /**
2040      * Indicates the view is focused. States are used with
2041      * {@link android.graphics.drawable.Drawable} to change the drawing of the
2042      * view depending on its state.
2043      *
2044      * @see android.graphics.drawable.Drawable
2045      * @see #getDrawableState()
2046      */
2047     protected static final int[] FOCUSED_STATE_SET;
2048     /**
2049      * Indicates the view is selected. States are used with
2050      * {@link android.graphics.drawable.Drawable} to change the drawing of the
2051      * view depending on its state.
2052      *
2053      * @see android.graphics.drawable.Drawable
2054      * @see #getDrawableState()
2055      */
2056     protected static final int[] SELECTED_STATE_SET;
2057     /**
2058      * Indicates the view is pressed. States are used with
2059      * {@link android.graphics.drawable.Drawable} to change the drawing of the
2060      * view depending on its state.
2061      *
2062      * @see android.graphics.drawable.Drawable
2063      * @see #getDrawableState()
2064      */
2065     protected static final int[] PRESSED_STATE_SET;
2066     /**
2067      * Indicates the view's window has focus. States are used with
2068      * {@link android.graphics.drawable.Drawable} to change the drawing of the
2069      * view depending on its state.
2070      *
2071      * @see android.graphics.drawable.Drawable
2072      * @see #getDrawableState()
2073      */
2074     protected static final int[] WINDOW_FOCUSED_STATE_SET;
2075     // Doubles
2076     /**
2077      * Indicates the view is enabled and has the focus.
2078      *
2079      * @see #ENABLED_STATE_SET
2080      * @see #FOCUSED_STATE_SET
2081      */
2082     protected static final int[] ENABLED_FOCUSED_STATE_SET;
2083     /**
2084      * Indicates the view is enabled and selected.
2085      *
2086      * @see #ENABLED_STATE_SET
2087      * @see #SELECTED_STATE_SET
2088      */
2089     protected static final int[] ENABLED_SELECTED_STATE_SET;
2090     /**
2091      * Indicates the view is enabled and that its window has focus.
2092      *
2093      * @see #ENABLED_STATE_SET
2094      * @see #WINDOW_FOCUSED_STATE_SET
2095      */
2096     protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
2097     /**
2098      * Indicates the view is focused and selected.
2099      *
2100      * @see #FOCUSED_STATE_SET
2101      * @see #SELECTED_STATE_SET
2102      */
2103     protected static final int[] FOCUSED_SELECTED_STATE_SET;
2104     /**
2105      * Indicates the view has the focus and that its window has the focus.
2106      *
2107      * @see #FOCUSED_STATE_SET
2108      * @see #WINDOW_FOCUSED_STATE_SET
2109      */
2110     protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
2111     /**
2112      * Indicates the view is selected and that its window has the focus.
2113      *
2114      * @see #SELECTED_STATE_SET
2115      * @see #WINDOW_FOCUSED_STATE_SET
2116      */
2117     protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
2118     // Triples
2119     /**
2120      * Indicates the view is enabled, focused and selected.
2121      *
2122      * @see #ENABLED_STATE_SET
2123      * @see #FOCUSED_STATE_SET
2124      * @see #SELECTED_STATE_SET
2125      */
2126     protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
2127     /**
2128      * Indicates the view is enabled, focused and its window has the focus.
2129      *
2130      * @see #ENABLED_STATE_SET
2131      * @see #FOCUSED_STATE_SET
2132      * @see #WINDOW_FOCUSED_STATE_SET
2133      */
2134     protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
2135     /**
2136      * Indicates the view is enabled, selected and its window has the focus.
2137      *
2138      * @see #ENABLED_STATE_SET
2139      * @see #SELECTED_STATE_SET
2140      * @see #WINDOW_FOCUSED_STATE_SET
2141      */
2142     protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2143     /**
2144      * Indicates the view is focused, selected and its window has the focus.
2145      *
2146      * @see #FOCUSED_STATE_SET
2147      * @see #SELECTED_STATE_SET
2148      * @see #WINDOW_FOCUSED_STATE_SET
2149      */
2150     protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2151     /**
2152      * Indicates the view is enabled, focused, selected and its window
2153      * has the focus.
2154      *
2155      * @see #ENABLED_STATE_SET
2156      * @see #FOCUSED_STATE_SET
2157      * @see #SELECTED_STATE_SET
2158      * @see #WINDOW_FOCUSED_STATE_SET
2159      */
2160     protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2161     /**
2162      * Indicates the view is pressed and its window has the focus.
2163      *
2164      * @see #PRESSED_STATE_SET
2165      * @see #WINDOW_FOCUSED_STATE_SET
2166      */
2167     protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
2168     /**
2169      * Indicates the view is pressed and selected.
2170      *
2171      * @see #PRESSED_STATE_SET
2172      * @see #SELECTED_STATE_SET
2173      */
2174     protected static final int[] PRESSED_SELECTED_STATE_SET;
2175     /**
2176      * Indicates the view is pressed, selected and its window has the focus.
2177      *
2178      * @see #PRESSED_STATE_SET
2179      * @see #SELECTED_STATE_SET
2180      * @see #WINDOW_FOCUSED_STATE_SET
2181      */
2182     protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2183     /**
2184      * Indicates the view is pressed and focused.
2185      *
2186      * @see #PRESSED_STATE_SET
2187      * @see #FOCUSED_STATE_SET
2188      */
2189     protected static final int[] PRESSED_FOCUSED_STATE_SET;
2190     /**
2191      * Indicates the view is pressed, focused and its window has the focus.
2192      *
2193      * @see #PRESSED_STATE_SET
2194      * @see #FOCUSED_STATE_SET
2195      * @see #WINDOW_FOCUSED_STATE_SET
2196      */
2197     protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
2198     /**
2199      * Indicates the view is pressed, focused and selected.
2200      *
2201      * @see #PRESSED_STATE_SET
2202      * @see #SELECTED_STATE_SET
2203      * @see #FOCUSED_STATE_SET
2204      */
2205     protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
2206     /**
2207      * Indicates the view is pressed, focused, selected and its window has the focus.
2208      *
2209      * @see #PRESSED_STATE_SET
2210      * @see #FOCUSED_STATE_SET
2211      * @see #SELECTED_STATE_SET
2212      * @see #WINDOW_FOCUSED_STATE_SET
2213      */
2214     protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2215     /**
2216      * Indicates the view is pressed and enabled.
2217      *
2218      * @see #PRESSED_STATE_SET
2219      * @see #ENABLED_STATE_SET
2220      */
2221     protected static final int[] PRESSED_ENABLED_STATE_SET;
2222     /**
2223      * Indicates the view is pressed, enabled and its window has the focus.
2224      *
2225      * @see #PRESSED_STATE_SET
2226      * @see #ENABLED_STATE_SET
2227      * @see #WINDOW_FOCUSED_STATE_SET
2228      */
2229     protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
2230     /**
2231      * Indicates the view is pressed, enabled and selected.
2232      *
2233      * @see #PRESSED_STATE_SET
2234      * @see #ENABLED_STATE_SET
2235      * @see #SELECTED_STATE_SET
2236      */
2237     protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
2238     /**
2239      * Indicates the view is pressed, enabled, selected and its window has the
2240      * focus.
2241      *
2242      * @see #PRESSED_STATE_SET
2243      * @see #ENABLED_STATE_SET
2244      * @see #SELECTED_STATE_SET
2245      * @see #WINDOW_FOCUSED_STATE_SET
2246      */
2247     protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2248     /**
2249      * Indicates the view is pressed, enabled and focused.
2250      *
2251      * @see #PRESSED_STATE_SET
2252      * @see #ENABLED_STATE_SET
2253      * @see #FOCUSED_STATE_SET
2254      */
2255     protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
2256     /**
2257      * Indicates the view is pressed, enabled, focused and its window has the
2258      * focus.
2259      *
2260      * @see #PRESSED_STATE_SET
2261      * @see #ENABLED_STATE_SET
2262      * @see #FOCUSED_STATE_SET
2263      * @see #WINDOW_FOCUSED_STATE_SET
2264      */
2265     protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
2266     /**
2267      * Indicates the view is pressed, enabled, focused and selected.
2268      *
2269      * @see #PRESSED_STATE_SET
2270      * @see #ENABLED_STATE_SET
2271      * @see #SELECTED_STATE_SET
2272      * @see #FOCUSED_STATE_SET
2273      */
2274     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
2275     /**
2276      * Indicates the view is pressed, enabled, focused, selected and its window
2277      * has the focus.
2278      *
2279      * @see #PRESSED_STATE_SET
2280      * @see #ENABLED_STATE_SET
2281      * @see #SELECTED_STATE_SET
2282      * @see #FOCUSED_STATE_SET
2283      * @see #WINDOW_FOCUSED_STATE_SET
2284      */
2285     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2286 
2287     static {
2288         EMPTY_STATE_SET = StateSet.get(0);
2289 
2290         WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
2291 
2292         SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
2293         SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2294                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
2295 
2296         FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
2297         FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2298                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
2299         FOCUSED_SELECTED_STATE_SET = StateSet.get(
2300                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
2301         FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2302                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2303                         | StateSet.VIEW_STATE_FOCUSED);
2304 
2305         ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
2306         ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2307                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
2308         ENABLED_SELECTED_STATE_SET = StateSet.get(
2309                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
2310         ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2311                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2312                         | StateSet.VIEW_STATE_ENABLED);
2313         ENABLED_FOCUSED_STATE_SET = StateSet.get(
2314                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
2315         ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2316                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2317                         | StateSet.VIEW_STATE_ENABLED);
2318         ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2319                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2320                         | StateSet.VIEW_STATE_ENABLED);
2321         ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2322                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2323                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
2324 
2325         PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
2326         PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2327                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
2328         PRESSED_SELECTED_STATE_SET = StateSet.get(
2329                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
2330         PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2331                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2332                         | StateSet.VIEW_STATE_PRESSED);
2333         PRESSED_FOCUSED_STATE_SET = StateSet.get(
2334                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
2335         PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2336                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2337                         | StateSet.VIEW_STATE_PRESSED);
2338         PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2339                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2340                         | StateSet.VIEW_STATE_PRESSED);
2341         PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2342                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2343                         | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
2344         PRESSED_ENABLED_STATE_SET = StateSet.get(
2345                 StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2346         PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2347                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
2348                         | StateSet.VIEW_STATE_PRESSED);
2349         PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
2350                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
2351                         | StateSet.VIEW_STATE_PRESSED);
2352         PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2353                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2354                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2355         PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
2356                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
2357                         | StateSet.VIEW_STATE_PRESSED);
2358         PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2359                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2360                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2361         PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2362                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2363                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2364         PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2365                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2366                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
2367                         | StateSet.VIEW_STATE_PRESSED);
2368     }
2369 
2370     /**
2371      * Accessibility event types that are dispatched for text population.
2372      */
2373     private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
2374             AccessibilityEvent.TYPE_VIEW_CLICKED
2375             | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
2376             | AccessibilityEvent.TYPE_VIEW_SELECTED
2377             | AccessibilityEvent.TYPE_VIEW_FOCUSED
2378             | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
2379             | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
2380             | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
2381             | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
2382             | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
2383             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
2384             | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
2385 
2386     static final int DEBUG_CORNERS_COLOR = Color.rgb(63, 127, 255);
2387 
2388     static final int DEBUG_CORNERS_SIZE_DIP = 8;
2389 
2390     /**
2391      * Temporary Rect currently for use in setBackground().  This will probably
2392      * be extended in the future to hold our own class with more than just
2393      * a Rect. :)
2394      */
2395     static final ThreadLocal<Rect> sThreadLocal = ThreadLocal.withInitial(Rect::new);
2396 
2397     /**
2398      * Map used to store views' tags.
2399      */
2400     @UnsupportedAppUsage
2401     private SparseArray<Object> mKeyedTags;
2402 
2403     /**
2404      * The next available accessibility id.
2405      */
2406     private static int sNextAccessibilityViewId;
2407 
2408     /**
2409      * The animation currently associated with this view.
2410      * @hide
2411      */
2412     protected Animation mCurrentAnimation = null;
2413 
2414     /**
2415      * Width as measured during measure pass.
2416      * {@hide}
2417      */
2418     @ViewDebug.ExportedProperty(category = "measurement")
2419     @UnsupportedAppUsage
2420     int mMeasuredWidth;
2421 
2422     /**
2423      * Height as measured during measure pass.
2424      * {@hide}
2425      */
2426     @ViewDebug.ExportedProperty(category = "measurement")
2427     @UnsupportedAppUsage
2428     int mMeasuredHeight;
2429 
2430     /**
2431      * Flag to indicate that this view was marked INVALIDATED, or had its display list
2432      * invalidated, prior to the current drawing iteration. If true, the view must re-draw
2433      * its display list. This flag, used only when hw accelerated, allows us to clear the
2434      * flag while retaining this information until it's needed (at getDisplayList() time and
2435      * in drawChild(), when we decide to draw a view's children's display lists into our own).
2436      *
2437      * {@hide}
2438      */
2439     @UnsupportedAppUsage
2440     boolean mRecreateDisplayList = false;
2441 
2442     /**
2443      * The view's identifier.
2444      * {@hide}
2445      *
2446      * @see #setId(int)
2447      * @see #getId()
2448      */
2449     @IdRes
2450     @ViewDebug.ExportedProperty(resolveId = true)
2451     int mID = NO_ID;
2452 
2453     /** The ID of this view for autofill purposes.
2454      * <ul>
2455      *     <li>== {@link #NO_ID}: ID has not been assigned yet
2456      *     <li>&le; {@link #LAST_APP_AUTOFILL_ID}: View is not part of a activity. The ID is
2457      *                                                  unique in the process. This might change
2458      *                                                  over activity lifecycle events.
2459      *     <li>&gt; {@link #LAST_APP_AUTOFILL_ID}: View is part of a activity. The ID is
2460      *                                                  unique in the activity. This stays the same
2461      *                                                  over activity lifecycle events.
2462      */
2463     private int mAutofillViewId = NO_ID;
2464 
2465     // ID for accessibility purposes. This ID must be unique for every window
2466     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
2467     private int mAccessibilityViewId = NO_ID;
2468 
2469     private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
2470 
2471     /**
2472      * The view's tag.
2473      * {@hide}
2474      *
2475      * @see #setTag(Object)
2476      * @see #getTag()
2477      */
2478     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
2479     protected Object mTag = null;
2480 
2481     /*
2482      * Masks for mPrivateFlags, as generated by dumpFlags():
2483      *
2484      * |-------|-------|-------|-------|
2485      *                                 1 PFLAG_WANTS_FOCUS
2486      *                                1  PFLAG_FOCUSED
2487      *                               1   PFLAG_SELECTED
2488      *                              1    PFLAG_IS_ROOT_NAMESPACE
2489      *                             1     PFLAG_HAS_BOUNDS
2490      *                            1      PFLAG_DRAWN
2491      *                           1       PFLAG_DRAW_ANIMATION
2492      *                          1        PFLAG_SKIP_DRAW
2493      *                        1          PFLAG_REQUEST_TRANSPARENT_REGIONS
2494      *                       1           PFLAG_DRAWABLE_STATE_DIRTY
2495      *                      1            PFLAG_MEASURED_DIMENSION_SET
2496      *                     1             PFLAG_FORCE_LAYOUT
2497      *                    1              PFLAG_LAYOUT_REQUIRED
2498      *                   1               PFLAG_PRESSED
2499      *                  1                PFLAG_DRAWING_CACHE_VALID
2500      *                 1                 PFLAG_ANIMATION_STARTED
2501      *                1                  PFLAG_SAVE_STATE_CALLED
2502      *               1                   PFLAG_ALPHA_SET
2503      *              1                    PFLAG_SCROLL_CONTAINER
2504      *             1                     PFLAG_SCROLL_CONTAINER_ADDED
2505      *            1                      PFLAG_DIRTY
2506      *            1                      PFLAG_DIRTY_MASK
2507      *          1                        PFLAG_OPAQUE_BACKGROUND
2508      *         1                         PFLAG_OPAQUE_SCROLLBARS
2509      *         11                        PFLAG_OPAQUE_MASK
2510      *        1                          PFLAG_PREPRESSED
2511      *       1                           PFLAG_CANCEL_NEXT_UP_EVENT
2512      *      1                            PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH
2513      *     1                             PFLAG_HOVERED
2514      *    1                              PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK
2515      *   1                               PFLAG_ACTIVATED
2516      *  1                                PFLAG_INVALIDATED
2517      * |-------|-------|-------|-------|
2518      */
2519     /** {@hide} */
2520     static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
2521     /** {@hide} */
2522     static final int PFLAG_FOCUSED                     = 0x00000002;
2523     /** {@hide} */
2524     static final int PFLAG_SELECTED                    = 0x00000004;
2525     /** {@hide} */
2526     static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
2527     /** {@hide} */
2528     static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
2529     /** {@hide} */
2530     static final int PFLAG_DRAWN                       = 0x00000020;
2531     /**
2532      * When this flag is set, this view is running an animation on behalf of its
2533      * children and should therefore not cancel invalidate requests, even if they
2534      * lie outside of this view's bounds.
2535      *
2536      * {@hide}
2537      */
2538     static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
2539     /** {@hide} */
2540     static final int PFLAG_SKIP_DRAW                   = 0x00000080;
2541     /** {@hide} */
2542     static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
2543     /** {@hide} */
2544     static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
2545     /** {@hide} */
2546     static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
2547     /** {@hide} */
2548     static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
2549     /** {@hide} */
2550     static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
2551 
2552     private static final int PFLAG_PRESSED             = 0x00004000;
2553 
2554     /** {@hide} */
2555     static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
2556     /**
2557      * Flag used to indicate that this view should be drawn once more (and only once
2558      * more) after its animation has completed.
2559      * {@hide}
2560      */
2561     static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
2562 
2563     private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
2564 
2565     /**
2566      * Indicates that the View returned true when onSetAlpha() was called and that
2567      * the alpha must be restored.
2568      * {@hide}
2569      */
2570     static final int PFLAG_ALPHA_SET                   = 0x00040000;
2571 
2572     /**
2573      * Set by {@link #setScrollContainer(boolean)}.
2574      */
2575     static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
2576 
2577     /**
2578      * Set by {@link #setScrollContainer(boolean)}.
2579      */
2580     static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
2581 
2582     /**
2583      * View flag indicating whether this view was invalidated (fully or partially.)
2584      *
2585      * @hide
2586      */
2587     static final int PFLAG_DIRTY                       = 0x00200000;
2588 
2589     /**
2590      * Mask for {@link #PFLAG_DIRTY}.
2591      *
2592      * @hide
2593      */
2594     static final int PFLAG_DIRTY_MASK                  = 0x00200000;
2595 
2596     /**
2597      * Indicates whether the background is opaque.
2598      *
2599      * @hide
2600      */
2601     static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
2602 
2603     /**
2604      * Indicates whether the scrollbars are opaque.
2605      *
2606      * @hide
2607      */
2608     static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
2609 
2610     /**
2611      * Indicates whether the view is opaque.
2612      *
2613      * @hide
2614      */
2615     static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
2616 
2617     /**
2618      * Indicates a prepressed state;
2619      * the short time between ACTION_DOWN and recognizing
2620      * a 'real' press. Prepressed is used to recognize quick taps
2621      * even when they are shorter than ViewConfiguration.getTapTimeout().
2622      *
2623      * @hide
2624      */
2625     private static final int PFLAG_PREPRESSED          = 0x02000000;
2626 
2627     /**
2628      * Indicates whether the view is temporarily detached.
2629      *
2630      * @hide
2631      */
2632     static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
2633 
2634     /**
2635      * Indicates that we should awaken scroll bars once attached
2636      *
2637      * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
2638      * during window attachment and it is no longer needed. Feel free to repurpose it.
2639      *
2640      * @hide
2641      */
2642     private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
2643 
2644     /**
2645      * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
2646      * @hide
2647      */
2648     private static final int PFLAG_HOVERED             = 0x10000000;
2649 
2650     /**
2651      * Flag set by {@link AutofillManager} if it needs to be notified when this view is clicked.
2652      */
2653     private static final int PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK = 0x20000000;
2654 
2655     /** {@hide} */
2656     static final int PFLAG_ACTIVATED                   = 0x40000000;
2657 
2658     /**
2659      * Indicates that this view was specifically invalidated, not just dirtied because some
2660      * child view was invalidated. The flag is used to determine when we need to recreate
2661      * a view's display list (as opposed to just returning a reference to its existing
2662      * display list).
2663      *
2664      * @hide
2665      */
2666     static final int PFLAG_INVALIDATED                 = 0x80000000;
2667 
2668     /* End of masks for mPrivateFlags */
2669 
2670     /*
2671      * Masks for mPrivateFlags2, as generated by dumpFlags():
2672      *
2673      * |-------|-------|-------|-------|
2674      *                                 1 PFLAG2_DRAG_CAN_ACCEPT
2675      *                                1  PFLAG2_DRAG_HOVERED
2676      *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
2677      *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
2678      *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
2679      *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
2680      *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
2681      *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
2682      *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
2683      *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
2684      *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
2685      *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
2686      *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
2687      *                         111       PFLAG2_TEXT_DIRECTION_MASK
2688      *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
2689      *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
2690      *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
2691      *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
2692      *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
2693      *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
2694      *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
2695      *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
2696      *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
2697      *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
2698      *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
2699      *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
2700      *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
2701      *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
2702      *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
2703      *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
2704      *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
2705      *     1                             PFLAG2_VIEW_QUICK_REJECTED
2706      *    1                              PFLAG2_PADDING_RESOLVED
2707      *   1                               PFLAG2_DRAWABLE_RESOLVED
2708      *  1                                PFLAG2_HAS_TRANSIENT_STATE
2709      * |-------|-------|-------|-------|
2710      */
2711 
2712     /**
2713      * Indicates that this view has reported that it can accept the current drag's content.
2714      * Cleared when the drag operation concludes.
2715      * @hide
2716      */
2717     static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
2718 
2719     /**
2720      * Indicates that this view is currently directly under the drag location in a
2721      * drag-and-drop operation involving content that it can accept.  Cleared when
2722      * the drag exits the view, or when the drag operation concludes.
2723      * @hide
2724      */
2725     static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
2726 
2727     /** @hide */
2728     @IntDef(prefix = { "LAYOUT_DIRECTION_" }, value = {
2729             LAYOUT_DIRECTION_LTR,
2730             LAYOUT_DIRECTION_RTL,
2731             LAYOUT_DIRECTION_INHERIT,
2732             LAYOUT_DIRECTION_LOCALE
2733     })
2734     @Retention(RetentionPolicy.SOURCE)
2735     // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
2736     public @interface LayoutDir {}
2737 
2738     /** @hide */
2739     @IntDef(prefix = { "LAYOUT_DIRECTION_" }, value = {
2740             LAYOUT_DIRECTION_LTR,
2741             LAYOUT_DIRECTION_RTL
2742     })
2743     @Retention(RetentionPolicy.SOURCE)
2744     public @interface ResolvedLayoutDir {}
2745 
2746     /**
2747      * A flag to indicate that the layout direction of this view has not been defined yet.
2748      * @hide
2749      */
2750     public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
2751 
2752     /**
2753      * Horizontal layout direction of this view is from Left to Right.
2754      * Use with {@link #setLayoutDirection}.
2755      */
2756     public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
2757 
2758     /**
2759      * Horizontal layout direction of this view is from Right to Left.
2760      * Use with {@link #setLayoutDirection}.
2761      */
2762     public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
2763 
2764     /**
2765      * Horizontal layout direction of this view is inherited from its parent.
2766      * Use with {@link #setLayoutDirection}.
2767      */
2768     public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
2769 
2770     /**
2771      * Horizontal layout direction of this view is from deduced from the default language
2772      * script for the locale. Use with {@link #setLayoutDirection}.
2773      */
2774     public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
2775 
2776     /**
2777      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2778      * @hide
2779      */
2780     static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
2781 
2782     /**
2783      * Mask for use with private flags indicating bits used for horizontal layout direction.
2784      * @hide
2785      */
2786     static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2787 
2788     /**
2789      * Indicates whether the view horizontal layout direction has been resolved and drawn to the
2790      * right-to-left direction.
2791      * @hide
2792      */
2793     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2794 
2795     /**
2796      * Indicates whether the view horizontal layout direction has been resolved.
2797      * @hide
2798      */
2799     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2800 
2801     /**
2802      * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
2803      * @hide
2804      */
2805     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
2806             << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2807 
2808     /*
2809      * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
2810      * flag value.
2811      * @hide
2812      */
2813     private static final int[] LAYOUT_DIRECTION_FLAGS = {
2814             LAYOUT_DIRECTION_LTR,
2815             LAYOUT_DIRECTION_RTL,
2816             LAYOUT_DIRECTION_INHERIT,
2817             LAYOUT_DIRECTION_LOCALE
2818     };
2819 
2820     /**
2821      * Default horizontal layout direction.
2822      */
2823     private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
2824 
2825     /**
2826      * Default horizontal layout direction.
2827      * @hide
2828      */
2829     static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
2830 
2831     /**
2832      * Text direction is inherited through {@link ViewGroup}
2833      */
2834     public static final int TEXT_DIRECTION_INHERIT = 0;
2835 
2836     /**
2837      * Text direction is using "first strong algorithm". The first strong directional character
2838      * determines the paragraph direction. If there is no strong directional character, the
2839      * paragraph direction is the view's resolved layout direction.
2840      */
2841     public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2842 
2843     /**
2844      * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2845      * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2846      * If there are neither, the paragraph direction is the view's resolved layout direction.
2847      */
2848     public static final int TEXT_DIRECTION_ANY_RTL = 2;
2849 
2850     /**
2851      * Text direction is forced to LTR.
2852      */
2853     public static final int TEXT_DIRECTION_LTR = 3;
2854 
2855     /**
2856      * Text direction is forced to RTL.
2857      */
2858     public static final int TEXT_DIRECTION_RTL = 4;
2859 
2860     /**
2861      * Text direction is coming from the system Locale.
2862      */
2863     public static final int TEXT_DIRECTION_LOCALE = 5;
2864 
2865     /**
2866      * Text direction is using "first strong algorithm". The first strong directional character
2867      * determines the paragraph direction. If there is no strong directional character, the
2868      * paragraph direction is LTR.
2869      */
2870     public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2871 
2872     /**
2873      * Text direction is using "first strong algorithm". The first strong directional character
2874      * determines the paragraph direction. If there is no strong directional character, the
2875      * paragraph direction is RTL.
2876      */
2877     public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2878 
2879     /**
2880      * Default text direction is inherited
2881      */
2882     private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2883 
2884     /**
2885      * Default resolved text direction
2886      * @hide
2887      */
2888     static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2889 
2890     /**
2891      * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2892      * @hide
2893      */
2894     static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2895 
2896     /**
2897      * Mask for use with private flags indicating bits used for text direction.
2898      * @hide
2899      */
2900     static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2901             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2902 
2903     /**
2904      * Array of text direction flags for mapping attribute "textDirection" to correct
2905      * flag value.
2906      * @hide
2907      */
2908     private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2909             TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2910             TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2911             TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2912             TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2913             TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2914             TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2915             TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2916             TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2917     };
2918 
2919     /**
2920      * Indicates whether the view text direction has been resolved.
2921      * @hide
2922      */
2923     static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2924             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2925 
2926     /**
2927      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2928      * @hide
2929      */
2930     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2931 
2932     /**
2933      * Mask for use with private flags indicating bits used for resolved text direction.
2934      * @hide
2935      */
2936     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2937             << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2938 
2939     /**
2940      * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2941      * @hide
2942      */
2943     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2944             TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2945 
2946     /** @hide */
2947     @IntDef(prefix = { "TEXT_ALIGNMENT_" }, value = {
2948             TEXT_ALIGNMENT_INHERIT,
2949             TEXT_ALIGNMENT_GRAVITY,
2950             TEXT_ALIGNMENT_CENTER,
2951             TEXT_ALIGNMENT_TEXT_START,
2952             TEXT_ALIGNMENT_TEXT_END,
2953             TEXT_ALIGNMENT_VIEW_START,
2954             TEXT_ALIGNMENT_VIEW_END
2955     })
2956     @Retention(RetentionPolicy.SOURCE)
2957     public @interface TextAlignment {}
2958 
2959     /**
2960      * Default text alignment. The text alignment of this View is inherited from its parent.
2961      * Use with {@link #setTextAlignment(int)}
2962      */
2963     public static final int TEXT_ALIGNMENT_INHERIT = 0;
2964 
2965     /**
2966      * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2967      * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph's text direction.
2968      *
2969      * Use with {@link #setTextAlignment(int)}
2970      */
2971     public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2972 
2973     /**
2974      * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2975      *
2976      * Use with {@link #setTextAlignment(int)}
2977      */
2978     public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2979 
2980     /**
2981      * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2982      *
2983      * Use with {@link #setTextAlignment(int)}
2984      */
2985     public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2986 
2987     /**
2988      * Center the paragraph, e.g. ALIGN_CENTER.
2989      *
2990      * Use with {@link #setTextAlignment(int)}
2991      */
2992     public static final int TEXT_ALIGNMENT_CENTER = 4;
2993 
2994     /**
2995      * Align to the start of the view, which is ALIGN_LEFT if the view's resolved
2996      * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2997      *
2998      * Use with {@link #setTextAlignment(int)}
2999      */
3000     public static final int TEXT_ALIGNMENT_VIEW_START = 5;
3001 
3002     /**
3003      * Align to the end of the view, which is ALIGN_RIGHT if the view's resolved
3004      * layoutDirection is LTR, and ALIGN_LEFT otherwise.
3005      *
3006      * Use with {@link #setTextAlignment(int)}
3007      */
3008     public static final int TEXT_ALIGNMENT_VIEW_END = 6;
3009 
3010     /**
3011      * Default text alignment is inherited
3012      */
3013     private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
3014 
3015     /**
3016      * Default resolved text alignment
3017      * @hide
3018      */
3019     static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
3020 
3021     /**
3022       * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
3023       * @hide
3024       */
3025     static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
3026 
3027     /**
3028       * Mask for use with private flags indicating bits used for text alignment.
3029       * @hide
3030       */
3031     static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
3032 
3033     /**
3034      * Array of text direction flags for mapping attribute "textAlignment" to correct
3035      * flag value.
3036      * @hide
3037      */
3038     private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
3039             TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
3040             TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
3041             TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
3042             TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
3043             TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
3044             TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
3045             TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
3046     };
3047 
3048     /**
3049      * Indicates whether the view text alignment has been resolved.
3050      * @hide
3051      */
3052     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
3053 
3054     /**
3055      * Bit shift to get the resolved text alignment.
3056      * @hide
3057      */
3058     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
3059 
3060     /**
3061      * Mask for use with private flags indicating bits used for text alignment.
3062      * @hide
3063      */
3064     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
3065             << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
3066 
3067     /**
3068      * Indicates whether if the view text alignment has been resolved to gravity
3069      */
3070     private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
3071             TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
3072 
3073     // Accessiblity constants for mPrivateFlags2
3074 
3075     /**
3076      * Shift for the bits in {@link #mPrivateFlags2} related to the
3077      * "importantForAccessibility" attribute.
3078      */
3079     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
3080 
3081     /**
3082      * Automatically determine whether a view is important for accessibility.
3083      */
3084     public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
3085 
3086     /**
3087      * The view is important for accessibility.
3088      */
3089     public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
3090 
3091     /**
3092      * The view is not important for accessibility.
3093      */
3094     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
3095 
3096     /**
3097      * The view is not important for accessibility, nor are any of its
3098      * descendant views.
3099      */
3100     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
3101 
3102     /**
3103      * The default whether the view is important for accessibility.
3104      */
3105     static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
3106 
3107     /**
3108      * Automatically determine whether the view should only allow interactions from
3109      * {@link android.accessibilityservice.AccessibilityService}s with the
3110      * {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property
3111      * set to true.
3112      *
3113      * <p>
3114      * Accessibility interactions from services without {@code isAccessibilityTool} set to true are
3115      * disallowed for any of the following conditions:
3116      * <li>this view sets {@link #getFilterTouchesWhenObscured()}.</li>
3117      * <li>any parent of this view returns true from {@link #isAccessibilityDataSensitive()}.</li>
3118      * </p>
3119      */
3120     public static final int ACCESSIBILITY_DATA_SENSITIVE_AUTO = 0x00000000;
3121 
3122     /**
3123      * Only allow interactions from {@link android.accessibilityservice.AccessibilityService}s
3124      * with the {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool}
3125      * property set to true.
3126      */
3127     public static final int ACCESSIBILITY_DATA_SENSITIVE_YES = 0x00000001;
3128 
3129     /**
3130      * Allow interactions from all {@link android.accessibilityservice.AccessibilityService}s,
3131      * regardless of their
3132      * {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property.
3133      */
3134     public static final int ACCESSIBILITY_DATA_SENSITIVE_NO = 0x00000002;
3135 
3136     /** @hide */
3137     @IntDef(prefix = { "ACCESSIBILITY_DATA_SENSITIVE_" }, value = {
3138             ACCESSIBILITY_DATA_SENSITIVE_AUTO,
3139             ACCESSIBILITY_DATA_SENSITIVE_YES,
3140             ACCESSIBILITY_DATA_SENSITIVE_NO,
3141     })
3142     @Retention(RetentionPolicy.SOURCE)
3143     public @interface AccessibilityDataSensitive {}
3144 
3145     /**
3146      * Mask for obtaining the bits which specify how to determine
3147      * whether a view is important for accessibility.
3148      */
3149     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
3150         | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
3151         | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
3152         << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
3153 
3154     /**
3155      * Shift for the bits in {@link #mPrivateFlags2} related to the
3156      * "accessibilityLiveRegion" attribute.
3157      */
3158     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
3159 
3160     /**
3161      * Live region mode specifying that accessibility services should not
3162      * automatically announce changes to this view. This is the default live
3163      * region mode for most views.
3164      * <p>
3165      * Use with {@link #setAccessibilityLiveRegion(int)}.
3166      */
3167     public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
3168 
3169     /**
3170      * Live region mode specifying that accessibility services should announce
3171      * changes to this view.
3172      * <p>
3173      * Use with {@link #setAccessibilityLiveRegion(int)}.
3174      */
3175     public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
3176 
3177     /**
3178      * Live region mode specifying that accessibility services should interrupt
3179      * ongoing speech to immediately announce changes to this view.
3180      * <p>
3181      * Use with {@link #setAccessibilityLiveRegion(int)}.
3182      */
3183     public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
3184 
3185     /**
3186      * The default whether the view is important for accessibility.
3187      */
3188     static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
3189 
3190     /**
3191      * Mask for obtaining the bits which specify a view's accessibility live
3192      * region mode.
3193      */
3194     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
3195             | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
3196             << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
3197 
3198     /**
3199      * Flag indicating whether a view has accessibility focus.
3200      */
3201     static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
3202 
3203     /**
3204      * Flag whether the accessibility state of the subtree rooted at this view changed.
3205      */
3206     static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
3207 
3208     /**
3209      * Flag indicating whether a view failed the quickReject() check in draw(). This condition
3210      * is used to check whether later changes to the view's transform should invalidate the
3211      * view to force the quickReject test to run again.
3212      */
3213     static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
3214 
3215     /**
3216      * Flag indicating that start/end padding has been resolved into left/right padding
3217      * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
3218      * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
3219      * during measurement. In some special cases this is required such as when an adapter-based
3220      * view measures prospective children without attaching them to a window.
3221      */
3222     static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
3223 
3224     /**
3225      * Flag indicating that the start/end drawables has been resolved into left/right ones.
3226      */
3227     static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
3228 
3229     /**
3230      * Indicates that the view is tracking some sort of transient state
3231      * that the app should not need to be aware of, but that the framework
3232      * should take special care to preserve.
3233      */
3234     static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
3235 
3236     /**
3237      * Group of bits indicating that RTL properties resolution is done.
3238      */
3239     static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
3240             PFLAG2_TEXT_DIRECTION_RESOLVED |
3241             PFLAG2_TEXT_ALIGNMENT_RESOLVED |
3242             PFLAG2_PADDING_RESOLVED |
3243             PFLAG2_DRAWABLE_RESOLVED;
3244 
3245     // There are a couple of flags left in mPrivateFlags2
3246 
3247     /* End of masks for mPrivateFlags2 */
3248 
3249     /*
3250      * Masks for mPrivateFlags3, as generated by dumpFlags():
3251      *
3252      * |-------|-------|-------|-------|
3253      *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
3254      *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
3255      *                               1   PFLAG3_IS_LAID_OUT
3256      *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
3257      *                             1     PFLAG3_CALLED_SUPER
3258      *                            1      PFLAG3_APPLYING_INSETS
3259      *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
3260      *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
3261      *                         1         PFLAG3_SCROLL_INDICATOR_TOP
3262      *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
3263      *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
3264      *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
3265      *                     1             PFLAG3_SCROLL_INDICATOR_START
3266      *                    1              PFLAG3_SCROLL_INDICATOR_END
3267      *                   1               PFLAG3_ASSIST_BLOCKED
3268      *                  1                PFLAG3_CLUSTER
3269      *                 1                 PFLAG3_IS_AUTOFILLED
3270      *                1                  PFLAG3_FINGER_DOWN
3271      *               1                   PFLAG3_FOCUSED_BY_DEFAULT
3272      *           1111                    PFLAG3_IMPORTANT_FOR_AUTOFILL
3273      *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
3274      *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
3275      *        1                          PFLAG3_TEMPORARY_DETACH
3276      *       1                           PFLAG3_NO_REVEAL_ON_FOCUS
3277      *      1                            PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT
3278      *     1                             PFLAG3_SCREEN_READER_FOCUSABLE
3279      *    1                              PFLAG3_AGGREGATED_VISIBLE
3280      *   1                               PFLAG3_AUTOFILLID_EXPLICITLY_SET
3281      *  1                                PFLAG3_ACCESSIBILITY_HEADING
3282      * |-------|-------|-------|-------|
3283      */
3284 
3285     /**
3286      * Flag indicating that view has a transform animation set on it. This is used to track whether
3287      * an animation is cleared between successive frames, in order to tell the associated
3288      * DisplayList to clear its animation matrix.
3289      */
3290     static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
3291 
3292     /**
3293      * Flag indicating that view has an alpha animation set on it. This is used to track whether an
3294      * animation is cleared between successive frames, in order to tell the associated
3295      * DisplayList to restore its alpha value.
3296      */
3297     static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
3298 
3299     /**
3300      * Flag indicating that the view has been through at least one layout since it
3301      * was last attached to a window.
3302      */
3303     static final int PFLAG3_IS_LAID_OUT = 0x4;
3304 
3305     /**
3306      * Flag indicating that a call to measure() was skipped and should be done
3307      * instead when layout() is invoked.
3308      */
3309     static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
3310 
3311     /**
3312      * Flag indicating that an overridden method correctly called down to
3313      * the superclass implementation as required by the API spec.
3314      */
3315     static final int PFLAG3_CALLED_SUPER = 0x10;
3316 
3317     /**
3318      * Flag indicating that we're in the process of applying window insets.
3319      */
3320     static final int PFLAG3_APPLYING_INSETS = 0x20;
3321 
3322     /**
3323      * Flag indicating that we're in the process of fitting system windows using the old method.
3324      */
3325     static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
3326 
3327     /**
3328      * Flag indicating that nested scrolling is enabled for this view.
3329      * The view will optionally cooperate with views up its parent chain to allow for
3330      * integrated nested scrolling along the same axis.
3331      */
3332     static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
3333 
3334     /**
3335      * Flag indicating that the bottom scroll indicator should be displayed
3336      * when this view can scroll up.
3337      */
3338     static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
3339 
3340     /**
3341      * Flag indicating that the bottom scroll indicator should be displayed
3342      * when this view can scroll down.
3343      */
3344     static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
3345 
3346     /**
3347      * Flag indicating that the left scroll indicator should be displayed
3348      * when this view can scroll left.
3349      */
3350     static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
3351 
3352     /**
3353      * Flag indicating that the right scroll indicator should be displayed
3354      * when this view can scroll right.
3355      */
3356     static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
3357 
3358     /**
3359      * Flag indicating that the start scroll indicator should be displayed
3360      * when this view can scroll in the start direction.
3361      */
3362     static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
3363 
3364     /**
3365      * Flag indicating that the end scroll indicator should be displayed
3366      * when this view can scroll in the end direction.
3367      */
3368     static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
3369 
3370     static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
3371 
3372     static final int SCROLL_INDICATORS_NONE = 0x0000;
3373 
3374     /**
3375      * Mask for use with setFlags indicating bits used for indicating which
3376      * scroll indicators are enabled.
3377      */
3378     static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
3379             | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
3380             | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
3381             | PFLAG3_SCROLL_INDICATOR_END;
3382 
3383     /**
3384      * Left-shift required to translate between public scroll indicator flags
3385      * and internal PFLAGS3 flags. When used as a right-shift, translates
3386      * PFLAGS3 flags to public flags.
3387      */
3388     static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
3389 
3390     /** @hide */
3391     @Retention(RetentionPolicy.SOURCE)
3392     @IntDef(flag = true, prefix = { "SCROLL_INDICATOR_" }, value = {
3393             SCROLL_INDICATOR_TOP,
3394             SCROLL_INDICATOR_BOTTOM,
3395             SCROLL_INDICATOR_LEFT,
3396             SCROLL_INDICATOR_RIGHT,
3397             SCROLL_INDICATOR_START,
3398             SCROLL_INDICATOR_END,
3399     })
3400     public @interface ScrollIndicators {}
3401 
3402     /**
3403      * Scroll indicator direction for the top edge of the view.
3404      *
3405      * @see #setScrollIndicators(int)
3406      * @see #setScrollIndicators(int, int)
3407      * @see #getScrollIndicators()
3408      */
3409     public static final int SCROLL_INDICATOR_TOP =
3410             PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3411 
3412     /**
3413      * Scroll indicator direction for the bottom edge of the view.
3414      *
3415      * @see #setScrollIndicators(int)
3416      * @see #setScrollIndicators(int, int)
3417      * @see #getScrollIndicators()
3418      */
3419     public static final int SCROLL_INDICATOR_BOTTOM =
3420             PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3421 
3422     /**
3423      * Scroll indicator direction for the left edge of the view.
3424      *
3425      * @see #setScrollIndicators(int)
3426      * @see #setScrollIndicators(int, int)
3427      * @see #getScrollIndicators()
3428      */
3429     public static final int SCROLL_INDICATOR_LEFT =
3430             PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3431 
3432     /**
3433      * Scroll indicator direction for the right edge of the view.
3434      *
3435      * @see #setScrollIndicators(int)
3436      * @see #setScrollIndicators(int, int)
3437      * @see #getScrollIndicators()
3438      */
3439     public static final int SCROLL_INDICATOR_RIGHT =
3440             PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3441 
3442     /**
3443      * Scroll indicator direction for the starting edge of the view.
3444      * <p>
3445      * Resolved according to the view's layout direction, see
3446      * {@link #getLayoutDirection()} for more information.
3447      *
3448      * @see #setScrollIndicators(int)
3449      * @see #setScrollIndicators(int, int)
3450      * @see #getScrollIndicators()
3451      */
3452     public static final int SCROLL_INDICATOR_START =
3453             PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3454 
3455     /**
3456      * Scroll indicator direction for the ending edge of the view.
3457      * <p>
3458      * Resolved according to the view's layout direction, see
3459      * {@link #getLayoutDirection()} for more information.
3460      *
3461      * @see #setScrollIndicators(int)
3462      * @see #setScrollIndicators(int, int)
3463      * @see #getScrollIndicators()
3464      */
3465     public static final int SCROLL_INDICATOR_END =
3466             PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3467 
3468     /**
3469      * <p>Indicates that we are allowing {@link ViewStructure} to traverse
3470      * into this view.<p>
3471      */
3472     static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
3473 
3474     /**
3475      * Flag indicating that the view is a root of a keyboard navigation cluster.
3476      *
3477      * @see #isKeyboardNavigationCluster()
3478      * @see #setKeyboardNavigationCluster(boolean)
3479      */
3480     private static final int PFLAG3_CLUSTER = 0x8000;
3481 
3482     /**
3483      * Flag indicating that the view is autofilled
3484      *
3485      * @see #isAutofilled()
3486      * @see #setAutofilled(boolean, boolean)
3487      */
3488     private static final int PFLAG3_IS_AUTOFILLED = 0x10000;
3489 
3490     /**
3491      * Indicates that the user is currently touching the screen.
3492      * Currently used for the tooltip positioning only.
3493      */
3494     private static final int PFLAG3_FINGER_DOWN = 0x20000;
3495 
3496     /**
3497      * Flag indicating that this view is the default-focus view.
3498      *
3499      * @see #isFocusedByDefault()
3500      * @see #setFocusedByDefault(boolean)
3501      */
3502     private static final int PFLAG3_FOCUSED_BY_DEFAULT = 0x40000;
3503 
3504     /**
3505      * Shift for the bits in {@link #mPrivateFlags3} related to the
3506      * "importantForAutofill" attribute.
3507      */
3508     static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT = 19;
3509 
3510     /**
3511      * Mask for obtaining the bits which specify how to determine
3512      * whether a view is important for autofill.
3513      */
3514     static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK = (IMPORTANT_FOR_AUTOFILL_AUTO
3515             | IMPORTANT_FOR_AUTOFILL_YES | IMPORTANT_FOR_AUTOFILL_NO
3516             | IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
3517             | IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS)
3518             << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
3519 
3520     /**
3521      * Whether this view has rendered elements that overlap (see {@link
3522      * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
3523      * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
3524      * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
3525      * determined by whatever {@link #hasOverlappingRendering()} returns.
3526      */
3527     private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
3528 
3529     /**
3530      * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
3531      * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
3532      */
3533     private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
3534 
3535     /**
3536      * Flag indicating that the view is temporarily detached from the parent view.
3537      *
3538      * @see #onStartTemporaryDetach()
3539      * @see #onFinishTemporaryDetach()
3540      */
3541     static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
3542 
3543     /**
3544      * Flag indicating that the view does not wish to be revealed within its parent
3545      * hierarchy when it gains focus. Expressed in the negative since the historical
3546      * default behavior is to reveal on focus; this flag suppresses that behavior.
3547      *
3548      * @see #setRevealOnFocusHint(boolean)
3549      * @see #getRevealOnFocusHint()
3550      */
3551     private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
3552 
3553     /**
3554      * Flag indicating that when layout is completed we should notify
3555      * that the view was entered for autofill purposes. To minimize
3556      * showing autofill for views not visible to the user we evaluate
3557      * user visibility which cannot be done until the view is laid out.
3558      */
3559     static final int PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT = 0x8000000;
3560 
3561     /**
3562      * Works like focusable for screen readers, but without the side effects on input focus.
3563      * @see #setScreenReaderFocusable(boolean)
3564      */
3565     private static final int PFLAG3_SCREEN_READER_FOCUSABLE = 0x10000000;
3566 
3567     /**
3568      * The last aggregated visibility. Used to detect when it truly changes.
3569      */
3570     private static final int PFLAG3_AGGREGATED_VISIBLE = 0x20000000;
3571 
3572     /**
3573      * Used to indicate that {@link #mAutofillId} was explicitly set through
3574      * {@link #setAutofillId(AutofillId)}.
3575      */
3576     private static final int PFLAG3_AUTOFILLID_EXPLICITLY_SET = 0x40000000;
3577 
3578     /**
3579      * Indicates if the View is a heading for accessibility purposes
3580      */
3581     private static final int PFLAG3_ACCESSIBILITY_HEADING = 0x80000000;
3582 
3583     /* End of masks for mPrivateFlags3 */
3584 
3585     /*
3586      * Masks for mPrivateFlags4, as generated by dumpFlags():
3587      *
3588      * |-------|-------|-------|-------|
3589      *                             1111 PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK
3590      *                            1     PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED
3591      *                           1      PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED
3592      *                          1       PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED
3593      *                         1        PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE
3594      *                         11       PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK
3595      *                        1         PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS
3596      *                       1          PFLAG4_AUTOFILL_HIDE_HIGHLIGHT
3597      *                     11           PFLAG4_SCROLL_CAPTURE_HINT_MASK
3598      *                    1             PFLAG4_ALLOW_CLICK_WHEN_DISABLED
3599      *                   1              PFLAG4_DETACHED
3600      *                  1               PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE
3601      *                 1                PFLAG4_DRAG_A11Y_STARTED
3602      *                1                 PFLAG4_AUTO_HANDWRITING_INITIATION_ENABLED
3603      *               1                  PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER
3604      *              1                   PFLAG4_TRAVERSAL_TRACING_ENABLED
3605      *             1                    PFLAG4_RELAYOUT_TRACING_ENABLED
3606      * |-------|-------|-------|-------|
3607      */
3608 
3609     /**
3610      * Mask for obtaining the bits which specify how to determine
3611      * whether a view is important for autofill.
3612      *
3613      * <p>NOTE: the important for content capture values were the first flags added and are set in
3614      * the rightmost position, so we don't need to shift them
3615      */
3616     private static final int PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK =
3617             IMPORTANT_FOR_CONTENT_CAPTURE_AUTO | IMPORTANT_FOR_CONTENT_CAPTURE_YES
3618             | IMPORTANT_FOR_CONTENT_CAPTURE_NO
3619             | IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
3620             | IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS;
3621 
3622     /*
3623      * Variables used to control when the IntelligenceManager.notifyNodeAdded()/removed() methods
3624      * should be called.
3625      *
3626      * The idea is to call notifyAppeared() after the view is layout and visible, then call
3627      * notifyDisappeared() when it's gone (without known when it was removed from the parent).
3628      */
3629     private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED = 0x10;
3630     private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED = 0x20;
3631 
3632     /*
3633      * Flags used to cache the value returned by isImportantForContentCapture while the view
3634      * hierarchy is being traversed.
3635      */
3636     private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED = 0x40;
3637     private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE = 0x80;
3638 
3639     private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK =
3640             PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED
3641             | PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
3642 
3643     /**
3644      * @see #OPTIONAL_FITS_SYSTEM_WINDOWS
3645      */
3646     static final int PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS = 0x000000100;
3647 
3648     /**
3649      * Flag indicating the field should not have yellow highlight when autofilled.
3650      */
3651     private static final int PFLAG4_AUTOFILL_HIDE_HIGHLIGHT = 0x200;
3652 
3653     /**
3654      * Shift for the bits in {@link #mPrivateFlags4} related to scroll capture.
3655      */
3656     static final int PFLAG4_SCROLL_CAPTURE_HINT_SHIFT = 10;
3657 
3658     static final int PFLAG4_SCROLL_CAPTURE_HINT_MASK = (SCROLL_CAPTURE_HINT_INCLUDE
3659             | SCROLL_CAPTURE_HINT_EXCLUDE | SCROLL_CAPTURE_HINT_EXCLUDE_DESCENDANTS)
3660             << PFLAG4_SCROLL_CAPTURE_HINT_SHIFT;
3661 
3662     /**
3663      * Indicates if the view can receive click events when disabled.
3664      */
3665     private static final int PFLAG4_ALLOW_CLICK_WHEN_DISABLED = 0x000001000;
3666 
3667     /**
3668      * Indicates if the view is just detached.
3669      */
3670     private static final int PFLAG4_DETACHED = 0x000002000;
3671 
3672     /**
3673      * Indicates that the view has transient state because the system is translating it.
3674      */
3675     private static final int PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE = 0x000004000;
3676 
3677     /**
3678      * Indicates that the view has started a drag with {@link AccessibilityAction#ACTION_DRAG_START}
3679      */
3680     private static final int PFLAG4_DRAG_A11Y_STARTED = 0x000008000;
3681 
3682     /**
3683      * Indicates that the view enables auto handwriting initiation.
3684      */
3685     private static final int PFLAG4_AUTO_HANDWRITING_ENABLED = 0x000010000;
3686 
3687     /**
3688      * Indicates that the view is important for Credential Manager.
3689      */
3690     private static final int PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER = 0x000020000;
3691 
3692     /**
3693      * When set, measure and layout passes of this view will be logged with {@link Trace}, so we
3694      * can better debug jank due to complex view hierarchies.
3695      */
3696     private static final int PFLAG4_TRAVERSAL_TRACING_ENABLED = 0x000040000;
3697 
3698     /**
3699      * When set, emits a {@link Trace} instant event and stacktrace every time a requestLayout of
3700      * this class happens.
3701      */
3702     private static final int PFLAG4_RELAYOUT_TRACING_ENABLED = 0x000080000;
3703 
3704     /* End of masks for mPrivateFlags4 */
3705 
3706     /** @hide */
3707     protected static final int VIEW_STRUCTURE_FOR_ASSIST = 0;
3708     /** @hide */
3709     protected  static final int VIEW_STRUCTURE_FOR_AUTOFILL = 1;
3710     /** @hide */
3711     protected  static final int VIEW_STRUCTURE_FOR_CONTENT_CAPTURE = 2;
3712 
3713     /** @hide */
3714     @IntDef(flag = true, prefix = { "VIEW_STRUCTURE_FOR" }, value = {
3715             VIEW_STRUCTURE_FOR_ASSIST,
3716             VIEW_STRUCTURE_FOR_AUTOFILL,
3717             VIEW_STRUCTURE_FOR_CONTENT_CAPTURE
3718     })
3719     @Retention(RetentionPolicy.SOURCE)
3720     public @interface ViewStructureType {}
3721 
3722     /**
3723      * Always allow a user to over-scroll this view, provided it is a
3724      * view that can scroll.
3725      *
3726      * @see #getOverScrollMode()
3727      * @see #setOverScrollMode(int)
3728      */
3729     public static final int OVER_SCROLL_ALWAYS = 0;
3730 
3731     /**
3732      * Allow a user to over-scroll this view only if the content is large
3733      * enough to meaningfully scroll, provided it is a view that can scroll.
3734      *
3735      * @see #getOverScrollMode()
3736      * @see #setOverScrollMode(int)
3737      */
3738     public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
3739 
3740     /**
3741      * Never allow a user to over-scroll this view.
3742      *
3743      * @see #getOverScrollMode()
3744      * @see #setOverScrollMode(int)
3745      */
3746     public static final int OVER_SCROLL_NEVER = 2;
3747 
3748     /**
3749      * Special constant for {@link #setSystemUiVisibility(int)}: View has
3750      * requested the system UI (status bar) to be visible (the default).
3751      *
3752      * @see #setSystemUiVisibility(int)
3753      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
3754      * instead.
3755      */
3756     @Deprecated
3757     public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
3758 
3759     /**
3760      * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
3761      * system UI to enter an unobtrusive "low profile" mode.
3762      *
3763      * <p>This is for use in games, book readers, video players, or any other
3764      * "immersive" application where the usual system chrome is deemed too distracting.
3765      *
3766      * <p>In low profile mode, the status bar and/or navigation icons may dim.
3767      *
3768      * @see #setSystemUiVisibility(int)
3769      * @deprecated Low profile mode is deprecated. Hide the system bars instead if the application
3770      * needs to be in a unobtrusive mode. Use {@link WindowInsetsController#hide(int)} with
3771      * {@link Type#systemBars()}.
3772      */
3773     @Deprecated
3774     public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
3775 
3776     /**
3777      * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
3778      * system navigation be temporarily hidden.
3779      *
3780      * <p>This is an even less obtrusive state than that called for by
3781      * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
3782      * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
3783      * those to disappear. This is useful (in conjunction with the
3784      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
3785      * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
3786      * window flags) for displaying content using every last pixel on the display.
3787      *
3788      * <p>There is a limitation: because navigation controls are so important, the least user
3789      * interaction will cause them to reappear immediately.  When this happens, both
3790      * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
3791      * so that both elements reappear at the same time.
3792      *
3793      * @see #setSystemUiVisibility(int)
3794      * @deprecated Use {@link WindowInsetsController#hide(int)} with {@link Type#navigationBars()}
3795      * instead.
3796      */
3797     @Deprecated
3798     public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
3799 
3800     /**
3801      * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
3802      * into the normal fullscreen mode so that its content can take over the screen
3803      * while still allowing the user to interact with the application.
3804      *
3805      * <p>This has the same visual effect as
3806      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
3807      * WindowManager.LayoutParams.FLAG_FULLSCREEN},
3808      * meaning that non-critical screen decorations (such as the status bar) will be
3809      * hidden while the user is in the View's window, focusing the experience on
3810      * that content.  Unlike the window flag, if you are using ActionBar in
3811      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3812      * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
3813      * hide the action bar.
3814      *
3815      * <p>This approach to going fullscreen is best used over the window flag when
3816      * it is a transient state -- that is, the application does this at certain
3817      * points in its user interaction where it wants to allow the user to focus
3818      * on content, but not as a continuous state.  For situations where the application
3819      * would like to simply stay full screen the entire time (such as a game that
3820      * wants to take over the screen), the
3821      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
3822      * is usually a better approach.  The state set here will be removed by the system
3823      * in various situations (such as the user moving to another application) like
3824      * the other system UI states.
3825      *
3826      * <p>When using this flag, the application should provide some easy facility
3827      * for the user to go out of it.  A common example would be in an e-book
3828      * reader, where tapping on the screen brings back whatever screen and UI
3829      * decorations that had been hidden while the user was immersed in reading
3830      * the book.
3831      *
3832      * @see #setSystemUiVisibility(int)
3833      * @deprecated Use {@link WindowInsetsController#hide(int)} with {@link Type#statusBars()}
3834      * instead.
3835      */
3836     @Deprecated
3837     public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
3838 
3839     /**
3840      * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
3841      * flags, we would like a stable view of the content insets given to
3842      * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
3843      * will always represent the worst case that the application can expect
3844      * as a continuous state.  In the stock Android UI this is the space for
3845      * the system bar, nav bar, and status bar, but not more transient elements
3846      * such as an input method.
3847      *
3848      * The stable layout your UI sees is based on the system UI modes you can
3849      * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
3850      * then you will get a stable layout for changes of the
3851      * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
3852      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
3853      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
3854      * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
3855      * with a stable layout.  (Note that you should avoid using
3856      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
3857      *
3858      * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
3859      * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
3860      * then a hidden status bar will be considered a "stable" state for purposes
3861      * here.  This allows your UI to continually hide the status bar, while still
3862      * using the system UI flags to hide the action bar while still retaining
3863      * a stable layout.  Note that changing the window fullscreen flag will never
3864      * provide a stable layout for a clean transition.
3865      *
3866      * <p>If you are using ActionBar in
3867      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3868      * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
3869      * insets it adds to those given to the application.
3870      *
3871      * @deprecated Use {@link WindowInsets#getInsetsIgnoringVisibility(int)} instead to retrieve
3872      * insets that don't change when system bars change visibility state.
3873      */
3874     @Deprecated
3875     public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
3876 
3877     /**
3878      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3879      * to be laid out as if it has requested
3880      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
3881      * allows it to avoid artifacts when switching in and out of that mode, at
3882      * the expense that some of its user interface may be covered by screen
3883      * decorations when they are shown.  You can perform layout of your inner
3884      * UI elements to account for the navigation system UI through the
3885      * {@link #fitSystemWindows(Rect)} method.
3886      *
3887      * @deprecated For floating windows, use {@link LayoutParams#setFitInsetsTypes(int)} with
3888      * {@link Type#navigationBars()}. For non-floating windows that fill the screen, call
3889      * {@link Window#setDecorFitsSystemWindows(boolean)} with {@code false}.
3890      */
3891     public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
3892 
3893     /**
3894      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3895      * to be laid out as if it has requested
3896      * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
3897      * allows it to avoid artifacts when switching in and out of that mode, at
3898      * the expense that some of its user interface may be covered by screen
3899      * decorations when they are shown.  You can perform layout of your inner
3900      * UI elements to account for non-fullscreen system UI through the
3901      * {@link #fitSystemWindows(Rect)} method.
3902      *
3903      * <p>Note: on displays that have a {@link DisplayCutout}, the window may still be placed
3904      *  differently than if {@link #SYSTEM_UI_FLAG_FULLSCREEN} was set, if the
3905      *  window's {@link WindowManager.LayoutParams#layoutInDisplayCutoutMode
3906      *  layoutInDisplayCutoutMode} is
3907      *  {@link WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
3908      *  LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT}. To avoid this, use either of the other modes.
3909      *
3910      * @see WindowManager.LayoutParams#layoutInDisplayCutoutMode
3911      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
3912      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
3913      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
3914      *
3915      * @deprecated For floating windows, use {@link LayoutParams#setFitInsetsTypes(int)} with
3916      * {@link Type#statusBars()} ()}. For non-floating windows that fill the screen, call
3917      * {@link Window#setDecorFitsSystemWindows(boolean)} with {@code false}.
3918      */
3919     @Deprecated
3920     public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
3921 
3922     /**
3923      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3924      * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
3925      * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
3926      * user interaction.
3927      * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
3928      * has an effect when used in combination with that flag.</p>
3929      *
3930      * @deprecated Use {@link WindowInsetsController#BEHAVIOR_DEFAULT} instead.
3931      */
3932     @Deprecated
3933     public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
3934 
3935     /**
3936      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3937      * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
3938      * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
3939      * experience while also hiding the system bars.  If this flag is not set,
3940      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
3941      * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
3942      * if the user swipes from the top of the screen.
3943      * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
3944      * system gestures, such as swiping from the top of the screen.  These transient system bars
3945      * will overlay app's content, may have some degree of transparency, and will automatically
3946      * hide after a short timeout.
3947      * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
3948      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
3949      * with one or both of those flags.</p>
3950      *
3951      * @deprecated Use {@link WindowInsetsController#BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE} instead.
3952      */
3953     @Deprecated
3954     public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
3955 
3956     /**
3957      * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
3958      * is compatible with light status bar backgrounds.
3959      *
3960      * <p>For this to take effect, the window must request
3961      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3962      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3963      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
3964      *         FLAG_TRANSLUCENT_STATUS}.
3965      *
3966      * @see android.R.attr#windowLightStatusBar
3967      * @deprecated Use {@link WindowInsetsController#APPEARANCE_LIGHT_STATUS_BARS} instead.
3968      */
3969     @Deprecated
3970     public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
3971 
3972     /**
3973      * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3974      * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3975      */
3976     private static final int SYSTEM_UI_RESERVED_LEGACY1 = 0x00004000;
3977 
3978     /**
3979      * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3980      * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3981      */
3982     private static final int SYSTEM_UI_RESERVED_LEGACY2 = 0x00010000;
3983 
3984     /**
3985      * Flag for {@link #setSystemUiVisibility(int)}: Requests the navigation bar to draw in a mode
3986      * that is compatible with light navigation bar backgrounds.
3987      *
3988      * <p>For this to take effect, the window must request
3989      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3990      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3991      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION
3992      *         FLAG_TRANSLUCENT_NAVIGATION}.
3993      *
3994      * @see android.R.attr#windowLightNavigationBar
3995      * @deprecated Use {@link WindowInsetsController#APPEARANCE_LIGHT_NAVIGATION_BARS} instead.
3996      */
3997     @Deprecated
3998     public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010;
3999 
4000     /**
4001      * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
4002      */
4003     @Deprecated
4004     public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
4005 
4006     /**
4007      * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
4008      */
4009     @Deprecated
4010     public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
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 make the status bar not expandable.  Unless you also
4019      * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
4020      */
4021     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
4022     public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
4023 
4024     /**
4025      * @hide
4026      *
4027      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4028      * out of the public fields to keep the undefined bits out of the developer's way.
4029      *
4030      * Flag to hide notification icons and scrolling ticker text.
4031      */
4032     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
4033 
4034     /**
4035      * @hide
4036      *
4037      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4038      * out of the public fields to keep the undefined bits out of the developer's way.
4039      *
4040      * Flag to disable incoming notification alerts.  This will not block
4041      * icons, but it will block sound, vibrating and other visual or aural notifications.
4042      */
4043     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
4044 
4045     /**
4046      * @hide
4047      *
4048      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4049      * out of the public fields to keep the undefined bits out of the developer's way.
4050      *
4051      * Flag to hide only the scrolling ticker.  Note that
4052      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
4053      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
4054      */
4055     public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
4056 
4057     /**
4058      * @hide
4059      *
4060      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4061      * out of the public fields to keep the undefined bits out of the developer's way.
4062      *
4063      * Flag to hide the center system info area.
4064      */
4065     public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
4066 
4067     /**
4068      * @hide
4069      *
4070      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4071      * out of the public fields to keep the undefined bits out of the developer's way.
4072      *
4073      * Flag to hide only the home button.  Don't use this
4074      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
4075      */
4076     @UnsupportedAppUsage
4077     public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
4078 
4079     /**
4080      * @hide
4081      *
4082      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4083      * out of the public fields to keep the undefined bits out of the developer's way.
4084      *
4085      * Flag to hide only the back button. Don't use this
4086      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
4087      */
4088     @UnsupportedAppUsage
4089     public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
4090 
4091     /**
4092      * @hide
4093      *
4094      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4095      * out of the public fields to keep the undefined bits out of the developer's way.
4096      *
4097      * Flag to hide only the clock.  You might use this if your activity has
4098      * its own clock making the status bar's clock redundant.
4099      */
4100     public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
4101 
4102     /**
4103      * @hide
4104      *
4105      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4106      * out of the public fields to keep the undefined bits out of the developer's way.
4107      *
4108      * Flag to hide only the recent apps button. Don't use this
4109      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
4110      */
4111     @UnsupportedAppUsage
4112     public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
4113 
4114     /**
4115      * @hide
4116      *
4117      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4118      * out of the public fields to keep the undefined bits out of the developer's way.
4119      *
4120      * Flag to disable the global search gesture. Don't use this
4121      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
4122      */
4123     public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
4124 
4125     /**
4126      * @hide
4127      *
4128      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
4129      * out of the public fields to keep the undefined bits out of the developer's way.
4130      *
4131      * Flag to disable the ongoing call chip.
4132      */
4133     public static final int STATUS_BAR_DISABLE_ONGOING_CALL_CHIP = 0x04000000;
4134 
4135     /**
4136      * @hide
4137      */
4138     public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
4139 
4140     /**
4141      * These are the system UI flags that can be cleared by events outside
4142      * of an application.  Currently this is just the ability to tap on the
4143      * screen while hiding the navigation bar to have it return.
4144      * @hide
4145      */
4146     public static final int SYSTEM_UI_CLEARABLE_FLAGS =
4147             SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
4148             | SYSTEM_UI_FLAG_FULLSCREEN;
4149 
4150     /**
4151      * Flags that can impact the layout in relation to system UI.
4152      *
4153      * @deprecated System UI layout flags are deprecated.
4154      */
4155     @Deprecated
4156     public static final int SYSTEM_UI_LAYOUT_FLAGS =
4157             SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
4158             | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
4159 
4160     /** @hide */
4161     @IntDef(flag = true, prefix = { "FIND_VIEWS_" }, value = {
4162             FIND_VIEWS_WITH_TEXT,
4163             FIND_VIEWS_WITH_CONTENT_DESCRIPTION
4164     })
4165     @Retention(RetentionPolicy.SOURCE)
4166     public @interface FindViewFlags {}
4167 
4168     /**
4169      * Find views that render the specified text.
4170      *
4171      * @see #findViewsWithText(ArrayList, CharSequence, int)
4172      */
4173     public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
4174 
4175     /**
4176      * Find find views that contain the specified content description.
4177      *
4178      * @see #findViewsWithText(ArrayList, CharSequence, int)
4179      */
4180     public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
4181 
4182     /**
4183      * Find views that contain {@link AccessibilityNodeProvider}. Such
4184      * a View is a root of virtual view hierarchy and may contain the searched
4185      * text. If this flag is set Views with providers are automatically
4186      * added and it is a responsibility of the client to call the APIs of
4187      * the provider to determine whether the virtual tree rooted at this View
4188      * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
4189      * representing the virtual views with this text.
4190      *
4191      * @see #findViewsWithText(ArrayList, CharSequence, int)
4192      *
4193      * @hide
4194      */
4195     public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
4196 
4197     /**
4198      * The undefined cursor position.
4199      *
4200      * @hide
4201      */
4202     public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
4203 
4204     /**
4205      * Indicates that the screen has changed state and is now off.
4206      *
4207      * @see #onScreenStateChanged(int)
4208      */
4209     public static final int SCREEN_STATE_OFF = 0x0;
4210 
4211     /**
4212      * Indicates that the screen has changed state and is now on.
4213      *
4214      * @see #onScreenStateChanged(int)
4215      */
4216     public static final int SCREEN_STATE_ON = 0x1;
4217 
4218     /**
4219      * Indicates no axis of view scrolling.
4220      */
4221     public static final int SCROLL_AXIS_NONE = 0;
4222 
4223     /**
4224      * Indicates scrolling along the horizontal axis.
4225      */
4226     public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
4227 
4228     /**
4229      * Indicates scrolling along the vertical axis.
4230      */
4231     public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
4232 
4233     /**
4234      * Controls the over-scroll mode for this view.
4235      * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
4236      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
4237      * and {@link #OVER_SCROLL_NEVER}.
4238      */
4239     private int mOverScrollMode;
4240 
4241     /**
4242      * The parent this view is attached to.
4243      * {@hide}
4244      *
4245      * @see #getParent()
4246      */
4247     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4248     protected ViewParent mParent;
4249 
4250     /**
4251      * {@hide}
4252      *
4253      * Not available for general use. If you need help, hang up and then dial one of the following
4254      * public APIs:
4255      *
4256      * @see #isAttachedToWindow() for current attach state
4257      * @see #onAttachedToWindow() for subclasses performing work when becoming attached
4258      * @see #onDetachedFromWindow() for subclasses performing work when becoming detached
4259      * @see OnAttachStateChangeListener for other code performing work on attach/detach
4260      * @see #getHandler() for posting messages to this view's UI thread/looper
4261      * @see #getParent() for interacting with the parent chain
4262      * @see #getWindowToken() for the current window token
4263      * @see #getRootView() for the view at the root of the attached hierarchy
4264      * @see #getDisplay() for the Display this view is presented on
4265      * @see #getRootWindowInsets() for the current insets applied to the whole attached window
4266      * @see #hasWindowFocus() for whether the attached window is currently focused
4267      * @see #getWindowVisibility() for checking the visibility of the attached window
4268      */
4269     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4270     AttachInfo mAttachInfo;
4271 
4272     /**
4273      * {@hide}
4274      */
4275     @ViewDebug.ExportedProperty(flagMapping = {
4276         @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
4277                 name = "FORCE_LAYOUT"),
4278         @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
4279                 name = "LAYOUT_REQUIRED"),
4280         @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
4281             name = "DRAWING_CACHE_INVALID", outputIf = false),
4282         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
4283         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
4284         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
4285     }, formatToHexString = true)
4286 
4287     /* @hide */
4288     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769414)
4289     public int mPrivateFlags;
4290     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768943)
4291     int mPrivateFlags2;
4292     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 129147060)
4293     int mPrivateFlags3;
4294 
4295     private int mPrivateFlags4;
4296 
4297     /**
4298      * This view's request for the visibility of the status bar.
4299      * @hide
4300      */
4301     @ViewDebug.ExportedProperty(flagMapping = {
4302             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
4303                     equals = SYSTEM_UI_FLAG_LOW_PROFILE,
4304                     name = "LOW_PROFILE"),
4305             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
4306                     equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
4307                     name = "HIDE_NAVIGATION"),
4308             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_FULLSCREEN,
4309                     equals = SYSTEM_UI_FLAG_FULLSCREEN,
4310                     name = "FULLSCREEN"),
4311             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_STABLE,
4312                     equals = SYSTEM_UI_FLAG_LAYOUT_STABLE,
4313                     name = "LAYOUT_STABLE"),
4314             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
4315                     equals = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
4316                     name = "LAYOUT_HIDE_NAVIGATION"),
4317             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
4318                     equals = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
4319                     name = "LAYOUT_FULLSCREEN"),
4320             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE,
4321                     equals = SYSTEM_UI_FLAG_IMMERSIVE,
4322                     name = "IMMERSIVE"),
4323             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
4324                     equals = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
4325                     name = "IMMERSIVE_STICKY"),
4326             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
4327                     equals = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
4328                     name = "LIGHT_STATUS_BAR"),
4329             @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
4330                     equals = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
4331                     name = "LIGHT_NAVIGATION_BAR"),
4332             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_EXPAND,
4333                     equals = STATUS_BAR_DISABLE_EXPAND,
4334                     name = "STATUS_BAR_DISABLE_EXPAND"),
4335             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
4336                     equals = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
4337                     name = "STATUS_BAR_DISABLE_NOTIFICATION_ICONS"),
4338             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
4339                     equals = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
4340                     name = "STATUS_BAR_DISABLE_NOTIFICATION_ALERTS"),
4341             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
4342                     equals = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
4343                     name = "STATUS_BAR_DISABLE_NOTIFICATION_TICKER"),
4344             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SYSTEM_INFO,
4345                     equals = STATUS_BAR_DISABLE_SYSTEM_INFO,
4346                     name = "STATUS_BAR_DISABLE_SYSTEM_INFO"),
4347             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_HOME,
4348                     equals = STATUS_BAR_DISABLE_HOME,
4349                     name = "STATUS_BAR_DISABLE_HOME"),
4350             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_BACK,
4351                     equals = STATUS_BAR_DISABLE_BACK,
4352                     name = "STATUS_BAR_DISABLE_BACK"),
4353             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_CLOCK,
4354                     equals = STATUS_BAR_DISABLE_CLOCK,
4355                     name = "STATUS_BAR_DISABLE_CLOCK"),
4356             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_RECENT,
4357                     equals = STATUS_BAR_DISABLE_RECENT,
4358                     name = "STATUS_BAR_DISABLE_RECENT"),
4359             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SEARCH,
4360                     equals = STATUS_BAR_DISABLE_SEARCH,
4361                     name = "STATUS_BAR_DISABLE_SEARCH"),
4362             @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
4363                     equals = STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
4364                     name = "STATUS_BAR_DISABLE_ONGOING_CALL_CHIP")
4365     }, formatToHexString = true)
4366     @SystemUiVisibility
4367     int mSystemUiVisibility;
4368 
4369     /**
4370      * @hide
4371      */
4372     @IntDef(flag = true, prefix = "", value = {
4373             SYSTEM_UI_FLAG_LOW_PROFILE,
4374             SYSTEM_UI_FLAG_HIDE_NAVIGATION,
4375             SYSTEM_UI_FLAG_FULLSCREEN,
4376             SYSTEM_UI_FLAG_LAYOUT_STABLE,
4377             SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
4378             SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
4379             SYSTEM_UI_FLAG_IMMERSIVE,
4380             SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
4381             SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
4382             SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
4383             STATUS_BAR_DISABLE_EXPAND,
4384             STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
4385             STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
4386             STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
4387             STATUS_BAR_DISABLE_SYSTEM_INFO,
4388             STATUS_BAR_DISABLE_HOME,
4389             STATUS_BAR_DISABLE_BACK,
4390             STATUS_BAR_DISABLE_CLOCK,
4391             STATUS_BAR_DISABLE_RECENT,
4392             STATUS_BAR_DISABLE_SEARCH,
4393             STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
4394     })
4395     @Retention(RetentionPolicy.SOURCE)
4396     public @interface SystemUiVisibility {}
4397 
4398     /**
4399      * Reference count for transient state.
4400      * @see #setHasTransientState(boolean)
4401      */
4402     int mTransientStateCount = 0;
4403 
4404     /**
4405      * Count of how many windows this view has been attached to.
4406      */
4407     int mWindowAttachCount;
4408 
4409     /**
4410      * The layout parameters associated with this view and used by the parent
4411      * {@link android.view.ViewGroup} to determine how this view should be
4412      * laid out.
4413      *
4414      * The field should not be used directly. Instead {@link #getLayoutParams()} and {@link
4415      * #setLayoutParams(ViewGroup.LayoutParams)} should be used. The setter guarantees internal
4416      * state correctness of the class.
4417      * {@hide}
4418      */
4419     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4420     protected ViewGroup.LayoutParams mLayoutParams;
4421 
4422     /**
4423      * The view flags hold various views states.
4424      *
4425      * Use {@link #setTransitionVisibility(int)} to change the visibility of this view without
4426      * triggering updates.
4427      * {@hide}
4428      */
4429     @ViewDebug.ExportedProperty(formatToHexString = true)
4430     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4431     int mViewFlags;
4432 
4433     static class TransformationInfo {
4434         /**
4435          * The transform matrix for the View. This transform is calculated internally
4436          * based on the translation, rotation, and scale properties.
4437          *
4438          * Do *not* use this variable directly; instead call getMatrix(), which will
4439          * load the value from the View's RenderNode.
4440          */
4441         private final Matrix mMatrix = new Matrix();
4442 
4443         /**
4444          * The inverse transform matrix for the View. This transform is calculated
4445          * internally based on the translation, rotation, and scale properties.
4446          *
4447          * Do *not* use this variable directly; instead call getInverseMatrix(),
4448          * which will load the value from the View's RenderNode.
4449          */
4450         private Matrix mInverseMatrix;
4451 
4452         /**
4453          * The opacity of the View. This is a value from 0 to 1, where 0 means
4454          * completely transparent and 1 means completely opaque.
4455          */
4456         @ViewDebug.ExportedProperty
4457         private float mAlpha = 1f;
4458 
4459         /**
4460          * The opacity of the view as manipulated by the Fade transition. This is a
4461          * property only used by transitions, which is composited with the other alpha
4462          * values to calculate the final visual alpha value.
4463          */
4464         float mTransitionAlpha = 1f;
4465     }
4466 
4467     /** @hide */
4468     @UnsupportedAppUsage
4469     public TransformationInfo mTransformationInfo;
4470 
4471     /**
4472      * Current clip bounds. to which all drawing of this view are constrained.
4473      */
4474     @ViewDebug.ExportedProperty(category = "drawing")
4475     Rect mClipBounds = null;
4476 
4477     private boolean mLastIsOpaque;
4478 
4479     /**
4480      * The distance in pixels from the left edge of this view's parent
4481      * to the left edge of this view.
4482      * {@hide}
4483      */
4484     @ViewDebug.ExportedProperty(category = "layout")
4485     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4486     protected int mLeft;
4487     /**
4488      * The distance in pixels from the left edge of this view's parent
4489      * to the right edge of this view.
4490      * {@hide}
4491      */
4492     @ViewDebug.ExportedProperty(category = "layout")
4493     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4494     protected int mRight;
4495     /**
4496      * The distance in pixels from the top edge of this view's parent
4497      * to the top edge of this view.
4498      * {@hide}
4499      */
4500     @ViewDebug.ExportedProperty(category = "layout")
4501     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4502     protected int mTop;
4503     /**
4504      * The distance in pixels from the top edge of this view's parent
4505      * to the bottom edge of this view.
4506      * {@hide}
4507      */
4508     @ViewDebug.ExportedProperty(category = "layout")
4509     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4510     protected int mBottom;
4511 
4512     /**
4513      * The offset, in pixels, by which the content of this view is scrolled
4514      * horizontally.
4515      * Please use {@link View#getScrollX()} and {@link View#setScrollX(int)} instead of
4516      * accessing these directly.
4517      * {@hide}
4518      */
4519     @ViewDebug.ExportedProperty(category = "scrolling")
4520     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4521     protected int mScrollX;
4522     /**
4523      * The offset, in pixels, by which the content of this view is scrolled
4524      * vertically.
4525      * Please use {@link View#getScrollY()} and {@link View#setScrollY(int)} instead of
4526      * accessing these directly.
4527      * {@hide}
4528      */
4529     @ViewDebug.ExportedProperty(category = "scrolling")
4530     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
4531     protected int mScrollY;
4532 
4533     /**
4534      * The final computed left padding in pixels that is used for drawing. This is the distance in
4535      * pixels between the left edge of this view and the left edge of its content.
4536      * {@hide}
4537      */
4538     @ViewDebug.ExportedProperty(category = "padding")
4539     @UnsupportedAppUsage
4540     protected int mPaddingLeft = 0;
4541     /**
4542      * The final computed right padding in pixels that is used for drawing. This is the distance in
4543      * pixels between the right edge of this view and the right edge of its content.
4544      * {@hide}
4545      */
4546     @ViewDebug.ExportedProperty(category = "padding")
4547     @UnsupportedAppUsage
4548     protected int mPaddingRight = 0;
4549     /**
4550      * The final computed top padding in pixels that is used for drawing. This is the distance in
4551      * pixels between the top edge of this view and the top edge of its content.
4552      * {@hide}
4553      */
4554     @ViewDebug.ExportedProperty(category = "padding")
4555     @UnsupportedAppUsage
4556     protected int mPaddingTop;
4557     /**
4558      * The final computed bottom padding in pixels that is used for drawing. This is the distance in
4559      * pixels between the bottom edge of this view and the bottom edge of its content.
4560      * {@hide}
4561      */
4562     @ViewDebug.ExportedProperty(category = "padding")
4563     @UnsupportedAppUsage
4564     protected int mPaddingBottom;
4565 
4566     /**
4567      * The amount of pixel offset applied to the left edge of this view's handwriting bounds.
4568      */
4569     private float mHandwritingBoundsOffsetLeft;
4570 
4571     /**
4572      * The amount of pixel offset applied to the top edge of this view's handwriting bounds.
4573      */
4574     private float mHandwritingBoundsOffsetTop;
4575 
4576     /**
4577      * The amount of pixel offset applied to the right edge of this view's handwriting bounds.
4578      */
4579     private float mHandwritingBoundsOffsetRight;
4580 
4581     /**
4582      * The amount of pixel offset applied to the bottom edge of this view's handwriting bounds.
4583      */
4584     private float mHandwritingBoundsOffsetBottom;
4585 
4586     /**
4587      * The layout insets in pixels, that is the distance in pixels between the
4588      * visible edges of this view its bounds.
4589      */
4590     private Insets mLayoutInsets;
4591 
4592     /**
4593      * Briefly describes the state of the view and is primarily used for accessibility support.
4594      */
4595     private CharSequence mStateDescription;
4596 
4597     /**
4598      * Briefly describes the view and is primarily used for accessibility support.
4599      */
4600     private CharSequence mContentDescription;
4601 
4602     /**
4603      * If this view represents a distinct part of the window, it can have a title that labels the
4604      * area.
4605      */
4606     private CharSequence mAccessibilityPaneTitle;
4607 
4608     /**
4609      * Describes whether this view should only allow interactions from
4610      * {@link android.accessibilityservice.AccessibilityService}s with the
4611      * {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property
4612      * set to true.
4613      */
4614     private int mExplicitAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_AUTO;
4615     /** Used to calculate and cache {@link #isAccessibilityDataSensitive()}. */
4616     private int mInferredAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_AUTO;
4617 
4618     /**
4619      * Specifies the id of a view for which this view serves as a label for
4620      * accessibility purposes.
4621      */
4622     private int mLabelForId = View.NO_ID;
4623 
4624     /**
4625      * Predicate for matching labeled view id with its label for
4626      * accessibility purposes.
4627      */
4628     private MatchLabelForPredicate mMatchLabelForPredicate;
4629 
4630     /**
4631      * Specifies a view before which this one is visited in accessibility traversal.
4632      */
4633     private int mAccessibilityTraversalBeforeId = NO_ID;
4634 
4635     /**
4636      * Specifies a view after which this one is visited in accessibility traversal.
4637      */
4638     private int mAccessibilityTraversalAfterId = NO_ID;
4639 
4640     /**
4641      * Predicate for matching a view by its id.
4642      */
4643     private MatchIdPredicate mMatchIdPredicate;
4644 
4645     /**
4646      * The right padding after RTL resolution, but before taking account of scroll bars.
4647      *
4648      * @hide
4649      */
4650     @ViewDebug.ExportedProperty(category = "padding")
4651     protected int mUserPaddingRight;
4652 
4653     /**
4654      * The resolved bottom padding before taking account of scroll bars.
4655      *
4656      * @hide
4657      */
4658     @ViewDebug.ExportedProperty(category = "padding")
4659     protected int mUserPaddingBottom;
4660 
4661     /**
4662      * The left padding after RTL resolution, but before taking account of scroll bars.
4663      *
4664      * @hide
4665      */
4666     @ViewDebug.ExportedProperty(category = "padding")
4667     protected int mUserPaddingLeft;
4668 
4669     /**
4670      * Cache the paddingStart set by the user to append to the scrollbar's size.
4671      *
4672      */
4673     @ViewDebug.ExportedProperty(category = "padding")
4674     int mUserPaddingStart;
4675 
4676     /**
4677      * Cache the paddingEnd set by the user to append to the scrollbar's size.
4678      *
4679      */
4680     @ViewDebug.ExportedProperty(category = "padding")
4681     int mUserPaddingEnd;
4682 
4683     /**
4684      * The left padding as set by a setter method, a background's padding, or via XML property
4685      * resolution. This value is the padding before LTR resolution or taking account of scrollbars.
4686      *
4687      * @hide
4688      */
4689     int mUserPaddingLeftInitial;
4690 
4691     /**
4692      * The right padding as set by a setter method, a background's padding, or via XML property
4693      * resolution. This value is the padding before LTR resolution or taking account of scrollbars.
4694      *
4695      * @hide
4696      */
4697     int mUserPaddingRightInitial;
4698 
4699     /**
4700      * Default undefined padding
4701      */
4702     private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
4703 
4704     /**
4705      * Cache if a left padding has been defined explicitly via padding, horizontal padding,
4706      * or leftPadding in XML, or by setPadding(...) or setRelativePadding(...)
4707      */
4708     private boolean mLeftPaddingDefined = false;
4709 
4710     /**
4711      * Cache if a right padding has been defined explicitly via padding, horizontal padding,
4712      * or rightPadding in XML, or by setPadding(...) or setRelativePadding(...)
4713      */
4714     private boolean mRightPaddingDefined = false;
4715 
4716     /**
4717      * @hide
4718      */
4719     int mOldWidthMeasureSpec = Integer.MIN_VALUE;
4720     /**
4721      * @hide
4722      */
4723     int mOldHeightMeasureSpec = Integer.MIN_VALUE;
4724 
4725     private LongSparseLongArray mMeasureCache;
4726 
4727     @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
4728     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
4729     private Drawable mBackground;
4730     private TintInfo mBackgroundTint;
4731 
4732     @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
4733     private ForegroundInfo mForegroundInfo;
4734 
4735     private Drawable mScrollIndicatorDrawable;
4736 
4737     /**
4738      * RenderNode used for backgrounds.
4739      * <p>
4740      * When non-null and valid, this is expected to contain an up-to-date copy
4741      * of the background drawable. It is cleared on temporary detach, and reset
4742      * on cleanup.
4743      * @hide
4744      */
4745     RenderNode mBackgroundRenderNode;
4746 
4747     @UnsupportedAppUsage
4748     private int mBackgroundResource;
4749     private boolean mBackgroundSizeChanged;
4750 
4751     /** The default focus highlight.
4752      * @see #mDefaultFocusHighlightEnabled
4753      * @see Drawable#hasFocusStateSpecified()
4754      */
4755     private Drawable mDefaultFocusHighlight;
4756     private Drawable mDefaultFocusHighlightCache;
4757     private boolean mDefaultFocusHighlightSizeChanged;
4758     /**
4759      * True if the default focus highlight is needed on the target device.
4760      */
4761     private static boolean sUseDefaultFocusHighlight;
4762 
4763     /**
4764      * True if zero-sized views can be focused.
4765      */
4766     private static boolean sCanFocusZeroSized;
4767 
4768     /**
4769      * Always assign focus if a focusable View is available.
4770      */
4771     private static boolean sAlwaysAssignFocus;
4772 
4773     private String mTransitionName;
4774 
4775     static class TintInfo {
4776         ColorStateList mTintList;
4777         BlendMode mBlendMode;
4778         boolean mHasTintMode;
4779         boolean mHasTintList;
4780     }
4781 
4782     private static class ForegroundInfo {
4783         private Drawable mDrawable;
4784         private TintInfo mTintInfo;
4785         private int mGravity = Gravity.FILL;
4786         private boolean mInsidePadding = true;
4787         private boolean mBoundsChanged = true;
4788         private final Rect mSelfBounds = new Rect();
4789         private final Rect mOverlayBounds = new Rect();
4790     }
4791 
4792     static class ListenerInfo {
4793 
4794         @UnsupportedAppUsage
ListenerInfo()4795         ListenerInfo() {
4796         }
4797 
4798         /**
4799          * Listener used to dispatch focus change events.
4800          * This field should be made private, so it is hidden from the SDK.
4801          * {@hide}
4802          */
4803         @UnsupportedAppUsage
4804         protected OnFocusChangeListener mOnFocusChangeListener;
4805 
4806         /**
4807          * Listeners for layout change events.
4808          */
4809         private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
4810 
4811         protected OnScrollChangeListener mOnScrollChangeListener;
4812 
4813         /**
4814          * Listeners for attach events.
4815          */
4816         private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
4817 
4818         /**
4819          * Listener used to dispatch click events.
4820          * This field should be made private, so it is hidden from the SDK.
4821          * {@hide}
4822          */
4823         @UnsupportedAppUsage
4824         public OnClickListener mOnClickListener;
4825 
4826         /**
4827          * Listener used to dispatch long click events.
4828          * This field should be made private, so it is hidden from the SDK.
4829          * {@hide}
4830          */
4831         @UnsupportedAppUsage
4832         protected OnLongClickListener mOnLongClickListener;
4833 
4834         /**
4835          * Listener used to dispatch context click events. This field should be made private, so it
4836          * is hidden from the SDK.
4837          * {@hide}
4838          */
4839         protected OnContextClickListener mOnContextClickListener;
4840 
4841         /**
4842          * Listener used to build the context menu.
4843          * This field should be made private, so it is hidden from the SDK.
4844          * {@hide}
4845          */
4846         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
4847         protected OnCreateContextMenuListener mOnCreateContextMenuListener;
4848 
4849         @UnsupportedAppUsage
4850         private OnKeyListener mOnKeyListener;
4851 
4852         @UnsupportedAppUsage
4853         private OnTouchListener mOnTouchListener;
4854 
4855         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
4856         private OnHoverListener mOnHoverListener;
4857 
4858         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
4859         private OnGenericMotionListener mOnGenericMotionListener;
4860 
4861         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
4862         private OnDragListener mOnDragListener;
4863 
4864         private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
4865 
4866         OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
4867 
4868         OnCapturedPointerListener mOnCapturedPointerListener;
4869 
4870         private ArrayList<OnUnhandledKeyEventListener> mUnhandledKeyListeners;
4871 
4872         WindowInsetsAnimation.Callback mWindowInsetsAnimationCallback;
4873 
4874         /**
4875          * This lives here since it's only valid for interactive views. This list is null
4876          * until its first use.
4877          */
4878         private List<Rect> mSystemGestureExclusionRects = null;
4879         private List<Rect> mKeepClearRects = null;
4880         private List<Rect> mUnrestrictedKeepClearRects = null;
4881         private boolean mPreferKeepClear = false;
4882         private Rect mHandwritingArea = null;
4883 
4884         /**
4885          * Used to track {@link #mSystemGestureExclusionRects}, {@link #mKeepClearRects} and
4886          * {@link #mHandwritingArea}.
4887          */
4888         public RenderNode.PositionUpdateListener mPositionUpdateListener;
4889         private Runnable mPositionChangedUpdate;
4890 
4891         /**
4892          * Allows the application to implement custom scroll capture support.
4893          */
4894         ScrollCaptureCallback mScrollCaptureCallback;
4895 
4896         @Nullable
4897         private OnReceiveContentListener mOnReceiveContentListener;
4898     }
4899 
4900     @UnsupportedAppUsage
4901     ListenerInfo mListenerInfo;
4902 
4903     private static class TooltipInfo {
4904         /**
4905          * Text to be displayed in a tooltip popup.
4906          */
4907         @Nullable
4908         CharSequence mTooltipText;
4909 
4910         /**
4911          * View-relative position of the tooltip anchor point.
4912          */
4913         int mAnchorX;
4914         int mAnchorY;
4915 
4916         /**
4917          * The tooltip popup.
4918          */
4919         @Nullable
4920         TooltipPopup mTooltipPopup;
4921 
4922         /**
4923          * Set to true if the tooltip was shown as a result of a long click.
4924          */
4925         boolean mTooltipFromLongClick;
4926 
4927         /**
4928          * Keep these Runnables so that they can be used to reschedule.
4929          */
4930         Runnable mShowTooltipRunnable;
4931         Runnable mHideTooltipRunnable;
4932 
4933         /**
4934          * Hover move is ignored if it is within this distance in pixels from the previous one.
4935          */
4936         int mHoverSlop;
4937 
4938         /**
4939          * Update the anchor position if it significantly (that is by at least mHoverSlop)
4940          * different from the previously stored position. Ignoring insignificant changes
4941          * filters out the jitter which is typical for such input sources as stylus.
4942          *
4943          * @return True if the position has been updated.
4944          */
updateAnchorPos(MotionEvent event)4945         private boolean updateAnchorPos(MotionEvent event) {
4946             final int newAnchorX = (int) event.getX();
4947             final int newAnchorY = (int) event.getY();
4948             if (Math.abs(newAnchorX - mAnchorX) <= mHoverSlop
4949                     && Math.abs(newAnchorY - mAnchorY) <= mHoverSlop) {
4950                 return false;
4951             }
4952             mAnchorX = newAnchorX;
4953             mAnchorY = newAnchorY;
4954             return true;
4955         }
4956 
4957         /**
4958          *  Clear the anchor position to ensure that the next change is considered significant.
4959          */
clearAnchorPos()4960         private void clearAnchorPos() {
4961             mAnchorX = Integer.MAX_VALUE;
4962             mAnchorY = Integer.MAX_VALUE;
4963         }
4964     }
4965 
4966     TooltipInfo mTooltipInfo;
4967 
4968     // Temporary values used to hold (x,y) coordinates when delegating from the
4969     // two-arg performLongClick() method to the legacy no-arg version.
4970     private float mLongClickX = Float.NaN;
4971     private float mLongClickY = Float.NaN;
4972 
4973     /**
4974      * The application environment this view lives in.
4975      * This field should be made private, so it is hidden from the SDK.
4976      * {@hide}
4977      */
4978     @ViewDebug.ExportedProperty(deepExport = true)
4979     @UnsupportedAppUsage
4980     @UiContext
4981     protected Context mContext;
4982 
4983     @UnsupportedAppUsage
4984     private final Resources mResources;
4985 
4986     @UnsupportedAppUsage
4987     private ScrollabilityCache mScrollCache;
4988 
4989     private int[] mDrawableState = null;
4990 
4991     ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
4992 
4993     /**
4994      * Animator that automatically runs based on state changes.
4995      */
4996     private StateListAnimator mStateListAnimator;
4997 
4998     /**
4999      * When this view has focus and the next focus is {@link #FOCUS_LEFT},
5000      * the user may specify which view to go to next.
5001      */
5002     private int mNextFocusLeftId = View.NO_ID;
5003 
5004     /**
5005      * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
5006      * the user may specify which view to go to next.
5007      */
5008     private int mNextFocusRightId = View.NO_ID;
5009 
5010     /**
5011      * When this view has focus and the next focus is {@link #FOCUS_UP},
5012      * the user may specify which view to go to next.
5013      */
5014     private int mNextFocusUpId = View.NO_ID;
5015 
5016     /**
5017      * When this view has focus and the next focus is {@link #FOCUS_DOWN},
5018      * the user may specify which view to go to next.
5019      */
5020     private int mNextFocusDownId = View.NO_ID;
5021 
5022     /**
5023      * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
5024      * the user may specify which view to go to next.
5025      */
5026     int mNextFocusForwardId = View.NO_ID;
5027 
5028     /**
5029      * User-specified next keyboard navigation cluster in the {@link #FOCUS_FORWARD} direction.
5030      *
5031      * @see #findUserSetNextKeyboardNavigationCluster(View, int)
5032      */
5033     int mNextClusterForwardId = View.NO_ID;
5034 
5035     /**
5036      * Whether this View should use a default focus highlight when it gets focused but doesn't
5037      * have {@link android.R.attr#state_focused} defined in its background.
5038      */
5039     boolean mDefaultFocusHighlightEnabled = true;
5040 
5041     private CheckForLongPress mPendingCheckForLongPress;
5042     @UnsupportedAppUsage
5043     private CheckForTap mPendingCheckForTap = null;
5044     private PerformClick mPerformClick;
5045     private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
5046     private SendAccessibilityEventThrottle mSendStateChangedAccessibilityEvent;
5047     private UnsetPressedState mUnsetPressedState;
5048 
5049     /**
5050      * Whether the long press's action has been invoked.  The tap's action is invoked on the
5051      * up event while a long press is invoked as soon as the long press duration is reached, so
5052      * a long press could be performed before the tap is checked, in which case the tap's action
5053      * should not be invoked.
5054      */
5055     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
5056     private boolean mHasPerformedLongPress;
5057 
5058     /**
5059      * Whether a context click button is currently pressed down. This is true when the stylus is
5060      * touching the screen and the primary button has been pressed, or if a mouse's right button is
5061      * pressed. This is false once the button is released or if the stylus has been lifted.
5062      */
5063     private boolean mInContextButtonPress;
5064 
5065     /**
5066      * Whether the next up event should be ignored for the purposes of gesture recognition. This is
5067      * true after a stylus button press has occured, when the next up event should not be recognized
5068      * as a tap.
5069      */
5070     private boolean mIgnoreNextUpEvent;
5071 
5072     /**
5073      * The minimum height of the view. We'll try our best to have the height
5074      * of this view to at least this amount.
5075      */
5076     @ViewDebug.ExportedProperty(category = "measurement")
5077     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
5078     private int mMinHeight;
5079 
5080     /**
5081      * The minimum width of the view. We'll try our best to have the width
5082      * of this view to at least this amount.
5083      */
5084     @ViewDebug.ExportedProperty(category = "measurement")
5085     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
5086     private int mMinWidth;
5087 
5088     /**
5089      * The delegate to handle touch events that are physically in this view
5090      * but should be handled by another view.
5091      */
5092     private TouchDelegate mTouchDelegate = null;
5093 
5094     /**
5095      * While touch exploration is in use, set to true when hovering across boundaries and
5096      * inside the touch area of the delegate at receiving {@link MotionEvent#ACTION_HOVER_ENTER}
5097      * or {@link MotionEvent#ACTION_HOVER_MOVE}. False when leaving boundaries or receiving a
5098      * {@link MotionEvent#ACTION_HOVER_EXIT}.
5099      * Note that children of view group are excluded in the touch area.
5100      * @see #dispatchTouchExplorationHoverEvent
5101      */
5102     private boolean mHoveringTouchDelegate = false;
5103 
5104     // These two fields are set if the view is a handwriting delegator.
5105     private Runnable mHandwritingDelegatorCallback;
5106     private String mAllowedHandwritingDelegatePackageName;
5107 
5108     // These two fields are set if the view is a handwriting delegate.
5109     private boolean mIsHandwritingDelegate;
5110     private String mAllowedHandwritingDelegatorPackageName;
5111 
5112     /**
5113      * Solid color to use as a background when creating the drawing cache. Enables
5114      * the cache to use 16 bit bitmaps instead of 32 bit.
5115      */
5116     private int mDrawingCacheBackgroundColor = 0;
5117 
5118     /**
5119      * Special tree observer used when mAttachInfo is null.
5120      */
5121     private ViewTreeObserver mFloatingTreeObserver;
5122 
5123     /**
5124      * Cache the touch slop from the context that created the view.
5125      */
5126     private int mTouchSlop;
5127 
5128     /**
5129      * Cache the ambiguous gesture multiplier from the context that created the view.
5130      */
5131     private float mAmbiguousGestureMultiplier;
5132 
5133     /**
5134      * Object that handles automatic animation of view properties.
5135      */
5136     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
5137     private ViewPropertyAnimator mAnimator = null;
5138 
5139     /**
5140      * List of registered FrameMetricsObservers.
5141      */
5142     private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
5143 
5144     /**
5145      * Flag indicating that a drag can cross window boundaries.  When
5146      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
5147      * with this flag set, all visible applications with targetSdkVersion >=
5148      * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
5149      * in the drag operation and receive the dragged content.
5150      *
5151      * <p>If this is the only flag set, then the drag recipient will only have access to text data
5152      * and intents contained in the {@link ClipData} object. Access to URIs contained in the
5153      * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p>
5154      */
5155     public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
5156 
5157     /**
5158      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
5159      * request read access to the content URI(s) contained in the {@link ClipData} object.
5160      * @see android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION
5161      */
5162     public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
5163 
5164     /**
5165      * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
5166      * request write access to the content URI(s) contained in the {@link ClipData} object.
5167      * @see android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION
5168      */
5169     public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
5170 
5171     /**
5172      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
5173      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
5174      * reboots until explicitly revoked with
5175      * {@link android.content.Context#revokeUriPermission(Uri, int)} Context.revokeUriPermission}.
5176      * @see android.content.Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION
5177      */
5178     public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
5179             Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
5180 
5181     /**
5182      * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
5183      * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
5184      * match against the original granted URI.
5185      * @see android.content.Intent#FLAG_GRANT_PREFIX_URI_PERMISSION
5186      */
5187     public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
5188             Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
5189 
5190     /**
5191      * Flag indicating that the drag shadow will be opaque.  When
5192      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
5193      * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
5194      */
5195     public static final int DRAG_FLAG_OPAQUE = 1 << 9;
5196 
5197     /**
5198      * Flag indicating that the drag was initiated with
5199      * {@link AccessibilityNodeInfo.AccessibilityAction#ACTION_DRAG_START}. When
5200      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called, this
5201      * is used by the system to perform a drag without animations.
5202      */
5203     public static final int DRAG_FLAG_ACCESSIBILITY_ACTION = 1 << 10;
5204 
5205     /**
5206      * Flag indicating that the caller desires to take ownership of the drag surface for handling
5207      * the animation associated with an unhandled drag.  It is mainly useful if the view starting
5208      * a global drag changes visibility during the gesture and the default animation of animating
5209      * the surface back to the origin is not sufficient.
5210      *
5211      * The calling app must hold the {@link android.Manifest.permission#START_TASKS_FROM_RECENTS}
5212      * permission and will receive the drag surface as a part of
5213      * {@link action.view.DragEvent#ACTION_DRAG_ENDED} only if the drag event's
5214      * {@link action.view.DragEvent#getDragResult()} is {@code false}.  The caller is responsible
5215      * for removing the surface after its animation.
5216      *
5217      * This flag has no effect if the system decides that a cancel-drag animation does not need to
5218      * occur.
5219      * @hide
5220      */
5221     public static final int DRAG_FLAG_REQUEST_SURFACE_FOR_RETURN_ANIMATION = 1 << 11;
5222 
5223     /**
5224      * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
5225      */
5226     private float mVerticalScrollFactor;
5227 
5228     /**
5229      * Position of the vertical scroll bar.
5230      */
5231     @UnsupportedAppUsage
5232     private int mVerticalScrollbarPosition;
5233 
5234     /**
5235      * Position the scroll bar at the default position as determined by the system.
5236      */
5237     public static final int SCROLLBAR_POSITION_DEFAULT = 0;
5238 
5239     /**
5240      * Position the scroll bar along the left edge.
5241      */
5242     public static final int SCROLLBAR_POSITION_LEFT = 1;
5243 
5244     /**
5245      * Position the scroll bar along the right edge.
5246      */
5247     public static final int SCROLLBAR_POSITION_RIGHT = 2;
5248 
5249     /**
5250      * Indicates that the view does not have a layer.
5251      *
5252      * @see #getLayerType()
5253      * @see #setLayerType(int, android.graphics.Paint)
5254      * @see #LAYER_TYPE_SOFTWARE
5255      * @see #LAYER_TYPE_HARDWARE
5256      */
5257     public static final int LAYER_TYPE_NONE = 0;
5258 
5259     /**
5260      * <p>Indicates that the view has a software layer. A software layer is backed
5261      * by a bitmap and causes the view to be rendered using Android's software
5262      * rendering pipeline, even if hardware acceleration is enabled.</p>
5263      *
5264      * <p>Software layers have various usages:</p>
5265      * <p>When the application is not using hardware acceleration, a software layer
5266      * is useful to apply a specific color filter and/or blending mode and/or
5267      * translucency to a view and all its children.</p>
5268      * <p>When the application is using hardware acceleration, a software layer
5269      * is useful to render drawing primitives not supported by the hardware
5270      * accelerated pipeline. It can also be used to cache a complex view tree
5271      * into a texture and reduce the complexity of drawing operations. For instance,
5272      * when animating a complex view tree with a translation, a software layer can
5273      * be used to render the view tree only once.</p>
5274      * <p>Software layers should be avoided when the affected view tree updates
5275      * often. Every update will require to re-render the software layer, which can
5276      * potentially be slow (particularly when hardware acceleration is turned on
5277      * since the layer will have to be uploaded into a hardware texture after every
5278      * update.)</p>
5279      *
5280      * @see #getLayerType()
5281      * @see #setLayerType(int, android.graphics.Paint)
5282      * @see #LAYER_TYPE_NONE
5283      * @see #LAYER_TYPE_HARDWARE
5284      */
5285     public static final int LAYER_TYPE_SOFTWARE = 1;
5286 
5287     /**
5288      * <p>Indicates that the view has a hardware layer. A hardware layer is backed
5289      * by a hardware specific texture (generally Frame Buffer Objects or FBO on
5290      * OpenGL hardware) and causes the view to be rendered using Android's hardware
5291      * rendering pipeline, but only if hardware acceleration is turned on for the
5292      * view hierarchy. When hardware acceleration is turned off, hardware layers
5293      * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
5294      *
5295      * <p>A hardware layer is useful to apply a specific color filter and/or
5296      * blending mode and/or translucency to a view and all its children.</p>
5297      * <p>A hardware layer can be used to cache a complex view tree into a
5298      * texture and reduce the complexity of drawing operations. For instance,
5299      * when animating a complex view tree with a translation, a hardware layer can
5300      * be used to render the view tree only once.</p>
5301      * <p>A hardware layer can also be used to increase the rendering quality when
5302      * rotation transformations are applied on a view. It can also be used to
5303      * prevent potential clipping issues when applying 3D transforms on a view.</p>
5304      *
5305      * @see #getLayerType()
5306      * @see #setLayerType(int, android.graphics.Paint)
5307      * @see #LAYER_TYPE_NONE
5308      * @see #LAYER_TYPE_SOFTWARE
5309      */
5310     public static final int LAYER_TYPE_HARDWARE = 2;
5311 
5312     /** @hide */
5313     @IntDef(prefix = { "LAYER_TYPE_" }, value = {
5314             LAYER_TYPE_NONE,
5315             LAYER_TYPE_SOFTWARE,
5316             LAYER_TYPE_HARDWARE
5317     })
5318     @Retention(RetentionPolicy.SOURCE)
5319     public @interface LayerType {}
5320 
5321     @ViewDebug.ExportedProperty(category = "drawing", mapping = {
5322             @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
5323             @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
5324             @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
5325     })
5326     int mLayerType = LAYER_TYPE_NONE;
5327     Paint mLayerPaint;
5328 
5329     /**
5330      * Set to true when drawing cache is enabled and cannot be created.
5331      *
5332      * @hide
5333      */
5334     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
5335     public boolean mCachingFailed;
5336     @UnsupportedAppUsage
5337     private Bitmap mDrawingCache;
5338     @UnsupportedAppUsage
5339     private Bitmap mUnscaledDrawingCache;
5340 
5341     /**
5342      * RenderNode holding View properties, potentially holding a DisplayList of View content.
5343      * <p>
5344      * When non-null and valid, this is expected to contain an up-to-date copy
5345      * of the View content. Its DisplayList content is cleared on temporary detach and reset on
5346      * cleanup.
5347      */
5348     @UnsupportedAppUsage
5349     final RenderNode mRenderNode;
5350 
5351     /**
5352      * Set to true when the view is sending hover accessibility events because it
5353      * is the innermost hovered view.
5354      */
5355     private boolean mSendingHoverAccessibilityEvents;
5356 
5357     /**
5358      * Delegate for injecting accessibility functionality.
5359      */
5360     @UnsupportedAppUsage
5361     AccessibilityDelegate mAccessibilityDelegate;
5362 
5363     /**
5364      * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
5365      * and add/remove objects to/from the overlay directly through the Overlay methods.
5366      */
5367     ViewOverlay mOverlay;
5368 
5369     /**
5370      * The currently active parent view for receiving delegated nested scrolling events.
5371      * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
5372      * by {@link #stopNestedScroll()} at the same point where we clear
5373      * requestDisallowInterceptTouchEvent.
5374      */
5375     private ViewParent mNestedScrollingParent;
5376 
5377     /**
5378      * Consistency verifier for debugging purposes.
5379      * @hide
5380      */
5381     protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
5382             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
5383                     new InputEventConsistencyVerifier(this, 0) : null;
5384 
5385     private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
5386 
5387     private int[] mTempNestedScrollConsumed;
5388 
5389     /**
5390      * An overlay is going to draw this View instead of being drawn as part of this
5391      * View's parent. mGhostView is the View in the Overlay that must be invalidated
5392      * when this view is invalidated.
5393      */
5394     GhostView mGhostView;
5395 
5396     /**
5397      * Holds pairs of adjacent attribute data: attribute name followed by its value.
5398      * @hide
5399      */
5400     @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
5401     public String[] mAttributes;
5402 
5403     /**
5404      * Maps a Resource id to its name.
5405      */
5406     private static SparseArray<String> mAttributeMap;
5407 
5408     /**
5409      * Queue of pending runnables. Used to postpone calls to post() until this
5410      * view is attached and has a handler.
5411      */
5412     private HandlerActionQueue mRunQueue;
5413 
5414     /**
5415      * The pointer icon when the mouse hovers on this view. The default is null.
5416      */
5417     private PointerIcon mMousePointerIcon;
5418 
5419     /**
5420      * @hide
5421      */
5422     @UnsupportedAppUsage
5423     String mStartActivityRequestWho;
5424 
5425     @Nullable
5426     private RoundScrollbarRenderer mRoundScrollbarRenderer;
5427 
5428     /** Used to delay visibility updates sent to the autofill manager */
5429     private Handler mVisibilityChangeForAutofillHandler;
5430 
5431     /**
5432      * Used when app developers explicitly set the {@link ContentCaptureSession} associated with the
5433      * view (through {@link #setContentCaptureSession(ContentCaptureSession)}.
5434      */
5435     @Nullable
5436     private ContentCaptureSession mContentCaptureSession;
5437 
5438     /**
5439      * Whether {@link ContentCaptureSession} is cached, resets on {@link #invalidate()}.
5440      */
5441     private boolean mContentCaptureSessionCached;
5442 
5443     @LayoutRes
5444     private int mSourceLayoutId = ID_NULL;
5445 
5446     @Nullable
5447     private SparseIntArray mAttributeSourceResId;
5448 
5449     @Nullable
5450     private SparseArray<int[]> mAttributeResolutionStacks;
5451 
5452     @StyleRes
5453     private int mExplicitStyle;
5454 
5455     /**
5456      * Specifies which input source classes should provide unbuffered input events to this view
5457      *
5458      * @see View#requestUnbufferedDispatch(int)
5459      */
5460     @InputSourceClass
5461     int mUnbufferedInputSource = InputDevice.SOURCE_CLASS_NONE;
5462 
5463     @Nullable
5464     private String[] mReceiveContentMimeTypes;
5465 
5466     @Nullable
5467     private ViewTranslationCallback mViewTranslationCallback;
5468 
5469     @Nullable
5470 
5471     private ViewTranslationResponse mViewTranslationResponse;
5472 
5473     /**
5474      * Simple constructor to use when creating a view from code.
5475      *
5476      * @param context The Context the view is running in, through which it can
5477      *        access the current theme, resources, etc.
5478      */
View(Context context)5479     public View(Context context) {
5480         mContext = context;
5481         mResources = context != null ? context.getResources() : null;
5482         mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | FOCUSABLE_AUTO;
5483         // Set some flags defaults
5484         mPrivateFlags2 =
5485                 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
5486                 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
5487                 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
5488                 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
5489                 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
5490                 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
5491 
5492         final ViewConfiguration configuration = ViewConfiguration.get(context);
5493         mTouchSlop = configuration.getScaledTouchSlop();
5494         mAmbiguousGestureMultiplier = configuration.getScaledAmbiguousGestureMultiplier();
5495 
5496         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
5497         mUserPaddingStart = UNDEFINED_PADDING;
5498         mUserPaddingEnd = UNDEFINED_PADDING;
5499         mRenderNode = RenderNode.create(getClass().getName(), new ViewAnimationHostBridge(this));
5500 
5501         if (!sCompatibilityDone && context != null) {
5502             final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
5503 
5504             // Older apps may need this compatibility hack for measurement.
5505             sUseBrokenMakeMeasureSpec = targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1;
5506 
5507             // Older apps expect onMeasure() to always be called on a layout pass, regardless
5508             // of whether a layout was requested on that View.
5509             sIgnoreMeasureCache = targetSdkVersion < Build.VERSION_CODES.KITKAT;
5510 
5511             // In M and newer, our widgets can pass a "hint" value in the size
5512             // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
5513             // know what the expected parent size is going to be, so e.g. list items can size
5514             // themselves at 1/3 the size of their container. It breaks older apps though,
5515             // specifically apps that use some popular open source libraries.
5516             sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < Build.VERSION_CODES.M;
5517 
5518             // Old versions of the platform would give different results from
5519             // LinearLayout measurement passes using EXACTLY and non-EXACTLY
5520             // modes, so we always need to run an additional EXACTLY pass.
5521             sAlwaysRemeasureExactly = targetSdkVersion <= Build.VERSION_CODES.M;
5522 
5523             // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
5524             // On N+, we throw, but that breaks compatibility with apps that use these methods.
5525             sTextureViewIgnoresDrawableSetters = targetSdkVersion <= Build.VERSION_CODES.M;
5526 
5527             // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
5528             // in apps so we target check it to avoid breaking existing apps.
5529             sPreserveMarginParamsInLayoutParamConversion =
5530                     targetSdkVersion >= Build.VERSION_CODES.N;
5531 
5532             sCascadedDragDrop = targetSdkVersion < Build.VERSION_CODES.N;
5533 
5534             sHasFocusableExcludeAutoFocusable = targetSdkVersion < Build.VERSION_CODES.O;
5535 
5536             sAutoFocusableOffUIThreadWontNotifyParents = targetSdkVersion < Build.VERSION_CODES.O;
5537 
5538             sUseDefaultFocusHighlight = context.getResources().getBoolean(
5539                     com.android.internal.R.bool.config_useDefaultFocusHighlight);
5540 
5541             sThrowOnInvalidFloatProperties = targetSdkVersion >= Build.VERSION_CODES.P;
5542 
5543             sCanFocusZeroSized = targetSdkVersion < Build.VERSION_CODES.P;
5544 
5545             sAlwaysAssignFocus = targetSdkVersion < Build.VERSION_CODES.P;
5546 
5547             sAcceptZeroSizeDragShadow = targetSdkVersion < Build.VERSION_CODES.P;
5548 
5549             sBrokenInsetsDispatch = targetSdkVersion < Build.VERSION_CODES.R;
5550 
5551             sBrokenWindowBackground = targetSdkVersion < Build.VERSION_CODES.Q;
5552 
5553             GradientDrawable.sWrapNegativeAngleMeasurements =
5554                     targetSdkVersion >= Build.VERSION_CODES.Q;
5555 
5556             sForceLayoutWhenInsetsChanged = targetSdkVersion < Build.VERSION_CODES.R;
5557 
5558             sCompatibilityDone = true;
5559         }
5560     }
5561 
5562     /**
5563      * Constructor that is called when inflating a view from XML. This is called
5564      * when a view is being constructed from an XML file, supplying attributes
5565      * that were specified in the XML file. This version uses a default style of
5566      * 0, so the only attribute values applied are those in the Context's Theme
5567      * and the given AttributeSet.
5568      *
5569      * <p>
5570      * The method onFinishInflate() will be called after all children have been
5571      * added.
5572      *
5573      * @param context The Context the view is running in, through which it can
5574      *        access the current theme, resources, etc.
5575      * @param attrs The attributes of the XML tag that is inflating the view.
5576      * @see #View(Context, AttributeSet, int)
5577      */
5578     public View(Context context, @Nullable AttributeSet attrs) {
5579         this(context, attrs, 0);
5580     }
5581 
5582     /**
5583      * Perform inflation from XML and apply a class-specific base style from a
5584      * theme attribute. This constructor of View allows subclasses to use their
5585      * own base style when they are inflating. For example, a Button class's
5586      * constructor would call this version of the super class constructor and
5587      * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
5588      * allows the theme's button style to modify all of the base view attributes
5589      * (in particular its background) as well as the Button class's attributes.
5590      *
5591      * @param context The Context the view is running in, through which it can
5592      *        access the current theme, resources, etc.
5593      * @param attrs The attributes of the XML tag that is inflating the view.
5594      * @param defStyleAttr An attribute in the current theme that contains a
5595      *        reference to a style resource that supplies default values for
5596      *        the view. Can be 0 to not look for defaults.
5597      * @see #View(Context, AttributeSet)
5598      */
5599     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
5600         this(context, attrs, defStyleAttr, 0);
5601     }
5602 
5603     /**
5604      * Perform inflation from XML and apply a class-specific base style from a
5605      * theme attribute or style resource. This constructor of View allows
5606      * subclasses to use their own base style when they are inflating.
5607      * <p>
5608      * When determining the final value of a particular attribute, there are
5609      * four inputs that come into play:
5610      * <ol>
5611      * <li>Any attribute values in the given AttributeSet.
5612      * <li>The style resource specified in the AttributeSet (named "style").
5613      * <li>The default style specified by <var>defStyleAttr</var>.
5614      * <li>The default style specified by <var>defStyleRes</var>.
5615      * <li>The base values in this theme.
5616      * </ol>
5617      * <p>
5618      * Each of these inputs is considered in-order, with the first listed taking
5619      * precedence over the following ones. In other words, if in the
5620      * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
5621      * , then the button's text will <em>always</em> be black, regardless of
5622      * what is specified in any of the styles.
5623      *
5624      * @param context The Context the view is running in, through which it can
5625      *        access the current theme, resources, etc.
5626      * @param attrs The attributes of the XML tag that is inflating the view.
5627      * @param defStyleAttr An attribute in the current theme that contains a
5628      *        reference to a style resource that supplies default values for
5629      *        the view. Can be 0 to not look for defaults.
5630      * @param defStyleRes A resource identifier of a style resource that
5631      *        supplies default values for the view, used only if
5632      *        defStyleAttr is 0 or can not be found in the theme. Can be 0
5633      *        to not look for defaults.
5634      * @see #View(Context, AttributeSet, int)
5635      */
5636     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
5637         this(context);
5638 
5639         mSourceLayoutId = Resources.getAttributeSetSourceResId(attrs);
5640 
5641         final TypedArray a = context.obtainStyledAttributes(
5642                 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
5643 
5644         retrieveExplicitStyle(context.getTheme(), attrs);
5645         saveAttributeDataForStyleable(context, com.android.internal.R.styleable.View, attrs, a,
5646                 defStyleAttr, defStyleRes);
5647 
5648         if (sDebugViewAttributes) {
5649             saveAttributeData(attrs, a);
5650         }
5651 
5652         Drawable background = null;
5653 
5654         int leftPadding = -1;
5655         int topPadding = -1;
5656         int rightPadding = -1;
5657         int bottomPadding = -1;
5658         int startPadding = UNDEFINED_PADDING;
5659         int endPadding = UNDEFINED_PADDING;
5660 
5661         int padding = -1;
5662         int paddingHorizontal = -1;
5663         int paddingVertical = -1;
5664 
5665         int viewFlagValues = 0;
5666         int viewFlagMasks = 0;
5667 
5668         boolean setScrollContainer = false;
5669 
5670         int x = 0;
5671         int y = 0;
5672 
5673         float tx = 0;
5674         float ty = 0;
5675         float tz = 0;
5676         float elevation = 0;
5677         float rotation = 0;
5678         float rotationX = 0;
5679         float rotationY = 0;
5680         float sx = 1f;
5681         float sy = 1f;
5682         boolean transformSet = false;
5683 
5684         int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
5685         int overScrollMode = mOverScrollMode;
5686         boolean initializeScrollbars = false;
5687         boolean initializeScrollIndicators = false;
5688 
5689         boolean startPaddingDefined = false;
5690         boolean endPaddingDefined = false;
5691         boolean leftPaddingDefined = false;
5692         boolean rightPaddingDefined = false;
5693 
5694         final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
5695 
5696         // Set default values.
5697         viewFlagValues |= FOCUSABLE_AUTO;
5698         viewFlagMasks |= FOCUSABLE_AUTO;
5699 
5700         final int N = a.getIndexCount();
5701         for (int i = 0; i < N; i++) {
5702             int attr = a.getIndex(i);
5703             switch (attr) {
5704                 case com.android.internal.R.styleable.View_background:
5705                     background = a.getDrawable(attr);
5706                     break;
5707                 case com.android.internal.R.styleable.View_padding:
5708                     padding = a.getDimensionPixelSize(attr, -1);
5709                     mUserPaddingLeftInitial = padding;
5710                     mUserPaddingRightInitial = padding;
5711                     leftPaddingDefined = true;
5712                     rightPaddingDefined = true;
5713                     break;
5714                 case com.android.internal.R.styleable.View_paddingHorizontal:
5715                     paddingHorizontal = a.getDimensionPixelSize(attr, -1);
5716                     mUserPaddingLeftInitial = paddingHorizontal;
5717                     mUserPaddingRightInitial = paddingHorizontal;
5718                     leftPaddingDefined = true;
5719                     rightPaddingDefined = true;
5720                     break;
5721                 case com.android.internal.R.styleable.View_paddingVertical:
5722                     paddingVertical = a.getDimensionPixelSize(attr, -1);
5723                     break;
5724                 case com.android.internal.R.styleable.View_paddingLeft:
5725                     leftPadding = a.getDimensionPixelSize(attr, -1);
5726                     mUserPaddingLeftInitial = leftPadding;
5727                     leftPaddingDefined = true;
5728                     break;
5729                 case com.android.internal.R.styleable.View_paddingTop:
5730                     topPadding = a.getDimensionPixelSize(attr, -1);
5731                     break;
5732                 case com.android.internal.R.styleable.View_paddingRight:
5733                     rightPadding = a.getDimensionPixelSize(attr, -1);
5734                     mUserPaddingRightInitial = rightPadding;
5735                     rightPaddingDefined = true;
5736                     break;
5737                 case com.android.internal.R.styleable.View_paddingBottom:
5738                     bottomPadding = a.getDimensionPixelSize(attr, -1);
5739                     break;
5740                 case com.android.internal.R.styleable.View_paddingStart:
5741                     startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
5742                     startPaddingDefined = (startPadding != UNDEFINED_PADDING);
5743                     break;
5744                 case com.android.internal.R.styleable.View_paddingEnd:
5745                     endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
5746                     endPaddingDefined = (endPadding != UNDEFINED_PADDING);
5747                     break;
5748                 case com.android.internal.R.styleable.View_scrollX:
5749                     x = a.getDimensionPixelOffset(attr, 0);
5750                     break;
5751                 case com.android.internal.R.styleable.View_scrollY:
5752                     y = a.getDimensionPixelOffset(attr, 0);
5753                     break;
5754                 case com.android.internal.R.styleable.View_alpha:
5755                     setAlpha(a.getFloat(attr, 1f));
5756                     break;
5757                 case com.android.internal.R.styleable.View_transformPivotX:
5758                     setPivotX(a.getDimension(attr, 0));
5759                     break;
5760                 case com.android.internal.R.styleable.View_transformPivotY:
5761                     setPivotY(a.getDimension(attr, 0));
5762                     break;
5763                 case com.android.internal.R.styleable.View_translationX:
5764                     tx = a.getDimension(attr, 0);
5765                     transformSet = true;
5766                     break;
5767                 case com.android.internal.R.styleable.View_translationY:
5768                     ty = a.getDimension(attr, 0);
5769                     transformSet = true;
5770                     break;
5771                 case com.android.internal.R.styleable.View_translationZ:
5772                     tz = a.getDimension(attr, 0);
5773                     transformSet = true;
5774                     break;
5775                 case com.android.internal.R.styleable.View_elevation:
5776                     elevation = a.getDimension(attr, 0);
5777                     transformSet = true;
5778                     break;
5779                 case com.android.internal.R.styleable.View_rotation:
5780                     rotation = a.getFloat(attr, 0);
5781                     transformSet = true;
5782                     break;
5783                 case com.android.internal.R.styleable.View_rotationX:
5784                     rotationX = a.getFloat(attr, 0);
5785                     transformSet = true;
5786                     break;
5787                 case com.android.internal.R.styleable.View_rotationY:
5788                     rotationY = a.getFloat(attr, 0);
5789                     transformSet = true;
5790                     break;
5791                 case com.android.internal.R.styleable.View_scaleX:
5792                     sx = a.getFloat(attr, 1f);
5793                     transformSet = true;
5794                     break;
5795                 case com.android.internal.R.styleable.View_scaleY:
5796                     sy = a.getFloat(attr, 1f);
5797                     transformSet = true;
5798                     break;
5799                 case com.android.internal.R.styleable.View_id:
5800                     mID = a.getResourceId(attr, NO_ID);
5801                     break;
5802                 case com.android.internal.R.styleable.View_tag:
5803                     mTag = a.getText(attr);
5804                     break;
5805                 case com.android.internal.R.styleable.View_fitsSystemWindows:
5806                     if (a.getBoolean(attr, false)) {
5807                         viewFlagValues |= FITS_SYSTEM_WINDOWS;
5808                         viewFlagMasks |= FITS_SYSTEM_WINDOWS;
5809                     }
5810                     break;
5811                 case com.android.internal.R.styleable.View_focusable:
5812                     viewFlagValues = (viewFlagValues & ~FOCUSABLE_MASK) | getFocusableAttribute(a);
5813                     if ((viewFlagValues & FOCUSABLE_AUTO) == 0) {
5814                         viewFlagMasks |= FOCUSABLE_MASK;
5815                     }
5816                     break;
5817                 case com.android.internal.R.styleable.View_focusableInTouchMode:
5818                     if (a.getBoolean(attr, false)) {
5819                         // unset auto focus since focusableInTouchMode implies explicit focusable
5820                         viewFlagValues &= ~FOCUSABLE_AUTO;
5821                         viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
5822                         viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
5823                     }
5824                     break;
5825                 case com.android.internal.R.styleable.View_clickable:
5826                     if (a.getBoolean(attr, false)) {
5827                         viewFlagValues |= CLICKABLE;
5828                         viewFlagMasks |= CLICKABLE;
5829                     }
5830                     break;
5831                 case com.android.internal.R.styleable.View_allowClickWhenDisabled:
5832                     setAllowClickWhenDisabled(a.getBoolean(attr, false));
5833                     break;
5834                 case com.android.internal.R.styleable.View_longClickable:
5835                     if (a.getBoolean(attr, false)) {
5836                         viewFlagValues |= LONG_CLICKABLE;
5837                         viewFlagMasks |= LONG_CLICKABLE;
5838                     }
5839                     break;
5840                 case com.android.internal.R.styleable.View_contextClickable:
5841                     if (a.getBoolean(attr, false)) {
5842                         viewFlagValues |= CONTEXT_CLICKABLE;
5843                         viewFlagMasks |= CONTEXT_CLICKABLE;
5844                     }
5845                     break;
5846                 case com.android.internal.R.styleable.View_saveEnabled:
5847                     if (!a.getBoolean(attr, true)) {
5848                         viewFlagValues |= SAVE_DISABLED;
5849                         viewFlagMasks |= SAVE_DISABLED_MASK;
5850                     }
5851                     break;
5852                 case com.android.internal.R.styleable.View_duplicateParentState:
5853                     if (a.getBoolean(attr, false)) {
5854                         viewFlagValues |= DUPLICATE_PARENT_STATE;
5855                         viewFlagMasks |= DUPLICATE_PARENT_STATE;
5856                     }
5857                     break;
5858                 case com.android.internal.R.styleable.View_visibility:
5859                     final int visibility = a.getInt(attr, 0);
5860                     if (visibility != 0) {
5861                         viewFlagValues |= VISIBILITY_FLAGS[visibility];
5862                         viewFlagMasks |= VISIBILITY_MASK;
5863                     }
5864                     break;
5865                 case com.android.internal.R.styleable.View_layoutDirection:
5866                     // Clear any layout direction flags (included resolved bits) already set
5867                     mPrivateFlags2 &=
5868                             ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
5869                     // Set the layout direction flags depending on the value of the attribute
5870                     final int layoutDirection = a.getInt(attr, -1);
5871                     final int value = (layoutDirection != -1) ?
5872                             LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
5873                     mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
5874                     break;
5875                 case com.android.internal.R.styleable.View_drawingCacheQuality:
5876                     final int cacheQuality = a.getInt(attr, 0);
5877                     if (cacheQuality != 0) {
5878                         viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
5879                         viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
5880                     }
5881                     break;
5882                 case com.android.internal.R.styleable.View_contentDescription:
5883                     setContentDescription(a.getString(attr));
5884                     break;
5885                 case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
5886                     setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
5887                     break;
5888                 case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
5889                     setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
5890                     break;
5891                 case com.android.internal.R.styleable.View_labelFor:
5892                     setLabelFor(a.getResourceId(attr, NO_ID));
5893                     break;
5894                 case com.android.internal.R.styleable.View_soundEffectsEnabled:
5895                     if (!a.getBoolean(attr, true)) {
5896                         viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
5897                         viewFlagMasks |= SOUND_EFFECTS_ENABLED;
5898                     }
5899                     break;
5900                 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
5901                     if (!a.getBoolean(attr, true)) {
5902                         viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
5903                         viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
5904                     }
5905                     break;
5906                 case R.styleable.View_scrollbars:
5907                     final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
5908                     if (scrollbars != SCROLLBARS_NONE) {
5909                         viewFlagValues |= scrollbars;
5910                         viewFlagMasks |= SCROLLBARS_MASK;
5911                         initializeScrollbars = true;
5912                     }
5913                     break;
5914                 //noinspection deprecation
5915                 case R.styleable.View_fadingEdge:
5916                     if (targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
5917                         // Ignore the attribute starting with ICS
5918                         break;
5919                     }
5920                     // With builds < ICS, fall through and apply fading edges
5921                 case R.styleable.View_requiresFadingEdge:
5922                     final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
5923                     if (fadingEdge != FADING_EDGE_NONE) {
5924                         viewFlagValues |= fadingEdge;
5925                         viewFlagMasks |= FADING_EDGE_MASK;
5926                         initializeFadingEdgeInternal(a);
5927                     }
5928                     break;
5929                 case R.styleable.View_scrollbarStyle:
5930                     scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
5931                     if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
5932                         viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
5933                         viewFlagMasks |= SCROLLBARS_STYLE_MASK;
5934                     }
5935                     break;
5936                 case R.styleable.View_isScrollContainer:
5937                     setScrollContainer = true;
5938                     if (a.getBoolean(attr, false)) {
5939                         setScrollContainer(true);
5940                     }
5941                     break;
5942                 case com.android.internal.R.styleable.View_keepScreenOn:
5943                     if (a.getBoolean(attr, false)) {
5944                         viewFlagValues |= KEEP_SCREEN_ON;
5945                         viewFlagMasks |= KEEP_SCREEN_ON;
5946                     }
5947                     break;
5948                 case R.styleable.View_filterTouchesWhenObscured:
5949                     if (a.getBoolean(attr, false)) {
5950                         viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
5951                         viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
5952                     }
5953                     break;
5954                 case R.styleable.View_nextFocusLeft:
5955                     mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
5956                     break;
5957                 case R.styleable.View_nextFocusRight:
5958                     mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
5959                     break;
5960                 case R.styleable.View_nextFocusUp:
5961                     mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
5962                     break;
5963                 case R.styleable.View_nextFocusDown:
5964                     mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
5965                     break;
5966                 case R.styleable.View_nextFocusForward:
5967                     mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
5968                     break;
5969                 case R.styleable.View_nextClusterForward:
5970                     mNextClusterForwardId = a.getResourceId(attr, View.NO_ID);
5971                     break;
5972                 case R.styleable.View_minWidth:
5973                     mMinWidth = a.getDimensionPixelSize(attr, 0);
5974                     break;
5975                 case R.styleable.View_minHeight:
5976                     mMinHeight = a.getDimensionPixelSize(attr, 0);
5977                     break;
5978                 case R.styleable.View_onClick:
5979                     if (context.isRestricted()) {
5980                         throw new IllegalStateException("The android:onClick attribute cannot "
5981                                 + "be used within a restricted context");
5982                     }
5983 
5984                     final String handlerName = a.getString(attr);
5985                     if (handlerName != null) {
5986                         setOnClickListener(new DeclaredOnClickListener(this, handlerName));
5987                     }
5988                     break;
5989                 case R.styleable.View_overScrollMode:
5990                     overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
5991                     break;
5992                 case R.styleable.View_verticalScrollbarPosition:
5993                     mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
5994                     break;
5995                 case R.styleable.View_layerType:
5996                     setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
5997                     break;
5998                 case R.styleable.View_textDirection:
5999                     // Clear any text direction flag already set
6000                     mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
6001                     // Set the text direction flags depending on the value of the attribute
6002                     final int textDirection = a.getInt(attr, -1);
6003                     if (textDirection != -1) {
6004                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
6005                     }
6006                     break;
6007                 case R.styleable.View_textAlignment:
6008                     // Clear any text alignment flag already set
6009                     mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
6010                     // Set the text alignment flag depending on the value of the attribute
6011                     final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
6012                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
6013                     break;
6014                 case R.styleable.View_importantForAccessibility:
6015                     setImportantForAccessibility(a.getInt(attr,
6016                             IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
6017                     break;
6018                 case R.styleable.View_accessibilityDataSensitive:
6019                     setAccessibilityDataSensitive(a.getInt(attr,
6020                             ACCESSIBILITY_DATA_SENSITIVE_AUTO));
6021                     break;
6022                 case R.styleable.View_accessibilityLiveRegion:
6023                     setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
6024                     break;
6025                 case R.styleable.View_transitionName:
6026                     setTransitionName(a.getString(attr));
6027                     break;
6028                 case R.styleable.View_nestedScrollingEnabled:
6029                     setNestedScrollingEnabled(a.getBoolean(attr, false));
6030                     break;
6031                 case R.styleable.View_stateListAnimator:
6032                     setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
6033                             a.getResourceId(attr, 0)));
6034                     break;
6035                 case R.styleable.View_backgroundTint:
6036                     // This will get applied later during setBackground().
6037                     if (mBackgroundTint == null) {
6038                         mBackgroundTint = new TintInfo();
6039                     }
6040                     mBackgroundTint.mTintList = a.getColorStateList(
6041                             R.styleable.View_backgroundTint);
6042                     mBackgroundTint.mHasTintList = true;
6043                     break;
6044                 case R.styleable.View_backgroundTintMode:
6045                     // This will get applied later during setBackground().
6046                     if (mBackgroundTint == null) {
6047                         mBackgroundTint = new TintInfo();
6048                     }
6049                     mBackgroundTint.mBlendMode = Drawable.parseBlendMode(a.getInt(
6050                             R.styleable.View_backgroundTintMode, -1), null);
6051                     mBackgroundTint.mHasTintMode = true;
6052                     break;
6053                 case R.styleable.View_outlineProvider:
6054                     setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
6055                             PROVIDER_BACKGROUND));
6056                     break;
6057                 case R.styleable.View_foreground:
6058                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
6059                         setForeground(a.getDrawable(attr));
6060                     }
6061                     break;
6062                 case R.styleable.View_foregroundGravity:
6063                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
6064                         setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
6065                     }
6066                     break;
6067                 case R.styleable.View_foregroundTintMode:
6068                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
6069                         setForegroundTintBlendMode(
6070                                 Drawable.parseBlendMode(a.getInt(attr, -1),
6071                                         null));
6072                     }
6073                     break;
6074                 case R.styleable.View_foregroundTint:
6075                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
6076                         setForegroundTintList(a.getColorStateList(attr));
6077                     }
6078                     break;
6079                 case R.styleable.View_foregroundInsidePadding:
6080                     if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
6081                         if (mForegroundInfo == null) {
6082                             mForegroundInfo = new ForegroundInfo();
6083                         }
6084                         mForegroundInfo.mInsidePadding = a.getBoolean(attr,
6085                                 mForegroundInfo.mInsidePadding);
6086                     }
6087                     break;
6088                 case R.styleable.View_scrollIndicators:
6089                     final int scrollIndicators =
6090                             (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
6091                                     & SCROLL_INDICATORS_PFLAG3_MASK;
6092                     if (scrollIndicators != 0) {
6093                         mPrivateFlags3 |= scrollIndicators;
6094                         initializeScrollIndicators = true;
6095                     }
6096                     break;
6097                 case R.styleable.View_pointerIcon:
6098                     final int resourceId = a.getResourceId(attr, 0);
6099                     if (resourceId != 0) {
6100                         setPointerIcon(PointerIcon.load(
6101                                 context.getResources(), resourceId));
6102                     } else {
6103                         final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
6104                         if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
6105                             setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
6106                         }
6107                     }
6108                     break;
6109                 case R.styleable.View_forceHasOverlappingRendering:
6110                     if (a.peekValue(attr) != null) {
6111                         forceHasOverlappingRendering(a.getBoolean(attr, true));
6112                     }
6113                     break;
6114                 case R.styleable.View_tooltipText:
6115                     setTooltipText(a.getText(attr));
6116                     break;
6117                 case R.styleable.View_keyboardNavigationCluster:
6118                     if (a.peekValue(attr) != null) {
6119                         setKeyboardNavigationCluster(a.getBoolean(attr, true));
6120                     }
6121                     break;
6122                 case R.styleable.View_focusedByDefault:
6123                     if (a.peekValue(attr) != null) {
6124                         setFocusedByDefault(a.getBoolean(attr, true));
6125                     }
6126                     break;
6127                 case R.styleable.View_autofillHints:
6128                     if (a.peekValue(attr) != null) {
6129                         CharSequence[] rawHints = null;
6130                         String rawString = null;
6131 
6132                         if (a.getType(attr) == TypedValue.TYPE_REFERENCE) {
6133                             int resId = a.getResourceId(attr, 0);
6134 
6135                             try {
6136                                 rawHints = a.getTextArray(attr);
6137                             } catch (Resources.NotFoundException e) {
6138                                 rawString = getResources().getString(resId);
6139                             }
6140                         } else {
6141                             rawString = a.getString(attr);
6142                         }
6143 
6144                         if (rawHints == null) {
6145                             if (rawString == null) {
6146                                 throw new IllegalArgumentException(
6147                                         "Could not resolve autofillHints");
6148                             } else {
6149                                 rawHints = rawString.split(",");
6150                             }
6151                         }
6152 
6153                         String[] hints = new String[rawHints.length];
6154 
6155                         int numHints = rawHints.length;
6156                         for (int rawHintNum = 0; rawHintNum < numHints; rawHintNum++) {
6157                             hints[rawHintNum] = rawHints[rawHintNum].toString().trim();
6158                         }
6159                         setAutofillHints(hints);
6160                     }
6161                     break;
6162                 case R.styleable.View_importantForAutofill:
6163                     if (a.peekValue(attr) != null) {
6164                         setImportantForAutofill(a.getInt(attr, IMPORTANT_FOR_AUTOFILL_AUTO));
6165                     }
6166                     break;
6167                 case R.styleable.View_importantForContentCapture:
6168                     if (a.peekValue(attr) != null) {
6169                         setImportantForContentCapture(a.getInt(attr,
6170                                 IMPORTANT_FOR_CONTENT_CAPTURE_AUTO));
6171                     }
6172                     break;
6173                 case R.styleable.View_isCredential:
6174                     if (a.peekValue(attr) != null) {
6175                         setIsCredential(a.getBoolean(attr, false));
6176                     }
6177                     break;
6178                 case R.styleable.View_defaultFocusHighlightEnabled:
6179                     if (a.peekValue(attr) != null) {
6180                         setDefaultFocusHighlightEnabled(a.getBoolean(attr, true));
6181                     }
6182                     break;
6183                 case R.styleable.View_screenReaderFocusable:
6184                     if (a.peekValue(attr) != null) {
6185                         setScreenReaderFocusable(a.getBoolean(attr, false));
6186                     }
6187                     break;
6188                 case R.styleable.View_accessibilityPaneTitle:
6189                     if (a.peekValue(attr) != null) {
6190                         setAccessibilityPaneTitle(a.getString(attr));
6191                     }
6192                     break;
6193                 case R.styleable.View_outlineSpotShadowColor:
6194                     setOutlineSpotShadowColor(a.getColor(attr, Color.BLACK));
6195                     break;
6196                 case R.styleable.View_outlineAmbientShadowColor:
6197                     setOutlineAmbientShadowColor(a.getColor(attr, Color.BLACK));
6198                     break;
6199                 case com.android.internal.R.styleable.View_accessibilityHeading:
6200                     setAccessibilityHeading(a.getBoolean(attr, false));
6201                     break;
6202                 case R.styleable.View_forceDarkAllowed:
6203                     mRenderNode.setForceDarkAllowed(a.getBoolean(attr, true));
6204                     break;
6205                 case R.styleable.View_scrollCaptureHint:
6206                     setScrollCaptureHint((a.getInt(attr, SCROLL_CAPTURE_HINT_AUTO)));
6207                     break;
6208                 case R.styleable.View_clipToOutline:
6209                     setClipToOutline(a.getBoolean(attr, false));
6210                     break;
6211                 case R.styleable.View_preferKeepClear:
6212                     setPreferKeepClear(a.getBoolean(attr, false));
6213                     break;
6214                 case R.styleable.View_autoHandwritingEnabled:
6215                     setAutoHandwritingEnabled(a.getBoolean(attr, false));
6216                     break;
6217                 case R.styleable.View_handwritingBoundsOffsetLeft:
6218                     mHandwritingBoundsOffsetLeft = a.getDimension(attr, 0);
6219                     break;
6220                 case R.styleable.View_handwritingBoundsOffsetTop:
6221                     mHandwritingBoundsOffsetTop = a.getDimension(attr, 0);
6222                     break;
6223                 case R.styleable.View_handwritingBoundsOffsetRight:
6224                     mHandwritingBoundsOffsetRight = a.getDimension(attr, 0);
6225                     break;
6226                 case R.styleable.View_handwritingBoundsOffsetBottom:
6227                     mHandwritingBoundsOffsetBottom = a.getDimension(attr, 0);
6228                     break;
6229             }
6230         }
6231 
6232         setOverScrollMode(overScrollMode);
6233 
6234         // Cache start/end user padding as we cannot fully resolve padding here (we don't have yet
6235         // the resolved layout direction). Those cached values will be used later during padding
6236         // resolution.
6237         mUserPaddingStart = startPadding;
6238         mUserPaddingEnd = endPadding;
6239 
6240         if (background != null) {
6241             setBackground(background);
6242         }
6243 
6244         // setBackground above will record that padding is currently provided by the background.
6245         // If we have padding specified via xml, record that here instead and use it.
6246         mLeftPaddingDefined = leftPaddingDefined;
6247         mRightPaddingDefined = rightPaddingDefined;
6248 
6249         // Valid paddingHorizontal/paddingVertical beats leftPadding, rightPadding, topPadding,
6250         // bottomPadding, and padding set by background.  Valid padding beats everything.
6251         if (padding >= 0) {
6252             leftPadding = padding;
6253             topPadding = padding;
6254             rightPadding = padding;
6255             bottomPadding = padding;
6256             mUserPaddingLeftInitial = padding;
6257             mUserPaddingRightInitial = padding;
6258         } else {
6259             if (paddingHorizontal >= 0) {
6260                 leftPadding = paddingHorizontal;
6261                 rightPadding = paddingHorizontal;
6262                 mUserPaddingLeftInitial = paddingHorizontal;
6263                 mUserPaddingRightInitial = paddingHorizontal;
6264             }
6265             if (paddingVertical >= 0) {
6266                 topPadding = paddingVertical;
6267                 bottomPadding = paddingVertical;
6268             }
6269         }
6270 
6271         if (isRtlCompatibilityMode()) {
6272             // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
6273             // left / right padding are used if defined (meaning here nothing to do). If they are not
6274             // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
6275             // start / end and resolve them as left / right (layout direction is not taken into account).
6276             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
6277             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
6278             // defined.
6279             if (!mLeftPaddingDefined && startPaddingDefined) {
6280                 leftPadding = startPadding;
6281             }
6282             mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
6283             if (!mRightPaddingDefined && endPaddingDefined) {
6284                 rightPadding = endPadding;
6285             }
6286             mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
6287         } else {
6288             // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
6289             // values defined. Otherwise, left /right values are used.
6290             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
6291             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
6292             // defined.
6293             final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
6294 
6295             if (mLeftPaddingDefined && !hasRelativePadding) {
6296                 mUserPaddingLeftInitial = leftPadding;
6297             }
6298             if (mRightPaddingDefined && !hasRelativePadding) {
6299                 mUserPaddingRightInitial = rightPadding;
6300             }
6301         }
6302 
6303         // mPaddingTop and mPaddingBottom may have been set by setBackground(Drawable) so must pass
6304         // them on if topPadding or bottomPadding are not valid.
6305         internalSetPadding(
6306                 mUserPaddingLeftInitial,
6307                 topPadding >= 0 ? topPadding : mPaddingTop,
6308                 mUserPaddingRightInitial,
6309                 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
6310 
6311         if (viewFlagMasks != 0) {
6312             setFlags(viewFlagValues, viewFlagMasks);
6313         }
6314 
6315         if (initializeScrollbars) {
6316             initializeScrollbarsInternal(a);
6317         }
6318 
6319         if (initializeScrollIndicators) {
6320             initializeScrollIndicatorsInternal();
6321         }
6322 
6323         a.recycle();
6324 
6325         // Needs to be called after mViewFlags is set
6326         if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
6327             recomputePadding();
6328         }
6329 
6330         if (x != 0 || y != 0) {
6331             scrollTo(x, y);
6332         }
6333 
6334         if (transformSet) {
6335             setTranslationX(tx);
6336             setTranslationY(ty);
6337             setTranslationZ(tz);
6338             setElevation(elevation);
6339             setRotation(rotation);
6340             setRotationX(rotationX);
6341             setRotationY(rotationY);
6342             setScaleX(sx);
6343             setScaleY(sy);
6344         }
6345 
6346         if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
6347             setScrollContainer(true);
6348         }
6349 
6350         computeOpaqueFlags();
6351     }
6352 
6353     /**
6354      * Returns the ordered list of resource ID that are considered when resolving attribute values
6355      * for this {@link View}. The list will include layout resource ID if the View is inflated from
6356      * XML. It will also include a set of explicit styles if specified in XML using
6357      * {@code style="..."}. Finally, it will include the default styles resolved from the theme.
6358      *
6359      * <p>
6360      * <b>Note:</b> this method will only return actual values if the view attribute debugging
6361      * is enabled in Android developer options.
6362      *
6363      * @param attribute Attribute resource ID for which the resolution stack should be returned.
6364      * @return ordered list of resource ID that are considered when resolving attribute values for
6365      * this {@link View}.
6366      */
6367     @NonNull
6368     public int[] getAttributeResolutionStack(@AttrRes int attribute) {
6369         if (!sDebugViewAttributes
6370                 || mAttributeResolutionStacks == null
6371                 || mAttributeResolutionStacks.get(attribute) == null) {
6372             return new int[0];
6373         }
6374         int[] attributeResolutionStack = mAttributeResolutionStacks.get(attribute);
6375         int stackSize = attributeResolutionStack.length;
6376         if (mSourceLayoutId != ID_NULL) {
6377             stackSize++;
6378         }
6379 
6380         int currentIndex = 0;
6381         int[] stack = new int[stackSize];
6382 
6383         if (mSourceLayoutId != ID_NULL) {
6384             stack[currentIndex] = mSourceLayoutId;
6385             currentIndex++;
6386         }
6387         for (int i = 0; i < attributeResolutionStack.length; i++) {
6388             stack[currentIndex] = attributeResolutionStack[i];
6389             currentIndex++;
6390         }
6391         return stack;
6392     }
6393 
6394     /**
6395      * Returns the mapping of attribute resource ID to source resource ID where the attribute value
6396      * was set. Source resource ID can either be a layout resource ID, if the value was set in XML
6397      * within the View tag, or a style resource ID, if the attribute was set in a style. The source
6398      * resource value will be one of the resource IDs from {@link #getAttributeSourceResourceMap()}.
6399      *
6400      * <p>
6401      * <b>Note:</b> this method will only return actual values if the view attribute debugging
6402      * is enabled in Android developer options.
6403      *
6404      * @return mapping of attribute resource ID to source resource ID where the attribute value
6405      * was set.
6406      */
6407     @NonNull
6408     @SuppressWarnings("AndroidFrameworkEfficientCollections")
6409     public Map<Integer, Integer> getAttributeSourceResourceMap() {
6410         HashMap<Integer, Integer> map = new HashMap<>();
6411         if (!sDebugViewAttributes || mAttributeSourceResId == null) {
6412             return map;
6413         }
6414         for (int i = 0; i < mAttributeSourceResId.size(); i++) {
6415             map.put(mAttributeSourceResId.keyAt(i), mAttributeSourceResId.valueAt(i));
6416         }
6417         return map;
6418     }
6419 
6420     /**
6421      * Returns the resource ID for the style specified using {@code style="..."} in the
6422      * {@link AttributeSet}'s backing XML element or {@link Resources#ID_NULL} otherwise if not
6423      * specified or otherwise not applicable.
6424      * <p>
6425      * Each {@link View} can have an explicit style specified in the layout file.
6426      * This style is used first during the {@link View} attribute resolution, then if an attribute
6427      * is not defined there the resource system looks at default style and theme as fallbacks.
6428      *
6429      * <p>
6430      * <b>Note:</b> this method will only return actual values if the view attribute debugging
6431      * is enabled in Android developer options.
6432      *
6433      * @return The resource ID for the style specified using {@code style="..."} in the
6434      *      {@link AttributeSet}'s backing XML element or {@link Resources#ID_NULL} otherwise
6435      *      if not specified or otherwise not applicable.
6436      */
6437     @StyleRes
6438     public int getExplicitStyle() {
6439         if (!sDebugViewAttributes) {
6440             return ID_NULL;
6441         }
6442         return mExplicitStyle;
6443     }
6444 
6445     /**
6446      * An implementation of OnClickListener that attempts to lazily load a
6447      * named click handling method from a parent or ancestor context.
6448      */
6449     private static class DeclaredOnClickListener implements OnClickListener {
6450         private final View mHostView;
6451         private final String mMethodName;
6452 
6453         private Method mResolvedMethod;
6454         private Context mResolvedContext;
6455 
6456         public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
6457             mHostView = hostView;
6458             mMethodName = methodName;
6459         }
6460 
6461         @Override
6462         public void onClick(@NonNull View v) {
6463             if (mResolvedMethod == null) {
6464                 resolveMethod(mHostView.getContext(), mMethodName);
6465             }
6466 
6467             try {
6468                 mResolvedMethod.invoke(mResolvedContext, v);
6469             } catch (IllegalAccessException e) {
6470                 throw new IllegalStateException(
6471                         "Could not execute non-public method for android:onClick", e);
6472             } catch (InvocationTargetException e) {
6473                 throw new IllegalStateException(
6474                         "Could not execute method for android:onClick", e);
6475             }
6476         }
6477 
6478         @NonNull
6479         private void resolveMethod(@Nullable Context context, @NonNull String name) {
6480             while (context != null) {
6481                 try {
6482                     if (!context.isRestricted()) {
6483                         final Method method = context.getClass().getMethod(mMethodName, View.class);
6484                         if (method != null) {
6485                             mResolvedMethod = method;
6486                             mResolvedContext = context;
6487                             return;
6488                         }
6489                     }
6490                 } catch (NoSuchMethodException e) {
6491                     // Failed to find method, keep searching up the hierarchy.
6492                 }
6493 
6494                 if (context instanceof ContextWrapper) {
6495                     context = ((ContextWrapper) context).getBaseContext();
6496                 } else {
6497                     // Can't search up the hierarchy, null out and fail.
6498                     context = null;
6499                 }
6500             }
6501 
6502             final int id = mHostView.getId();
6503             final String idText = id == NO_ID ? "" : " with id '"
6504                     + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
6505             throw new IllegalStateException("Could not find method " + mMethodName
6506                     + "(View) in a parent or ancestor Context for android:onClick "
6507                     + "attribute defined on view " + mHostView.getClass() + idText);
6508         }
6509     }
6510 
6511     /**
6512      * Non-public constructor for use in testing
6513      */
6514     @UnsupportedAppUsage
6515     View() {
6516         mResources = null;
6517         mRenderNode = RenderNode.create(getClass().getName(), new ViewAnimationHostBridge(this));
6518     }
6519 
6520     /**
6521      * Returns {@code true} when the View is attached and the system developer setting to show
6522      * the layout bounds is enabled or {@code false} otherwise.
6523      */
6524     public final boolean isShowingLayoutBounds() {
6525         return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
6526     }
6527 
6528     /**
6529      * Used to test isShowingLayoutBounds(). This sets the local value used
6530      * by that function. This method does nothing if the layout isn't attached.
6531      *
6532      * @hide
6533      */
6534     @TestApi
6535     public final void setShowingLayoutBounds(boolean debugLayout) {
6536         if (mAttachInfo != null) {
6537             mAttachInfo.mDebugLayout = debugLayout;
6538         }
6539     }
6540 
6541     private static SparseArray<String> getAttributeMap() {
6542         if (mAttributeMap == null) {
6543             mAttributeMap = new SparseArray<>();
6544         }
6545         return mAttributeMap;
6546     }
6547 
6548     private void retrieveExplicitStyle(@NonNull Resources.Theme theme,
6549             @Nullable AttributeSet attrs) {
6550         if (!sDebugViewAttributes) {
6551             return;
6552         }
6553         mExplicitStyle = theme.getExplicitStyle(attrs);
6554     }
6555 
6556     /**
6557      * Stores debugging information about attributes. This should be called in a constructor by
6558      * every custom {@link View} that uses a custom styleable. If the custom view does not call it,
6559      * then the custom attributes used by this view will not be visible in layout inspection tools.
6560      *
6561      *  @param context Context under which this view is created.
6562      * @param styleable A reference to styleable array R.styleable.Foo
6563      * @param attrs AttributeSet used to construct this view.
6564      * @param t Resolved {@link TypedArray} returned by a call to
6565      *        {@link Resources#obtainAttributes(AttributeSet, int[])}.
6566      * @param defStyleAttr Default style attribute passed into the view constructor.
6567      * @param defStyleRes Default style resource passed into the view constructor.
6568      */
6569     public final void saveAttributeDataForStyleable(@NonNull Context context,
6570             @NonNull int[] styleable, @Nullable AttributeSet attrs, @NonNull TypedArray t,
6571             int defStyleAttr, int defStyleRes) {
6572         if (!sDebugViewAttributes) {
6573             return;
6574         }
6575 
6576         int[] attributeResolutionStack = context.getTheme().getAttributeResolutionStack(
6577                 defStyleAttr, defStyleRes, mExplicitStyle);
6578 
6579         if (mAttributeResolutionStacks == null) {
6580             mAttributeResolutionStacks = new SparseArray<>();
6581         }
6582 
6583         if (mAttributeSourceResId == null) {
6584             mAttributeSourceResId = new SparseIntArray();
6585         }
6586 
6587         final int indexCount = t.getIndexCount();
6588         for (int j = 0; j < indexCount; ++j) {
6589             final int index = t.getIndex(j);
6590             mAttributeSourceResId.append(styleable[index], t.getSourceResourceId(index, 0));
6591             mAttributeResolutionStacks.append(styleable[index], attributeResolutionStack);
6592         }
6593     }
6594 
6595     private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
6596         final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
6597         final int indexCount = t.getIndexCount();
6598         final String[] attributes = new String[(attrsCount + indexCount) * 2];
6599 
6600         int i = 0;
6601 
6602         // Store raw XML attributes.
6603         for (int j = 0; j < attrsCount; ++j) {
6604             attributes[i] = attrs.getAttributeName(j);
6605             attributes[i + 1] = attrs.getAttributeValue(j);
6606             i += 2;
6607         }
6608 
6609         // Store resolved styleable attributes.
6610         final Resources res = t.getResources();
6611         final SparseArray<String> attributeMap = getAttributeMap();
6612         for (int j = 0; j < indexCount; ++j) {
6613             final int index = t.getIndex(j);
6614             if (!t.hasValueOrEmpty(index)) {
6615                 // Value is undefined. Skip it.
6616                 continue;
6617             }
6618 
6619             final int resourceId = t.getResourceId(index, 0);
6620             if (resourceId == 0) {
6621                 // Value is not a reference. Skip it.
6622                 continue;
6623             }
6624 
6625             String resourceName = attributeMap.get(resourceId);
6626             if (resourceName == null) {
6627                 try {
6628                     resourceName = res.getResourceName(resourceId);
6629                 } catch (Resources.NotFoundException e) {
6630                     resourceName = "0x" + Integer.toHexString(resourceId);
6631                 }
6632                 attributeMap.put(resourceId, resourceName);
6633             }
6634 
6635             attributes[i] = resourceName;
6636             attributes[i + 1] = t.getString(index);
6637             i += 2;
6638         }
6639 
6640         // Trim to fit contents.
6641         final String[] trimmed = new String[i];
6642         System.arraycopy(attributes, 0, trimmed, 0, i);
6643         mAttributes = trimmed;
6644     }
6645 
6646     @Override
6647     public String toString() {
6648         StringBuilder out = new StringBuilder(256);
6649         out.append(getClass().getName());
6650         out.append('{');
6651         out.append(Integer.toHexString(System.identityHashCode(this)));
6652         out.append(' ');
6653         switch (mViewFlags&VISIBILITY_MASK) {
6654             case VISIBLE: out.append('V'); break;
6655             case INVISIBLE: out.append('I'); break;
6656             case GONE: out.append('G'); break;
6657             default: out.append('.'); break;
6658         }
6659         out.append((mViewFlags & FOCUSABLE) == FOCUSABLE ? 'F' : '.');
6660         out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
6661         out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
6662         out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
6663         out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
6664         out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
6665         out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
6666         out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
6667         out.append(' ');
6668         out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
6669         out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
6670         out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
6671         if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
6672             out.append('p');
6673         } else {
6674             out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
6675         }
6676         out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
6677         out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
6678         out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
6679         out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
6680         out.append(' ');
6681         out.append(mLeft);
6682         out.append(',');
6683         out.append(mTop);
6684         out.append('-');
6685         out.append(mRight);
6686         out.append(',');
6687         out.append(mBottom);
6688         appendId(out);
6689         if (mAutofillId != null) {
6690             out.append(" aid="); out.append(mAutofillId);
6691         }
6692         out.append("}");
6693         return out.toString();
6694     }
6695 
6696     void appendId(StringBuilder out) {
6697         final int id = getId();
6698         if (id != NO_ID) {
6699             out.append(" #");
6700             out.append(Integer.toHexString(id));
6701             final Resources r = mResources;
6702             if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
6703                 try {
6704                     String pkgname;
6705                     switch (id&0xff000000) {
6706                         case 0x7f000000:
6707                             pkgname="app";
6708                             break;
6709                         case 0x01000000:
6710                             pkgname="android";
6711                             break;
6712                         default:
6713                             pkgname = r.getResourcePackageName(id);
6714                             break;
6715                     }
6716                     String typename = r.getResourceTypeName(id);
6717                     String entryname = r.getResourceEntryName(id);
6718                     out.append(" ");
6719                     out.append(pkgname);
6720                     out.append(":");
6721                     out.append(typename);
6722                     out.append("/");
6723                     out.append(entryname);
6724                 } catch (Resources.NotFoundException e) {
6725                 }
6726             }
6727         }
6728     }
6729 
6730     /**
6731      * <p>
6732      * Initializes the fading edges from a given set of styled attributes. This
6733      * method should be called by subclasses that need fading edges and when an
6734      * instance of these subclasses is created programmatically rather than
6735      * being inflated from XML. This method is automatically called when the XML
6736      * is inflated.
6737      * </p>
6738      *
6739      * @param a the styled attributes set to initialize the fading edges from
6740      *
6741      * @removed
6742      */
6743     protected void initializeFadingEdge(TypedArray a) {
6744         // This method probably shouldn't have been included in the SDK to begin with.
6745         // It relies on 'a' having been initialized using an attribute filter array that is
6746         // not publicly available to the SDK. The old method has been renamed
6747         // to initializeFadingEdgeInternal and hidden for framework use only;
6748         // this one initializes using defaults to make it safe to call for apps.
6749 
6750         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
6751 
6752         initializeFadingEdgeInternal(arr);
6753 
6754         arr.recycle();
6755     }
6756 
6757     /**
6758      * <p>
6759      * Initializes the fading edges from a given set of styled attributes. This
6760      * method should be called by subclasses that need fading edges and when an
6761      * instance of these subclasses is created programmatically rather than
6762      * being inflated from XML. This method is automatically called when the XML
6763      * is inflated.
6764      * </p>
6765      *
6766      * @param a the styled attributes set to initialize the fading edges from
6767      * @hide This is the real method; the public one is shimmed to be safe to call from apps.
6768      */
6769     protected void initializeFadingEdgeInternal(TypedArray a) {
6770         initScrollCache();
6771 
6772         mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
6773                 R.styleable.View_fadingEdgeLength,
6774                 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
6775     }
6776 
6777     /**
6778      * Returns the size of the vertical faded edges used to indicate that more
6779      * content in this view is visible.
6780      *
6781      * @return The size in pixels of the vertical faded edge or 0 if vertical
6782      *         faded edges are not enabled for this view.
6783      * @attr ref android.R.styleable#View_fadingEdgeLength
6784      */
6785     public int getVerticalFadingEdgeLength() {
6786         if (isVerticalFadingEdgeEnabled()) {
6787             ScrollabilityCache cache = mScrollCache;
6788             if (cache != null) {
6789                 return cache.fadingEdgeLength;
6790             }
6791         }
6792         return 0;
6793     }
6794 
6795     /**
6796      * Set the size of the faded edge used to indicate that more content in this
6797      * view is available.  Will not change whether the fading edge is enabled; use
6798      * {@link #setVerticalFadingEdgeEnabled(boolean)} or
6799      * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
6800      * for the vertical or horizontal fading edges.
6801      *
6802      * @param length The size in pixels of the faded edge used to indicate that more
6803      *        content in this view is visible.
6804      */
6805     public void setFadingEdgeLength(int length) {
6806         initScrollCache();
6807         mScrollCache.fadingEdgeLength = length;
6808     }
6809 
6810     /**
6811      * Returns the size of the horizontal faded edges used to indicate that more
6812      * content in this view is visible.
6813      *
6814      * @return The size in pixels of the horizontal faded edge or 0 if horizontal
6815      *         faded edges are not enabled for this view.
6816      * @attr ref android.R.styleable#View_fadingEdgeLength
6817      */
6818     public int getHorizontalFadingEdgeLength() {
6819         if (isHorizontalFadingEdgeEnabled()) {
6820             ScrollabilityCache cache = mScrollCache;
6821             if (cache != null) {
6822                 return cache.fadingEdgeLength;
6823             }
6824         }
6825         return 0;
6826     }
6827 
6828     /**
6829      * Returns the width of the vertical scrollbar.
6830      *
6831      * @return The width in pixels of the vertical scrollbar or 0 if there
6832      *         is no vertical scrollbar.
6833      */
6834     public int getVerticalScrollbarWidth() {
6835         ScrollabilityCache cache = mScrollCache;
6836         if (cache != null) {
6837             ScrollBarDrawable scrollBar = cache.scrollBar;
6838             if (scrollBar != null) {
6839                 int size = scrollBar.getSize(true);
6840                 if (size <= 0) {
6841                     size = cache.scrollBarSize;
6842                 }
6843                 return size;
6844             }
6845             return 0;
6846         }
6847         return 0;
6848     }
6849 
6850     /**
6851      * Returns the height of the horizontal scrollbar.
6852      *
6853      * @return The height in pixels of the horizontal scrollbar or 0 if
6854      *         there is no horizontal scrollbar.
6855      */
6856     protected int getHorizontalScrollbarHeight() {
6857         ScrollabilityCache cache = mScrollCache;
6858         if (cache != null) {
6859             ScrollBarDrawable scrollBar = cache.scrollBar;
6860             if (scrollBar != null) {
6861                 int size = scrollBar.getSize(false);
6862                 if (size <= 0) {
6863                     size = cache.scrollBarSize;
6864                 }
6865                 return size;
6866             }
6867             return 0;
6868         }
6869         return 0;
6870     }
6871 
6872     /**
6873      * <p>
6874      * Initializes the scrollbars from a given set of styled attributes. This
6875      * method should be called by subclasses that need scrollbars and when an
6876      * instance of these subclasses is created programmatically rather than
6877      * being inflated from XML. This method is automatically called when the XML
6878      * is inflated.
6879      * </p>
6880      *
6881      * @param a the styled attributes set to initialize the scrollbars from
6882      *
6883      * @removed
6884      */
6885     protected void initializeScrollbars(TypedArray a) {
6886         // It's not safe to use this method from apps. The parameter 'a' must have been obtained
6887         // using the View filter array which is not available to the SDK. As such, internal
6888         // framework usage now uses initializeScrollbarsInternal and we grab a default
6889         // TypedArray with the right filter instead here.
6890         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
6891 
6892         initializeScrollbarsInternal(arr);
6893 
6894         // We ignored the method parameter. Recycle the one we actually did use.
6895         arr.recycle();
6896     }
6897 
6898     private void initializeScrollBarDrawable() {
6899         initScrollCache();
6900 
6901         if (mScrollCache.scrollBar == null) {
6902             mScrollCache.scrollBar = new ScrollBarDrawable();
6903             mScrollCache.scrollBar.setState(getDrawableState());
6904             mScrollCache.scrollBar.setCallback(this);
6905         }
6906     }
6907 
6908     /**
6909      * <p>
6910      * Initializes the scrollbars from a given set of styled attributes. This
6911      * method should be called by subclasses that need scrollbars and when an
6912      * instance of these subclasses is created programmatically rather than
6913      * being inflated from XML. This method is automatically called when the XML
6914      * is inflated.
6915      * </p>
6916      *
6917      * @param a the styled attributes set to initialize the scrollbars from
6918      * @hide
6919      */
6920     @UnsupportedAppUsage
6921     protected void initializeScrollbarsInternal(TypedArray a) {
6922         initScrollCache();
6923 
6924         final ScrollabilityCache scrollabilityCache = mScrollCache;
6925 
6926         if (scrollabilityCache.scrollBar == null) {
6927             scrollabilityCache.scrollBar = new ScrollBarDrawable();
6928             scrollabilityCache.scrollBar.setState(getDrawableState());
6929             scrollabilityCache.scrollBar.setCallback(this);
6930         }
6931 
6932         final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
6933 
6934         if (!fadeScrollbars) {
6935             scrollabilityCache.state = ScrollabilityCache.ON;
6936         }
6937         scrollabilityCache.fadeScrollBars = fadeScrollbars;
6938 
6939 
6940         scrollabilityCache.scrollBarFadeDuration = a.getInt(
6941                 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
6942                         .getScrollBarFadeDuration());
6943         scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
6944                 R.styleable.View_scrollbarDefaultDelayBeforeFade,
6945                 ViewConfiguration.getScrollDefaultDelay());
6946 
6947 
6948         scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
6949                 com.android.internal.R.styleable.View_scrollbarSize,
6950                 ViewConfiguration.get(mContext).getScaledScrollBarSize());
6951 
6952         Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
6953         scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
6954 
6955         Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
6956         if (thumb != null) {
6957             scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
6958         }
6959 
6960         boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
6961                 false);
6962         if (alwaysDraw) {
6963             scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
6964         }
6965 
6966         track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
6967         scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
6968 
6969         thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
6970         if (thumb != null) {
6971             scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
6972         }
6973 
6974         alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
6975                 false);
6976         if (alwaysDraw) {
6977             scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
6978         }
6979 
6980         // Apply layout direction to the new Drawables if needed
6981         final int layoutDirection = getLayoutDirection();
6982         if (track != null) {
6983             track.setLayoutDirection(layoutDirection);
6984         }
6985         if (thumb != null) {
6986             thumb.setLayoutDirection(layoutDirection);
6987         }
6988 
6989         // Re-apply user/background padding so that scrollbar(s) get added
6990         resolvePadding();
6991     }
6992 
6993     /**
6994      * Defines the vertical scrollbar thumb drawable
6995      * @attr ref android.R.styleable#View_scrollbarThumbVertical
6996      *
6997      * @see #awakenScrollBars(int)
6998      * @see #isVerticalScrollBarEnabled()
6999      * @see #setVerticalScrollBarEnabled(boolean)
7000      */
7001     public void setVerticalScrollbarThumbDrawable(@Nullable Drawable drawable) {
7002         initializeScrollBarDrawable();
7003         mScrollCache.scrollBar.setVerticalThumbDrawable(drawable);
7004     }
7005 
7006     /**
7007      * Defines the vertical scrollbar track drawable
7008      * @attr ref android.R.styleable#View_scrollbarTrackVertical
7009      *
7010      * @see #awakenScrollBars(int)
7011      * @see #isVerticalScrollBarEnabled()
7012      * @see #setVerticalScrollBarEnabled(boolean)
7013      */
7014     public void setVerticalScrollbarTrackDrawable(@Nullable Drawable drawable) {
7015         initializeScrollBarDrawable();
7016         mScrollCache.scrollBar.setVerticalTrackDrawable(drawable);
7017     }
7018 
7019     /**
7020      * Defines the horizontal thumb drawable
7021      * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
7022      *
7023      * @see #awakenScrollBars(int)
7024      * @see #isHorizontalScrollBarEnabled()
7025      * @see #setHorizontalScrollBarEnabled(boolean)
7026      */
7027     public void setHorizontalScrollbarThumbDrawable(@Nullable Drawable drawable) {
7028         initializeScrollBarDrawable();
7029         mScrollCache.scrollBar.setHorizontalThumbDrawable(drawable);
7030     }
7031 
7032     /**
7033      * Defines the horizontal track drawable
7034      * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
7035      *
7036      * @see #awakenScrollBars(int)
7037      * @see #isHorizontalScrollBarEnabled()
7038      * @see #setHorizontalScrollBarEnabled(boolean)
7039      */
7040     public void setHorizontalScrollbarTrackDrawable(@Nullable Drawable drawable) {
7041         initializeScrollBarDrawable();
7042         mScrollCache.scrollBar.setHorizontalTrackDrawable(drawable);
7043     }
7044 
7045     /**
7046      * Returns the currently configured Drawable for the thumb of the vertical scroll bar if it
7047      * exists, null otherwise.
7048      *
7049      * @see #awakenScrollBars(int)
7050      * @see #isVerticalScrollBarEnabled()
7051      * @see #setVerticalScrollBarEnabled(boolean)
7052      */
7053     public @Nullable Drawable getVerticalScrollbarThumbDrawable() {
7054         return mScrollCache != null ? mScrollCache.scrollBar.getVerticalThumbDrawable() : null;
7055     }
7056 
7057     /**
7058      * Returns the currently configured Drawable for the track of the vertical scroll bar if it
7059      * exists, null otherwise.
7060      *
7061      * @see #awakenScrollBars(int)
7062      * @see #isVerticalScrollBarEnabled()
7063      * @see #setVerticalScrollBarEnabled(boolean)
7064      */
7065     public @Nullable Drawable getVerticalScrollbarTrackDrawable() {
7066         return mScrollCache != null ? mScrollCache.scrollBar.getVerticalTrackDrawable() : null;
7067     }
7068 
7069     /**
7070      * Returns the currently configured Drawable for the thumb of the horizontal scroll bar if it
7071      * exists, null otherwise.
7072      *
7073      * @see #awakenScrollBars(int)
7074      * @see #isHorizontalScrollBarEnabled()
7075      * @see #setHorizontalScrollBarEnabled(boolean)
7076      */
7077     public @Nullable Drawable getHorizontalScrollbarThumbDrawable() {
7078         return mScrollCache != null ? mScrollCache.scrollBar.getHorizontalThumbDrawable() : null;
7079     }
7080 
7081     /**
7082      * Returns the currently configured Drawable for the track of the horizontal scroll bar if it
7083      * exists, null otherwise.
7084      *
7085      * @see #awakenScrollBars(int)
7086      * @see #isHorizontalScrollBarEnabled()
7087      * @see #setHorizontalScrollBarEnabled(boolean)
7088      */
7089     public @Nullable Drawable getHorizontalScrollbarTrackDrawable() {
7090         return mScrollCache != null ? mScrollCache.scrollBar.getHorizontalTrackDrawable() : null;
7091     }
7092 
7093     private void initializeScrollIndicatorsInternal() {
7094         // Some day maybe we'll break this into top/left/start/etc. and let the
7095         // client control it. Until then, you can have any scroll indicator you
7096         // want as long as it's a 1dp foreground-colored rectangle.
7097         if (mScrollIndicatorDrawable == null) {
7098             mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
7099         }
7100     }
7101 
7102     /**
7103      * <p>
7104      * Initalizes the scrollability cache if necessary.
7105      * </p>
7106      */
7107     private void initScrollCache() {
7108         if (mScrollCache == null) {
7109             mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
7110         }
7111     }
7112 
7113     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
7114     private ScrollabilityCache getScrollCache() {
7115         initScrollCache();
7116         return mScrollCache;
7117     }
7118 
7119     /**
7120      * Set the position of the vertical scroll bar. Should be one of
7121      * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
7122      * {@link #SCROLLBAR_POSITION_RIGHT}.
7123      *
7124      * @param position Where the vertical scroll bar should be positioned.
7125      */
7126     public void setVerticalScrollbarPosition(int position) {
7127         if (mVerticalScrollbarPosition != position) {
7128             mVerticalScrollbarPosition = position;
7129             computeOpaqueFlags();
7130             resolvePadding();
7131         }
7132     }
7133 
7134     /**
7135      * @return The position where the vertical scroll bar will show, if applicable.
7136      * @see #setVerticalScrollbarPosition(int)
7137      */
7138     public int getVerticalScrollbarPosition() {
7139         return mVerticalScrollbarPosition;
7140     }
7141 
7142     boolean isOnScrollbar(float x, float y) {
7143         if (mScrollCache == null) {
7144             return false;
7145         }
7146         x += getScrollX();
7147         y += getScrollY();
7148         final boolean canScrollVertically =
7149                 computeVerticalScrollRange() > computeVerticalScrollExtent();
7150         if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden() && canScrollVertically) {
7151             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
7152             getVerticalScrollBarBounds(null, touchBounds);
7153             if (touchBounds.contains((int) x, (int) y)) {
7154                 return true;
7155             }
7156         }
7157         final boolean canScrollHorizontally =
7158                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
7159         if (isHorizontalScrollBarEnabled() && canScrollHorizontally) {
7160             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
7161             getHorizontalScrollBarBounds(null, touchBounds);
7162             if (touchBounds.contains((int) x, (int) y)) {
7163                 return true;
7164             }
7165         }
7166         return false;
7167     }
7168 
7169     @UnsupportedAppUsage
7170     boolean isOnScrollbarThumb(float x, float y) {
7171         return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
7172     }
7173 
7174     private boolean isOnVerticalScrollbarThumb(float x, float y) {
7175         if (mScrollCache == null || !isVerticalScrollBarEnabled() || isVerticalScrollBarHidden()) {
7176             return false;
7177         }
7178         final int range = computeVerticalScrollRange();
7179         final int extent = computeVerticalScrollExtent();
7180         if (range > extent) {
7181             x += getScrollX();
7182             y += getScrollY();
7183             final Rect bounds = mScrollCache.mScrollBarBounds;
7184             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
7185             getVerticalScrollBarBounds(bounds, touchBounds);
7186             final int offset = computeVerticalScrollOffset();
7187             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
7188                     extent, range);
7189             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
7190                     extent, range, offset);
7191             final int thumbTop = bounds.top + thumbOffset;
7192             final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
7193             if (x >= touchBounds.left && x <= touchBounds.right
7194                     && y >= thumbTop - adjust && y <= thumbTop + thumbLength + adjust) {
7195                 return true;
7196             }
7197         }
7198         return false;
7199     }
7200 
7201     private boolean isOnHorizontalScrollbarThumb(float x, float y) {
7202         if (mScrollCache == null || !isHorizontalScrollBarEnabled()) {
7203             return false;
7204         }
7205         final int range = computeHorizontalScrollRange();
7206         final int extent = computeHorizontalScrollExtent();
7207         if (range > extent) {
7208             x += getScrollX();
7209             y += getScrollY();
7210             final Rect bounds = mScrollCache.mScrollBarBounds;
7211             final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
7212             getHorizontalScrollBarBounds(bounds, touchBounds);
7213             final int offset = computeHorizontalScrollOffset();
7214 
7215             final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
7216                     extent, range);
7217             final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
7218                     extent, range, offset);
7219             final int thumbLeft = bounds.left + thumbOffset;
7220             final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
7221             if (x >= thumbLeft - adjust && x <= thumbLeft + thumbLength + adjust
7222                     && y >= touchBounds.top && y <= touchBounds.bottom) {
7223                 return true;
7224             }
7225         }
7226         return false;
7227     }
7228 
7229     @UnsupportedAppUsage
7230     boolean isDraggingScrollBar() {
7231         return mScrollCache != null
7232                 && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
7233     }
7234 
7235     /**
7236      * Sets the state of all scroll indicators.
7237      * <p>
7238      * See {@link #setScrollIndicators(int, int)} for usage information.
7239      *
7240      * @param indicators a bitmask of indicators that should be enabled, or
7241      *                   {@code 0} to disable all indicators
7242      * @see #setScrollIndicators(int, int)
7243      * @see #getScrollIndicators()
7244      * @attr ref android.R.styleable#View_scrollIndicators
7245      */
7246     @RemotableViewMethod
7247     public void setScrollIndicators(@ScrollIndicators int indicators) {
7248         setScrollIndicators(indicators,
7249                 SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
7250     }
7251 
7252     /**
7253      * Sets the state of the scroll indicators specified by the mask. To change
7254      * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
7255      * <p>
7256      * When a scroll indicator is enabled, it will be displayed if the view
7257      * can scroll in the direction of the indicator.
7258      * <p>
7259      * Multiple indicator types may be enabled or disabled by passing the
7260      * logical OR of the desired types. If multiple types are specified, they
7261      * will all be set to the same enabled state.
7262      * <p>
7263      * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
7264      *
7265      * @param indicators the indicator direction, or the logical OR of multiple
7266      *             indicator directions. One or more of:
7267      *             <ul>
7268      *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
7269      *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
7270      *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
7271      *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
7272      *               <li>{@link #SCROLL_INDICATOR_START}</li>
7273      *               <li>{@link #SCROLL_INDICATOR_END}</li>
7274      *             </ul>
7275      * @see #setScrollIndicators(int)
7276      * @see #getScrollIndicators()
7277      * @attr ref android.R.styleable#View_scrollIndicators
7278      */
7279     public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
7280         // Shift and sanitize mask.
7281         mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
7282         mask &= SCROLL_INDICATORS_PFLAG3_MASK;
7283 
7284         // Shift and mask indicators.
7285         indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
7286         indicators &= mask;
7287 
7288         // Merge with non-masked flags.
7289         final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
7290 
7291         if (mPrivateFlags3 != updatedFlags) {
7292             mPrivateFlags3 = updatedFlags;
7293 
7294             if (indicators != 0) {
7295                 initializeScrollIndicatorsInternal();
7296             }
7297             invalidate();
7298         }
7299     }
7300 
7301     /**
7302      * Returns a bitmask representing the enabled scroll indicators.
7303      * <p>
7304      * For example, if the top and left scroll indicators are enabled and all
7305      * other indicators are disabled, the return value will be
7306      * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
7307      * <p>
7308      * To check whether the bottom scroll indicator is enabled, use the value
7309      * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
7310      *
7311      * @return a bitmask representing the enabled scroll indicators
7312      */
7313     @InspectableProperty(flagMapping = {
7314             @FlagEntry(target = SCROLL_INDICATORS_NONE, mask = 0xffff_ffff, name = "none"),
7315             @FlagEntry(target = SCROLL_INDICATOR_TOP, name = "top"),
7316             @FlagEntry(target = SCROLL_INDICATOR_BOTTOM, name = "bottom"),
7317             @FlagEntry(target = SCROLL_INDICATOR_LEFT, name = "left"),
7318             @FlagEntry(target = SCROLL_INDICATOR_RIGHT, name = "right"),
7319             @FlagEntry(target = SCROLL_INDICATOR_START, name = "start"),
7320             @FlagEntry(target = SCROLL_INDICATOR_END, name = "end")
7321     })
7322     @ScrollIndicators
7323     public int getScrollIndicators() {
7324         return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
7325                 >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
7326     }
7327 
7328     @UnsupportedAppUsage
7329     ListenerInfo getListenerInfo() {
7330         if (mListenerInfo != null) {
7331             return mListenerInfo;
7332         }
7333         mListenerInfo = new ListenerInfo();
7334         return mListenerInfo;
7335     }
7336 
7337     /**
7338      * Register a callback to be invoked when the scroll X or Y positions of
7339      * this view change.
7340      * <p>
7341      * <b>Note:</b> Some views handle scrolling independently from View and may
7342      * have their own separate listeners for scroll-type events. For example,
7343      * {@link android.widget.ListView ListView} allows clients to register an
7344      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
7345      * to listen for changes in list scroll position.
7346      *
7347      * @param l The listener to notify when the scroll X or Y position changes.
7348      * @see android.view.View#getScrollX()
7349      * @see android.view.View#getScrollY()
7350      */
7351     public void setOnScrollChangeListener(OnScrollChangeListener l) {
7352         getListenerInfo().mOnScrollChangeListener = l;
7353     }
7354 
7355     /**
7356      * Register a callback to be invoked when focus of this view changed.
7357      *
7358      * @param l The callback that will run.
7359      */
7360     public void setOnFocusChangeListener(OnFocusChangeListener l) {
7361         getListenerInfo().mOnFocusChangeListener = l;
7362     }
7363 
7364     /**
7365      * Add a listener that will be called when the bounds of the view change due to
7366      * layout processing.
7367      *
7368      * @param listener The listener that will be called when layout bounds change.
7369      */
7370     public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
7371         ListenerInfo li = getListenerInfo();
7372         if (li.mOnLayoutChangeListeners == null) {
7373             li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
7374         }
7375         if (!li.mOnLayoutChangeListeners.contains(listener)) {
7376             li.mOnLayoutChangeListeners.add(listener);
7377         }
7378     }
7379 
7380     /**
7381      * Remove a listener for layout changes.
7382      *
7383      * @param listener The listener for layout bounds change.
7384      */
7385     public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
7386         ListenerInfo li = mListenerInfo;
7387         if (li == null || li.mOnLayoutChangeListeners == null) {
7388             return;
7389         }
7390         li.mOnLayoutChangeListeners.remove(listener);
7391     }
7392 
7393     /**
7394      * Add a listener for attach state changes.
7395      *
7396      * This listener will be called whenever this view is attached or detached
7397      * from a window. Remove the listener using
7398      * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
7399      *
7400      * @param listener Listener to attach
7401      * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
7402      */
7403     public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
7404         ListenerInfo li = getListenerInfo();
7405         if (li.mOnAttachStateChangeListeners == null) {
7406             li.mOnAttachStateChangeListeners
7407                     = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
7408         }
7409         li.mOnAttachStateChangeListeners.add(listener);
7410     }
7411 
7412     /**
7413      * Remove a listener for attach state changes. The listener will receive no further
7414      * notification of window attach/detach events.
7415      *
7416      * @param listener Listener to remove
7417      * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
7418      */
7419     public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
7420         ListenerInfo li = mListenerInfo;
7421         if (li == null || li.mOnAttachStateChangeListeners == null) {
7422             return;
7423         }
7424         li.mOnAttachStateChangeListeners.remove(listener);
7425     }
7426 
7427     /**
7428      * Returns the focus-change callback registered for this view.
7429      *
7430      * @return The callback, or null if one is not registered.
7431      */
7432     public OnFocusChangeListener getOnFocusChangeListener() {
7433         ListenerInfo li = mListenerInfo;
7434         return li != null ? li.mOnFocusChangeListener : null;
7435     }
7436 
7437     /**
7438      * Register a callback to be invoked when this view is clicked. If this view is not
7439      * clickable, it becomes clickable.
7440      *
7441      * @param l The callback that will run
7442      *
7443      * @see #setClickable(boolean)
7444      */
7445     public void setOnClickListener(@Nullable OnClickListener l) {
7446         if (!isClickable()) {
7447             setClickable(true);
7448         }
7449         getListenerInfo().mOnClickListener = l;
7450     }
7451 
7452     /**
7453      * Return whether this view has an attached OnClickListener.  Returns
7454      * true if there is a listener, false if there is none.
7455      */
7456     public boolean hasOnClickListeners() {
7457         ListenerInfo li = mListenerInfo;
7458         return (li != null && li.mOnClickListener != null);
7459     }
7460 
7461     /**
7462      * Register a callback to be invoked when this view is clicked and held. If this view is not
7463      * long clickable, it becomes long clickable.
7464      *
7465      * @param l The callback that will run
7466      *
7467      * @see #setLongClickable(boolean)
7468      */
7469     public void setOnLongClickListener(@Nullable OnLongClickListener l) {
7470         if (!isLongClickable()) {
7471             setLongClickable(true);
7472         }
7473         getListenerInfo().mOnLongClickListener = l;
7474     }
7475 
7476     /**
7477      * Return whether this view has an attached OnLongClickListener.  Returns
7478      * true if there is a listener, false if there is none.
7479      */
7480     public boolean hasOnLongClickListeners() {
7481         ListenerInfo li = mListenerInfo;
7482         return (li != null && li.mOnLongClickListener != null);
7483     }
7484 
7485     /**
7486      * @return the registered {@link OnLongClickListener} if there is one, {@code null} otherwise.
7487      * @hide
7488      */
7489     @Nullable
7490     public OnLongClickListener getOnLongClickListener() {
7491         ListenerInfo li = mListenerInfo;
7492         return (li != null) ? li.mOnLongClickListener : null;
7493     }
7494 
7495     /**
7496      * Register a callback to be invoked when this view is context clicked. If the view is not
7497      * context clickable, it becomes context clickable.
7498      *
7499      * @param l The callback that will run
7500      * @see #setContextClickable(boolean)
7501      */
7502     public void setOnContextClickListener(@Nullable OnContextClickListener l) {
7503         if (!isContextClickable()) {
7504             setContextClickable(true);
7505         }
7506         getListenerInfo().mOnContextClickListener = l;
7507     }
7508 
7509     /**
7510      * Register a callback to be invoked when the context menu for this view is
7511      * being built. If this view is not long clickable, it becomes long clickable.
7512      *
7513      * @param l The callback that will run
7514      *
7515      */
7516     public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
7517         if (!isLongClickable()) {
7518             setLongClickable(true);
7519         }
7520         getListenerInfo().mOnCreateContextMenuListener = l;
7521     }
7522 
7523     /**
7524      * Set an observer to collect stats for each frame rendered for this view.
7525      *
7526      * @hide
7527      */
7528     public void addFrameMetricsListener(Window window,
7529             Window.OnFrameMetricsAvailableListener listener,
7530             Handler handler) {
7531         if (mAttachInfo != null) {
7532             if (mAttachInfo.mThreadedRenderer != null) {
7533                 if (mFrameMetricsObservers == null) {
7534                     mFrameMetricsObservers = new ArrayList<>();
7535                 }
7536 
7537                 FrameMetricsObserver fmo = new FrameMetricsObserver(window, handler, listener);
7538                 mFrameMetricsObservers.add(fmo);
7539                 mAttachInfo.mThreadedRenderer.addObserver(fmo.getRendererObserver());
7540             } else {
7541                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
7542             }
7543         } else {
7544             if (mFrameMetricsObservers == null) {
7545                 mFrameMetricsObservers = new ArrayList<>();
7546             }
7547 
7548             FrameMetricsObserver fmo = new FrameMetricsObserver(window, handler, listener);
7549             mFrameMetricsObservers.add(fmo);
7550         }
7551     }
7552 
7553     /**
7554      * Remove observer configured to collect frame stats for this view.
7555      *
7556      * @hide
7557      */
7558     public void removeFrameMetricsListener(
7559             Window.OnFrameMetricsAvailableListener listener) {
7560         ThreadedRenderer renderer = getThreadedRenderer();
7561         FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
7562         if (fmo == null) {
7563             throw new IllegalArgumentException(
7564                     "attempt to remove OnFrameMetricsAvailableListener that was never added");
7565         }
7566 
7567         if (mFrameMetricsObservers != null) {
7568             mFrameMetricsObservers.remove(fmo);
7569             if (renderer != null) {
7570                 renderer.removeObserver(fmo.getRendererObserver());
7571             }
7572         }
7573     }
7574 
7575     private void registerPendingFrameMetricsObservers() {
7576         if (mFrameMetricsObservers != null) {
7577             ThreadedRenderer renderer = getThreadedRenderer();
7578             if (renderer != null) {
7579                 for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
7580                     renderer.addObserver(fmo.getRendererObserver());
7581                 }
7582             } else {
7583                 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
7584             }
7585         }
7586     }
7587 
7588     private FrameMetricsObserver findFrameMetricsObserver(
7589             Window.OnFrameMetricsAvailableListener listener) {
7590         if (mFrameMetricsObservers != null) {
7591             for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
7592                 FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
7593                 if (observer.mListener == listener) {
7594                     return observer;
7595                 }
7596             }
7597         }
7598 
7599         return null;
7600     }
7601 
7602     /** @hide */
7603     public void setNotifyAutofillManagerOnClick(boolean notify) {
7604         if (notify) {
7605             mPrivateFlags |= PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
7606         } else {
7607             mPrivateFlags &= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
7608         }
7609     }
7610 
7611     private void notifyAutofillManagerOnClick() {
7612         if ((mPrivateFlags & PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK) != 0) {
7613             try {
7614                 getAutofillManager().notifyViewClicked(this);
7615             } finally {
7616                 // Set it to already called so it's not called twice when called by
7617                 // performClickInternal()
7618                 mPrivateFlags &= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
7619             }
7620         }
7621     }
7622 
7623     /**
7624      * Entry point for {@link #performClick()} - other methods on View should call it instead of
7625      * {@code performClick()} directly to make sure the autofill manager is notified when
7626      * necessary (as subclasses could extend {@code performClick()} without calling the parent's
7627      * method).
7628      */
7629     private boolean performClickInternal() {
7630         // Must notify autofill manager before performing the click actions to avoid scenarios where
7631         // the app has a click listener that changes the state of views the autofill service might
7632         // be interested on.
7633         notifyAutofillManagerOnClick();
7634 
7635         return performClick();
7636     }
7637 
7638     /**
7639      * Call this view's OnClickListener, if it is defined.  Performs all normal
7640      * actions associated with clicking: reporting accessibility event, playing
7641      * a sound, etc.
7642      *
7643      * @return True there was an assigned OnClickListener that was called, false
7644      *         otherwise is returned.
7645      */
7646     // NOTE: other methods on View should not call this method directly, but performClickInternal()
7647     // instead, to guarantee that the autofill manager is notified when necessary (as subclasses
7648     // could extend this method without calling super.performClick()).
7649     public boolean performClick() {
7650         // We still need to call this method to handle the cases where performClick() was called
7651         // externally, instead of through performClickInternal()
7652         notifyAutofillManagerOnClick();
7653 
7654         final boolean result;
7655         final ListenerInfo li = mListenerInfo;
7656         if (li != null && li.mOnClickListener != null) {
7657             playSoundEffect(SoundEffectConstants.CLICK);
7658             li.mOnClickListener.onClick(this);
7659             result = true;
7660         } else {
7661             result = false;
7662         }
7663 
7664         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
7665 
7666         notifyEnterOrExitForAutoFillIfNeeded(true);
7667 
7668         return result;
7669     }
7670 
7671     /**
7672      * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
7673      * this only calls the listener, and does not do any associated clicking
7674      * actions like reporting an accessibility event.
7675      *
7676      * @return True there was an assigned OnClickListener that was called, false
7677      *         otherwise is returned.
7678      */
7679     public boolean callOnClick() {
7680         ListenerInfo li = mListenerInfo;
7681         if (li != null && li.mOnClickListener != null) {
7682             li.mOnClickListener.onClick(this);
7683             return true;
7684         }
7685         return false;
7686     }
7687 
7688     /**
7689      * Calls this view's OnLongClickListener, if it is defined. Invokes the
7690      * context menu if the OnLongClickListener did not consume the event.
7691      *
7692      * @return {@code true} if one of the above receivers consumed the event,
7693      *         {@code false} otherwise
7694      */
7695     public boolean performLongClick() {
7696         return performLongClickInternal(mLongClickX, mLongClickY);
7697     }
7698 
7699     /**
7700      * Calls this view's OnLongClickListener, if it is defined. Invokes the
7701      * context menu if the OnLongClickListener did not consume the event,
7702      * anchoring it to an (x,y) coordinate.
7703      *
7704      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
7705      *          to disable anchoring
7706      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
7707      *          to disable anchoring
7708      * @return {@code true} if one of the above receivers consumed the event,
7709      *         {@code false} otherwise
7710      */
7711     public boolean performLongClick(float x, float y) {
7712         mLongClickX = x;
7713         mLongClickY = y;
7714         final boolean handled = performLongClick();
7715         mLongClickX = Float.NaN;
7716         mLongClickY = Float.NaN;
7717         return handled;
7718     }
7719 
7720     /**
7721      * Calls this view's OnLongClickListener, if it is defined. Invokes the
7722      * context menu if the OnLongClickListener did not consume the event,
7723      * optionally anchoring it to an (x,y) coordinate.
7724      *
7725      * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
7726      *          to disable anchoring
7727      * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
7728      *          to disable anchoring
7729      * @return {@code true} if one of the above receivers consumed the event,
7730      *         {@code false} otherwise
7731      */
7732     private boolean performLongClickInternal(float x, float y) {
7733         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
7734 
7735         boolean handled = false;
7736         final OnLongClickListener listener =
7737                 mListenerInfo == null ? null : mListenerInfo.mOnLongClickListener;
7738         boolean shouldPerformHapticFeedback = true;
7739         if (listener != null) {
7740             handled = listener.onLongClick(View.this);
7741             if (handled) {
7742                 shouldPerformHapticFeedback = listener.onLongClickUseDefaultHapticFeedback(
7743                         View.this);
7744             }
7745         }
7746         if (!handled) {
7747             final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
7748             handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
7749         }
7750         if ((mViewFlags & TOOLTIP) == TOOLTIP) {
7751             if (!handled) {
7752                 handled = showLongClickTooltip((int) x, (int) y);
7753             }
7754         }
7755         if (handled && shouldPerformHapticFeedback) {
7756             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
7757         }
7758         return handled;
7759     }
7760 
7761     /**
7762      * Call this view's OnContextClickListener, if it is defined.
7763      *
7764      * @param x the x coordinate of the context click
7765      * @param y the y coordinate of the context click
7766      * @return True if there was an assigned OnContextClickListener that consumed the event, false
7767      *         otherwise.
7768      */
7769     public boolean performContextClick(float x, float y) {
7770         return performContextClick();
7771     }
7772 
7773     /**
7774      * Call this view's OnContextClickListener, if it is defined.
7775      *
7776      * @return True if there was an assigned OnContextClickListener that consumed the event, false
7777      *         otherwise.
7778      */
7779     public boolean performContextClick() {
7780         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
7781 
7782         boolean handled = false;
7783         ListenerInfo li = mListenerInfo;
7784         if (li != null && li.mOnContextClickListener != null) {
7785             handled = li.mOnContextClickListener.onContextClick(View.this);
7786         }
7787         if (handled) {
7788             performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
7789         }
7790         return handled;
7791     }
7792 
7793     /**
7794      * Performs button-related actions during a touch down event.
7795      *
7796      * @param event The event.
7797      * @return True if the down was consumed.
7798      *
7799      * @hide
7800      */
7801     protected boolean performButtonActionOnTouchDown(MotionEvent event) {
7802         if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
7803             (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
7804             showContextMenu(event.getX(), event.getY());
7805             mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
7806             return true;
7807         }
7808         return false;
7809     }
7810 
7811     /**
7812      * Shows the context menu for this view.
7813      *
7814      * @return {@code true} if the context menu was shown, {@code false}
7815      *         otherwise
7816      * @see #showContextMenu(float, float)
7817      */
7818     public boolean showContextMenu() {
7819         return getParent().showContextMenuForChild(this);
7820     }
7821 
7822     /**
7823      * Shows the context menu for this view anchored to the specified
7824      * view-relative coordinate.
7825      *
7826      * @param x the X coordinate in pixels relative to the view to which the
7827      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
7828      * @param y the Y coordinate in pixels relative to the view to which the
7829      *          menu should be anchored, or {@link Float#NaN} to disable anchoring
7830      * @return {@code true} if the context menu was shown, {@code false}
7831      *         otherwise
7832      */
7833     public boolean showContextMenu(float x, float y) {
7834         return getParent().showContextMenuForChild(this, x, y);
7835     }
7836 
7837     /**
7838      * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
7839      *
7840      * @param callback Callback that will control the lifecycle of the action mode
7841      * @return The new action mode if it is started, null otherwise
7842      *
7843      * @see ActionMode
7844      * @see #startActionMode(android.view.ActionMode.Callback, int)
7845      */
7846     public ActionMode startActionMode(ActionMode.Callback callback) {
7847         return startActionMode(callback, ActionMode.TYPE_PRIMARY);
7848     }
7849 
7850     /**
7851      * Start an action mode with the given type.
7852      *
7853      * @param callback Callback that will control the lifecycle of the action mode
7854      * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
7855      * @return The new action mode if it is started, null otherwise
7856      *
7857      * @see ActionMode
7858      */
7859     public ActionMode startActionMode(ActionMode.Callback callback, int type) {
7860         ViewParent parent = getParent();
7861         if (parent == null) return null;
7862         try {
7863             return parent.startActionModeForChild(this, callback, type);
7864         } catch (AbstractMethodError ame) {
7865             // Older implementations of custom views might not implement this.
7866             return parent.startActionModeForChild(this, callback);
7867         }
7868     }
7869 
7870     /**
7871      * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
7872      * Context, creating a unique View identifier to retrieve the result.
7873      *
7874      * @param intent The Intent to be started.
7875      * @param requestCode The request code to use.
7876      * @hide
7877      */
7878     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
7879     public void startActivityForResult(Intent intent, int requestCode) {
7880         mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
7881         getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
7882     }
7883 
7884     /**
7885      * If this View corresponds to the calling who, dispatches the activity result.
7886      * @param who The identifier for the targeted View to receive the result.
7887      * @param requestCode The integer request code originally supplied to
7888      *                    startActivityForResult(), allowing you to identify who this
7889      *                    result came from.
7890      * @param resultCode The integer result code returned by the child activity
7891      *                   through its setResult().
7892      * @param data An Intent, which can return result data to the caller
7893      *               (various data can be attached to Intent "extras").
7894      * @return {@code true} if the activity result was dispatched.
7895      * @hide
7896      */
7897     public boolean dispatchActivityResult(
7898             String who, int requestCode, int resultCode, Intent data) {
7899         if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
7900             onActivityResult(requestCode, resultCode, data);
7901             mStartActivityRequestWho = null;
7902             return true;
7903         }
7904         return false;
7905     }
7906 
7907     /**
7908      * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
7909      *
7910      * @param requestCode The integer request code originally supplied to
7911      *                    startActivityForResult(), allowing you to identify who this
7912      *                    result came from.
7913      * @param resultCode The integer result code returned by the child activity
7914      *                   through its setResult().
7915      * @param data An Intent, which can return result data to the caller
7916      *               (various data can be attached to Intent "extras").
7917      * @hide
7918      */
7919     public void onActivityResult(int requestCode, int resultCode, Intent data) {
7920         // Do nothing.
7921     }
7922 
7923     /**
7924      * Register a callback to be invoked when a hardware key is pressed in this view.
7925      * Key presses in software input methods will generally not trigger the methods of
7926      * this listener.
7927      * @param l the key listener to attach to this view
7928      */
7929     public void setOnKeyListener(OnKeyListener l) {
7930         getListenerInfo().mOnKeyListener = l;
7931     }
7932 
7933     /**
7934      * Register a callback to be invoked when a touch event is sent to this view.
7935      * @param l the touch listener to attach to this view
7936      */
7937     public void setOnTouchListener(OnTouchListener l) {
7938         getListenerInfo().mOnTouchListener = l;
7939     }
7940 
7941     /**
7942      * Register a callback to be invoked when a generic motion event is sent to this view.
7943      * @param l the generic motion listener to attach to this view
7944      */
7945     public void setOnGenericMotionListener(OnGenericMotionListener l) {
7946         getListenerInfo().mOnGenericMotionListener = l;
7947     }
7948 
7949     /**
7950      * Register a callback to be invoked when a hover event is sent to this view.
7951      * @param l the hover listener to attach to this view
7952      */
7953     public void setOnHoverListener(OnHoverListener l) {
7954         getListenerInfo().mOnHoverListener = l;
7955     }
7956 
7957     /**
7958      * Register a drag event listener callback object for this View. The parameter is
7959      * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
7960      * View, the system calls the
7961      * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
7962      * @param l An implementation of {@link android.view.View.OnDragListener}.
7963      */
7964     public void setOnDragListener(OnDragListener l) {
7965         getListenerInfo().mOnDragListener = l;
7966     }
7967 
7968     /**
7969      * Give this view focus. This will cause
7970      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
7971      *
7972      * Note: this does not check whether this {@link View} should get focus, it just
7973      * gives it focus no matter what.  It should only be called internally by framework
7974      * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
7975      *
7976      * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
7977      *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
7978      *        focus moved when requestFocus() is called. It may not always
7979      *        apply, in which case use the default View.FOCUS_DOWN.
7980      * @param previouslyFocusedRect The rectangle of the view that had focus
7981      *        prior in this View's coordinate system.
7982      */
7983     void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
7984         if (DBG) {
7985             System.out.println(this + " requestFocus()");
7986         }
7987 
7988         if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
7989             mPrivateFlags |= PFLAG_FOCUSED;
7990 
7991             View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
7992 
7993             if (mParent != null) {
7994                 mParent.requestChildFocus(this, this);
7995                 updateFocusedInCluster(oldFocus, direction);
7996             }
7997 
7998             if (mAttachInfo != null) {
7999                 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
8000             }
8001 
8002             onFocusChanged(true, direction, previouslyFocusedRect);
8003             refreshDrawableState();
8004         }
8005     }
8006 
8007     /**
8008      * Sets this view's preference for reveal behavior when it gains focus.
8009      *
8010      * <p>When set to true, this is a signal to ancestor views in the hierarchy that
8011      * this view would prefer to be brought fully into view when it gains focus.
8012      * For example, a text field that a user is meant to type into. Other views such
8013      * as scrolling containers may prefer to opt-out of this behavior.</p>
8014      *
8015      * <p>The default value for views is true, though subclasses may change this
8016      * based on their preferred behavior.</p>
8017      *
8018      * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
8019      *
8020      * @see #getRevealOnFocusHint()
8021      */
8022     public final void setRevealOnFocusHint(boolean revealOnFocus) {
8023         if (revealOnFocus) {
8024             mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
8025         } else {
8026             mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
8027         }
8028     }
8029 
8030     /**
8031      * Returns this view's preference for reveal behavior when it gains focus.
8032      *
8033      * <p>When this method returns true for a child view requesting focus, ancestor
8034      * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
8035      * should make a best effort to make the newly focused child fully visible to the user.
8036      * When it returns false, ancestor views should preferably not disrupt scroll positioning or
8037      * other properties affecting visibility to the user as part of the focus change.</p>
8038      *
8039      * @return true if this view would prefer to become fully visible when it gains focus,
8040      *         false if it would prefer not to disrupt scroll positioning
8041      *
8042      * @see #setRevealOnFocusHint(boolean)
8043      */
8044     public final boolean getRevealOnFocusHint() {
8045         return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
8046     }
8047 
8048     /**
8049      * Populates <code>outRect</code> with the hotspot bounds. By default,
8050      * the hotspot bounds are identical to the screen bounds.
8051      *
8052      * @param outRect rect to populate with hotspot bounds
8053      * @hide Only for internal use by views and widgets.
8054      */
8055     public void getHotspotBounds(Rect outRect) {
8056         final Drawable background = getBackground();
8057         if (background != null) {
8058             background.getHotspotBounds(outRect);
8059         } else {
8060             getBoundsOnScreen(outRect);
8061         }
8062     }
8063 
8064     /**
8065      * Request that a rectangle of this view be visible on the screen,
8066      * scrolling if necessary just enough.
8067      *
8068      * <p>A View should call this if it maintains some notion of which part
8069      * of its content is interesting.  For example, a text editing view
8070      * should call this when its cursor moves.
8071      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
8072      * It should not be affected by which part of the View is currently visible or its scroll
8073      * position.
8074      *
8075      * @param rectangle The rectangle in the View's content coordinate space
8076      * @return Whether any parent scrolled.
8077      */
8078     public boolean requestRectangleOnScreen(Rect rectangle) {
8079         return requestRectangleOnScreen(rectangle, false);
8080     }
8081 
8082     /**
8083      * Request that a rectangle of this view be visible on the screen,
8084      * scrolling if necessary just enough.
8085      *
8086      * <p>A View should call this if it maintains some notion of which part
8087      * of its content is interesting.  For example, a text editing view
8088      * should call this when its cursor moves.
8089      * <p>The Rectangle passed into this method should be in the View's content coordinate space.
8090      * It should not be affected by which part of the View is currently visible or its scroll
8091      * position.
8092      * <p>When <code>immediate</code> is set to true, scrolling will not be
8093      * animated.
8094      *
8095      * @param rectangle The rectangle in the View's content coordinate space
8096      * @param immediate True to forbid animated scrolling, false otherwise
8097      * @return Whether any parent scrolled.
8098      */
8099     public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
8100         if (mParent == null) {
8101             return false;
8102         }
8103 
8104         View child = this;
8105 
8106         RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
8107         position.set(rectangle);
8108 
8109         ViewParent parent = mParent;
8110         boolean scrolled = false;
8111         while (parent != null) {
8112             rectangle.set((int) position.left, (int) position.top,
8113                     (int) position.right, (int) position.bottom);
8114 
8115             scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
8116 
8117             if (!(parent instanceof View)) {
8118                 break;
8119             }
8120 
8121             // move it from child's content coordinate space to parent's content coordinate space
8122             position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
8123 
8124             child = (View) parent;
8125             parent = child.getParent();
8126         }
8127 
8128         return scrolled;
8129     }
8130 
8131     /**
8132      * Called when this view wants to give up focus. If focus is cleared
8133      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
8134      * <p>
8135      * <strong>Note:</strong> When not in touch-mode, the framework will try to give focus
8136      * to the first focusable View from the top after focus is cleared. Hence, if this
8137      * View is the first from the top that can take focus, then all callbacks
8138      * related to clearing focus will be invoked after which the framework will
8139      * give focus to this view.
8140      * </p>
8141      */
8142     public void clearFocus() {
8143         if (DBG) {
8144             System.out.println(this + " clearFocus()");
8145         }
8146 
8147         final boolean refocus = sAlwaysAssignFocus || !isInTouchMode();
8148         clearFocusInternal(null, true, refocus);
8149     }
8150 
8151     /**
8152      * Clears focus from the view, optionally propagating the change up through
8153      * the parent hierarchy and requesting that the root view place new focus.
8154      *
8155      * @param propagate whether to propagate the change up through the parent
8156      *            hierarchy
8157      * @param refocus when propagate is true, specifies whether to request the
8158      *            root view place new focus
8159      */
8160     void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
8161         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
8162             mPrivateFlags &= ~PFLAG_FOCUSED;
8163             clearParentsWantFocus();
8164 
8165             if (propagate && mParent != null) {
8166                 mParent.clearChildFocus(this);
8167             }
8168 
8169             onFocusChanged(false, 0, null);
8170             refreshDrawableState();
8171 
8172             if (propagate && (!refocus || !rootViewRequestFocus())) {
8173                 notifyGlobalFocusCleared(this);
8174             }
8175         }
8176     }
8177 
8178     void notifyGlobalFocusCleared(View oldFocus) {
8179         if (oldFocus != null && mAttachInfo != null) {
8180             mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
8181         }
8182     }
8183 
8184     boolean rootViewRequestFocus() {
8185         final View root = getRootView();
8186         return root != null && root.requestFocus();
8187     }
8188 
8189     /**
8190      * Called internally by the view system when a new view is getting focus.
8191      * This is what clears the old focus.
8192      * <p>
8193      * <b>NOTE:</b> The parent view's focused child must be updated manually
8194      * after calling this method. Otherwise, the view hierarchy may be left in
8195      * an inconstent state.
8196      */
8197     void unFocus(View focused) {
8198         if (DBG) {
8199             System.out.println(this + " unFocus()");
8200         }
8201 
8202         clearFocusInternal(focused, false, false);
8203     }
8204 
8205     /**
8206      * Returns true if this view has focus itself, or is the ancestor of the
8207      * view that has focus.
8208      *
8209      * @return True if this view has or contains focus, false otherwise.
8210      */
8211     @ViewDebug.ExportedProperty(category = "focus")
8212     public boolean hasFocus() {
8213         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
8214     }
8215 
8216     /**
8217      * Returns true if this view is focusable or if it contains a reachable View
8218      * for which {@link #hasFocusable()} returns {@code true}. A "reachable hasFocusable()"
8219      * is a view whose parents do not block descendants focus.
8220      * Only {@link #VISIBLE} views are considered focusable.
8221      *
8222      * <p>As of {@link Build.VERSION_CODES#O} views that are determined to be focusable
8223      * through {@link #FOCUSABLE_AUTO} will also cause this method to return {@code true}.
8224      * Apps that declare a {@link android.content.pm.ApplicationInfo#targetSdkVersion} of
8225      * earlier than {@link Build.VERSION_CODES#O} will continue to see this method return
8226      * {@code false} for views not explicitly marked as focusable.
8227      * Use {@link #hasExplicitFocusable()} if you require the pre-{@link Build.VERSION_CODES#O}
8228      * behavior.</p>
8229      *
8230      * @return {@code true} if the view is focusable or if the view contains a focusable
8231      *         view, {@code false} otherwise
8232      *
8233      * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
8234      * @see ViewGroup#getTouchscreenBlocksFocus()
8235      * @see #hasExplicitFocusable()
8236      */
8237     public boolean hasFocusable() {
8238         return hasFocusable(!sHasFocusableExcludeAutoFocusable, false);
8239     }
8240 
8241     /**
8242      * Returns true if this view is focusable or if it contains a reachable View
8243      * for which {@link #hasExplicitFocusable()} returns {@code true}.
8244      * A "reachable hasExplicitFocusable()" is a view whose parents do not block descendants focus.
8245      * Only {@link #VISIBLE} views for which {@link #getFocusable()} would return
8246      * {@link #FOCUSABLE} are considered focusable.
8247      *
8248      * <p>This method preserves the pre-{@link Build.VERSION_CODES#O} behavior of
8249      * {@link #hasFocusable()} in that only views explicitly set focusable will cause
8250      * this method to return true. A view set to {@link #FOCUSABLE_AUTO} that resolves
8251      * to focusable will not.</p>
8252      *
8253      * @return {@code true} if the view is focusable or if the view contains a focusable
8254      *         view, {@code false} otherwise
8255      *
8256      * @see #hasFocusable()
8257      */
8258     public boolean hasExplicitFocusable() {
8259         return hasFocusable(false, true);
8260     }
8261 
8262     boolean hasFocusable(boolean allowAutoFocus, boolean dispatchExplicit) {
8263         if (!isFocusableInTouchMode()) {
8264             for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
8265                 final ViewGroup g = (ViewGroup) p;
8266                 if (g.shouldBlockFocusForTouchscreen()) {
8267                     return false;
8268                 }
8269             }
8270         }
8271 
8272         // Invisible, gone, or disabled views are never focusable.
8273         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE
8274                 || (mViewFlags & ENABLED_MASK) != ENABLED) {
8275             return false;
8276         }
8277 
8278         // Only use effective focusable value when allowed.
8279         if ((allowAutoFocus || getFocusable() != FOCUSABLE_AUTO) && isFocusable()) {
8280             return true;
8281         }
8282 
8283         return false;
8284     }
8285 
8286     /**
8287      * Called by the view system when the focus state of this view changes.
8288      * When the focus change event is caused by directional navigation, direction
8289      * and previouslyFocusedRect provide insight into where the focus is coming from.
8290      * When overriding, be sure to call up through to the super class so that
8291      * the standard focus handling will occur.
8292      *
8293      * @param gainFocus True if the View has focus; false otherwise.
8294      * @param direction The direction focus has moved when requestFocus()
8295      *                  is called to give this view focus. Values are
8296      *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
8297      *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
8298      *                  It may not always apply, in which case use the default.
8299      * @param previouslyFocusedRect The rectangle, in this view's coordinate
8300      *        system, of the previously focused view.  If applicable, this will be
8301      *        passed in as finer grained information about where the focus is coming
8302      *        from (in addition to direction).  Will be <code>null</code> otherwise.
8303      */
8304     @CallSuper
8305     protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
8306             @Nullable Rect previouslyFocusedRect) {
8307         if (gainFocus) {
8308             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
8309         } else {
8310             notifyViewAccessibilityStateChangedIfNeeded(
8311                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8312         }
8313 
8314         // Here we check whether we still need the default focus highlight, and switch it on/off.
8315         switchDefaultFocusHighlight();
8316 
8317         if (!gainFocus) {
8318             if (isPressed()) {
8319                 setPressed(false);
8320             }
8321             if (hasWindowFocus()) {
8322                 notifyFocusChangeToImeFocusController(false /* hasFocus */);
8323             }
8324             onFocusLost();
8325         } else if (hasWindowFocus()) {
8326             notifyFocusChangeToImeFocusController(true /* hasFocus */);
8327 
8328             if (mIsHandwritingDelegate) {
8329                 ViewRootImpl viewRoot = getViewRootImpl();
8330                 if (viewRoot != null) {
8331                     viewRoot.getHandwritingInitiator().onDelegateViewFocused(this);
8332                 }
8333             }
8334         }
8335 
8336         invalidate(true);
8337         ListenerInfo li = mListenerInfo;
8338         if (li != null && li.mOnFocusChangeListener != null) {
8339             li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
8340         }
8341 
8342         if (mAttachInfo != null) {
8343             mAttachInfo.mKeyDispatchState.reset(this);
8344         }
8345 
8346         if (mParent != null) {
8347             mParent.onDescendantUnbufferedRequested();
8348         }
8349 
8350         notifyEnterOrExitForAutoFillIfNeeded(gainFocus);
8351         updatePreferKeepClearForFocus();
8352     }
8353 
8354     /**
8355      * Notify {@link ImeFocusController} about the focus change of the {@link View}.
8356      *
8357      * @param hasFocus {@code true} when the {@link View} is being focused.
8358      */
8359     private void notifyFocusChangeToImeFocusController(boolean hasFocus) {
8360         if (mAttachInfo == null) {
8361             return;
8362         }
8363         mAttachInfo.mViewRootImpl.getImeFocusController().onViewFocusChanged(this, hasFocus);
8364     }
8365 
8366     /** @hide */
8367     public void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {
8368         if (canNotifyAutofillEnterExitEvent()) {
8369             AutofillManager afm = getAutofillManager();
8370             if (afm != null) {
8371                 if (enter) {
8372                     // We have not been laid out yet, hence cannot evaluate
8373                     // whether this view is visible to the user, we will do
8374                     // the evaluation once layout is complete.
8375                     // Sometimes, views are already laid out, but it's still
8376                     // not visible to the user, we also do the evaluation once
8377                     // the view is visible. ex: There is a fade-in animation
8378                     // for the activity, the view will be laid out when the
8379                     // animation beginning. On the time, the view is not visible
8380                     // to the user. And then as the animation progresses, the view
8381                     // becomes visible to the user.
8382                     if (!isLaidOut() || !isVisibleToUser()) {
8383                         mPrivateFlags3 |= PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
8384                     } else if (isVisibleToUser()) {
8385                         if (isFocused()) {
8386                             // TODO This is a potential problem that View gets focus before it's
8387                             // visible to User. Ideally View should handle the event when
8388                             // isVisibleToUser() becomes true where it should issue
8389                             // notifyViewEntered().
8390                             afm.notifyViewEntered(this);
8391                         } else {
8392                             afm.notifyViewEnteredForFillDialog(this);
8393                         }
8394                     }
8395                 } else if (!isFocused()) {
8396                     afm.notifyViewExited(this);
8397                 }
8398             }
8399         }
8400     }
8401 
8402     /**
8403      * Visually distinct portion of a window with window-like semantics are considered panes for
8404      * accessibility purposes. One example is the content view of a large fragment that is replaced.
8405      * In order for accessibility services to understand a pane's window-like behavior, panes
8406      * should have descriptive titles. Views with pane titles produce
8407      * {@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED}s when they appear, disappear, or change
8408      * title.
8409      *
8410      * <p>
8411      * When transitioning from one Activity to another, instead of using
8412      * setAccessibilityPaneTitle(), set a descriptive title for its window by using android:label
8413      * for the matching <activity> entry in your application’s manifest or updating the title at
8414      * runtime with{@link android.app.Activity#setTitle(CharSequence)}.
8415      *
8416      * @param accessibilityPaneTitle The pane's title. Setting to {@code null} indicates that this
8417      *                               View is not a pane.
8418      *
8419      * {@see AccessibilityNodeInfo#setPaneTitle(CharSequence)}
8420      *
8421      * @attr ref android.R.styleable#View_accessibilityPaneTitle
8422      */
8423     public void setAccessibilityPaneTitle(@Nullable CharSequence accessibilityPaneTitle) {
8424         if (!TextUtils.equals(accessibilityPaneTitle, mAccessibilityPaneTitle)) {
8425             boolean currentPaneTitleEmpty = mAccessibilityPaneTitle == null;
8426             boolean newPaneTitleEmpty =  accessibilityPaneTitle == null;
8427             mAccessibilityPaneTitle = accessibilityPaneTitle;
8428             // Make explicitly important as nulled titles need to be important for DISAPPEARED
8429             // events.
8430             if (mAccessibilityPaneTitle != null
8431                     && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
8432                 setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
8433             }
8434             if (currentPaneTitleEmpty) {
8435                 notifyViewAccessibilityStateChangedIfNeeded(
8436                         AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_APPEARED);
8437             } else if (newPaneTitleEmpty) {
8438                 notifyViewAccessibilityStateChangedIfNeeded(
8439                         AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED);
8440             } else {
8441                 notifyViewAccessibilityStateChangedIfNeeded(
8442                         AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_TITLE);
8443             }
8444         }
8445     }
8446 
8447     /**
8448      * Get the title of the pane for purposes of accessibility.
8449      *
8450      * @return The current pane title.
8451      *
8452      * {@see #setAccessibilityPaneTitle}.
8453      *
8454      * @attr ref android.R.styleable#View_accessibilityPaneTitle
8455      */
8456     @InspectableProperty
8457     @Nullable
8458     public CharSequence getAccessibilityPaneTitle() {
8459         return mAccessibilityPaneTitle;
8460     }
8461 
8462     private boolean isAccessibilityPane() {
8463         return mAccessibilityPaneTitle != null;
8464     }
8465 
8466     /**
8467      * Sends an accessibility event of the given type. If accessibility is
8468      * not enabled this method has no effect. The default implementation calls
8469      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
8470      * to populate information about the event source (this View), then calls
8471      * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
8472      * populate the text content of the event source including its descendants,
8473      * then for events type {@link AccessibilityEvent#TYPE_VIEW_SCROLLED}
8474      * and {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} with
8475      * subtype {@link AccessibilityEvent#CONTENT_CHANGE_TYPE_STATE_DESCRIPTION},
8476      * throttle the events, and last calls
8477      * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
8478      * on its parent to request sending of the event to interested parties.
8479      * <p>
8480      * If an {@link AccessibilityDelegate} has been specified via calling
8481      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8482      * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
8483      * responsible for handling this call.
8484      * </p>
8485      * <p>
8486      * If this view uses {@link AccessibilityNodeProvider} to provide virtual view hierarchy rooted
8487      * at this view, this method should not be called to send events from virtual children because
8488      * it will populate the events with wrong information and the events should be throttled per
8489      * child instead at the virtual root level. To send events from virtual children, call
8490      * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)} on the view's
8491      * parent to request sending of the event to interested parties.
8492      * </p>
8493      *
8494      * @param eventType The type of the event to send, as defined by several types from
8495      * {@link AccessibilityEvent}, such as
8496      * {@link AccessibilityEvent#TYPE_VIEW_CLICKED} or
8497      * {@link AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
8498      *
8499      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
8500      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
8501      * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
8502      * @see AccessibilityDelegate
8503      */
8504     public void sendAccessibilityEvent(int eventType) {
8505         if (mAccessibilityDelegate != null) {
8506             mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
8507         } else {
8508             sendAccessibilityEventInternal(eventType);
8509         }
8510     }
8511 
8512     /**
8513      * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
8514      * {@link AccessibilityEvent} to suggest that an accessibility service announce the
8515      * specified text to its users.
8516      * <p>
8517      * Note: The event generated with this API carries no semantic meaning, and is appropriate only
8518      * in exceptional situations. Apps can generally achieve correct behavior for accessibility by
8519      * accurately supplying the semantics of their UI.
8520      * They should not need to specify what exactly is announced to users.
8521      *
8522      * <p>
8523      * In general, only announce transitions and don’t generate a confirmation message for simple
8524      * actions like a button press. Label your controls concisely and precisely instead, and for
8525      * significant UI changes like window changes, use
8526      * {@link android.app.Activity#setTitle(CharSequence)} and
8527      * {@link View#setAccessibilityPaneTitle(CharSequence)}.
8528      *
8529      * <p>
8530      * Use {@link View#setAccessibilityLiveRegion(int)} to inform the user of changes to critical
8531      * views within the user interface. These should still be used sparingly as they may generate
8532      * announcements every time a View is updated.
8533      *
8534      * @param text The announcement text.
8535      */
8536     public void announceForAccessibility(CharSequence text) {
8537         if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
8538             AccessibilityEvent event = AccessibilityEvent.obtain(
8539                     AccessibilityEvent.TYPE_ANNOUNCEMENT);
8540             onInitializeAccessibilityEvent(event);
8541             event.getText().add(text);
8542             event.setContentDescription(null);
8543             mParent.requestSendAccessibilityEvent(this, event);
8544         }
8545     }
8546 
8547     /**
8548      * @see #sendAccessibilityEvent(int)
8549      *
8550      * Note: Called from the default {@link AccessibilityDelegate}.
8551      *
8552      * @hide
8553      */
8554     public void sendAccessibilityEventInternal(int eventType) {
8555         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
8556             sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
8557         }
8558     }
8559 
8560     /**
8561      * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
8562      * takes as an argument an empty {@link AccessibilityEvent} and does not
8563      * perform a check whether accessibility is enabled.
8564      * <p>
8565      * If an {@link AccessibilityDelegate} has been specified via calling
8566      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8567      * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
8568      * is responsible for handling this call.
8569      * </p>
8570      *
8571      * @param event The event to send.
8572      *
8573      * @see #sendAccessibilityEvent(int)
8574      */
8575     public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
8576         if (mAccessibilityDelegate != null) {
8577             mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
8578         } else {
8579             sendAccessibilityEventUncheckedInternal(event);
8580         }
8581     }
8582 
8583     /**
8584      * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
8585      *
8586      * Note: Called from the default {@link AccessibilityDelegate}.
8587      *
8588      * @hide
8589      */
8590     public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
8591         // Panes disappearing are relevant even if though the view is no longer visible.
8592         boolean isWindowStateChanged =
8593                 (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
8594         boolean isWindowDisappearedEvent = isWindowStateChanged && ((event.getContentChangeTypes()
8595                 & AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED) != 0);
8596         boolean detached = detached();
8597         if (!isShown() && !isWindowDisappearedEvent && !detached) {
8598             return;
8599         }
8600         onInitializeAccessibilityEvent(event);
8601         // Only a subset of accessibility events populates text content.
8602         if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
8603             dispatchPopulateAccessibilityEvent(event);
8604         }
8605         SendAccessibilityEventThrottle throttle = getThrottleForAccessibilityEvent(event);
8606         if (throttle != null) {
8607             throttle.post(event);
8608         } else if (!isWindowDisappearedEvent && detached) {
8609             // Views could be attached soon later. Accessibility events during this temporarily
8610             // detached period should be sent too.
8611             postDelayed(() -> {
8612                 if (AccessibilityManager.getInstance(mContext).isEnabled() && isShown()) {
8613                     requestParentSendAccessibilityEvent(event);
8614                 }
8615             }, ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
8616         } else {
8617             requestParentSendAccessibilityEvent(event);
8618         }
8619     }
8620 
8621     private void requestParentSendAccessibilityEvent(AccessibilityEvent event) {
8622         ViewParent parent = getParent();
8623         if (parent != null) {
8624             getParent().requestSendAccessibilityEvent(this, event);
8625         }
8626     }
8627 
8628     private SendAccessibilityEventThrottle getThrottleForAccessibilityEvent(
8629             AccessibilityEvent event) {
8630         if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
8631             if (mSendViewScrolledAccessibilityEvent == null) {
8632                 mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
8633             }
8634             return mSendViewScrolledAccessibilityEvent;
8635         }
8636         boolean isStateContentChanged = (event.getContentChangeTypes()
8637                 & AccessibilityEvent.CONTENT_CHANGE_TYPE_STATE_DESCRIPTION) != 0;
8638         if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
8639                 && isStateContentChanged) {
8640             if (mSendStateChangedAccessibilityEvent == null) {
8641                 mSendStateChangedAccessibilityEvent = new SendAccessibilityEventThrottle();
8642             }
8643             return mSendStateChangedAccessibilityEvent;
8644         }
8645         return null;
8646     }
8647 
8648     private void clearAccessibilityThrottles() {
8649         cancel(mSendViewScrolledAccessibilityEvent);
8650         cancel(mSendStateChangedAccessibilityEvent);
8651     }
8652 
8653     /**
8654      * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
8655      * to its children for adding their text content to the event. Note that the
8656      * event text is populated in a separate dispatch path since we add to the
8657      * event not only the text of the source but also the text of all its descendants.
8658      * A typical implementation will call
8659      * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
8660      * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
8661      * on each child. Override this method if custom population of the event text
8662      * content is required.
8663      * <p>
8664      * If an {@link AccessibilityDelegate} has been specified via calling
8665      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8666      * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
8667      * is responsible for handling this call.
8668      * </p>
8669      * <p>
8670      * If this view sets {@link #isAccessibilityDataSensitive()} then this view should only append
8671      * sensitive information to an event that also sets
8672      * {@link AccessibilityEvent#isAccessibilityDataSensitive()}.
8673      * </p>
8674      * <p>
8675      * <em>Note:</em> Accessibility events of certain types are not dispatched for
8676      * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
8677      * </p>
8678      *
8679      * @param event The event.
8680      *
8681      * @return True if the event population was completed.
8682      */
8683     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
8684         if (mAccessibilityDelegate != null) {
8685             return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
8686         } else {
8687             return dispatchPopulateAccessibilityEventInternal(event);
8688         }
8689     }
8690 
8691     /**
8692      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
8693      *
8694      * Note: Called from the default {@link AccessibilityDelegate}.
8695      *
8696      * @hide
8697      */
8698     public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
8699         onPopulateAccessibilityEvent(event);
8700         return false;
8701     }
8702 
8703     /**
8704      * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
8705      * giving a chance to this View to populate the accessibility event with its
8706      * text content. While this method is free to modify event
8707      * attributes other than text content, doing so should normally be performed in
8708      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
8709      * <p>
8710      * Example: Adding formatted date string to an accessibility event in addition
8711      *          to the text added by the super implementation:
8712      * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
8713      *     super.onPopulateAccessibilityEvent(event);
8714      *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
8715      *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
8716      *         mCurrentDate.getTimeInMillis(), flags);
8717      *     event.getText().add(selectedDateUtterance);
8718      * }</pre>
8719      * <p>
8720      * If an {@link AccessibilityDelegate} has been specified via calling
8721      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8722      * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
8723      * is responsible for handling this call.
8724      * </p>
8725      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
8726      * information to the event, in case the default implementation has basic information to add.
8727      * </p>
8728      *
8729      * @param event The accessibility event which to populate.
8730      *
8731      * @see #sendAccessibilityEvent(int)
8732      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
8733      */
8734     @CallSuper
8735     public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
8736         if (mAccessibilityDelegate != null) {
8737             mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
8738         } else {
8739             onPopulateAccessibilityEventInternal(event);
8740         }
8741     }
8742 
8743     /**
8744      * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
8745      *
8746      * Note: Called from the default {@link AccessibilityDelegate}.
8747      *
8748      * @hide
8749      */
8750     public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
8751         if ((event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED)
8752                 && isAccessibilityPane()) {
8753             event.getText().add(getAccessibilityPaneTitle());
8754         }
8755     }
8756 
8757     /**
8758      * Initializes an {@link AccessibilityEvent} with information about
8759      * this View which is the event source. In other words, the source of
8760      * an accessibility event is the view whose state change triggered firing
8761      * the event.
8762      * <p>
8763      * Example: Setting the password property of an event in addition
8764      *          to properties set by the super implementation:
8765      * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
8766      *     super.onInitializeAccessibilityEvent(event);
8767      *     event.setPassword(true);
8768      * }</pre>
8769      * <p>
8770      * If an {@link AccessibilityDelegate} has been specified via calling
8771      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8772      * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
8773      * is responsible for handling this call.
8774      * </p>
8775      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
8776      * information to the event, in case the default implementation has basic information to add.
8777      * </p>
8778      * @param event The event to initialize.
8779      *
8780      * @see #sendAccessibilityEvent(int)
8781      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
8782      */
8783     @CallSuper
8784     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
8785         if (mAccessibilityDelegate != null) {
8786             mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
8787         } else {
8788             onInitializeAccessibilityEventInternal(event);
8789         }
8790     }
8791 
8792     /**
8793      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
8794      *
8795      * Note: Called from the default {@link AccessibilityDelegate}.
8796      *
8797      * @hide
8798      */
8799     @UnsupportedAppUsage
8800     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
8801         event.setSource(this);
8802         event.setClassName(getAccessibilityClassName());
8803         event.setPackageName(getContext().getPackageName());
8804         event.setEnabled(isEnabled());
8805         event.setContentDescription(mContentDescription);
8806         event.setScrollX(getScrollX());
8807         event.setScrollY(getScrollY());
8808 
8809         switch (event.getEventType()) {
8810             case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
8811                 ArrayList<View> focusablesTempList = (mAttachInfo != null)
8812                         ? mAttachInfo.mTempArrayList : new ArrayList<View>();
8813                 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
8814                 event.setItemCount(focusablesTempList.size());
8815                 event.setCurrentItemIndex(focusablesTempList.indexOf(this));
8816                 if (mAttachInfo != null) {
8817                     focusablesTempList.clear();
8818                 }
8819             } break;
8820             case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
8821                 CharSequence text = getIterableTextForAccessibility();
8822                 if (text != null && text.length() > 0) {
8823                     event.setFromIndex(getAccessibilitySelectionStart());
8824                     event.setToIndex(getAccessibilitySelectionEnd());
8825                     event.setItemCount(text.length());
8826                 }
8827             } break;
8828         }
8829     }
8830 
8831     /**
8832      * Returns an {@link AccessibilityNodeInfo} representing this view from the
8833      * point of view of an {@link android.accessibilityservice.AccessibilityService}.
8834      * This method is responsible for obtaining an accessibility node info from a
8835      * pool of reusable instances and calling
8836      * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
8837      * initialize the former.
8838      * <p>
8839      * Note: The client is responsible for recycling the obtained instance by calling
8840      *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
8841      * </p>
8842      *
8843      * @return A populated {@link AccessibilityNodeInfo}.
8844      *
8845      * @see AccessibilityNodeInfo
8846      */
8847     public AccessibilityNodeInfo createAccessibilityNodeInfo() {
8848         if (mAccessibilityDelegate != null) {
8849             return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
8850         } else {
8851             return createAccessibilityNodeInfoInternal();
8852         }
8853     }
8854 
8855     /**
8856      * @see #createAccessibilityNodeInfo()
8857      *
8858      * @hide
8859      */
8860     public @Nullable AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
8861         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
8862         if (provider != null) {
8863             return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
8864         } else {
8865             AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
8866             onInitializeAccessibilityNodeInfo(info);
8867             return info;
8868         }
8869     }
8870 
8871     /**
8872      * Initializes an {@link AccessibilityNodeInfo} with information about this view.
8873      * The base implementation sets:
8874      * <ul>
8875      *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
8876      *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
8877      *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
8878      *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
8879      *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
8880      *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
8881      *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
8882      *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
8883      *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
8884      *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
8885      *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
8886      *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
8887      *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
8888      * </ul>
8889      * <p>
8890      * Subclasses should override this method, call the super implementation,
8891      * and set additional attributes.
8892      * </p>
8893      * <p>
8894      * If an {@link AccessibilityDelegate} has been specified via calling
8895      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8896      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
8897      * is responsible for handling this call.
8898      * </p>
8899      *
8900      * @param info The instance to initialize.
8901      */
8902     @CallSuper
8903     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
8904         if (mAccessibilityDelegate != null) {
8905             mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
8906         } else {
8907             onInitializeAccessibilityNodeInfoInternal(info);
8908         }
8909     }
8910 
8911     /**
8912      * Gets the location of this view in screen coordinates.
8913      *
8914      * @param outRect The output location
8915      * @hide
8916      */
8917     @UnsupportedAppUsage
8918     public void getBoundsOnScreen(Rect outRect) {
8919         getBoundsOnScreen(outRect, false);
8920     }
8921 
8922     /**
8923      * Gets the location of this view in screen coordinates.
8924      *
8925      * @param outRect The output location
8926      * @param clipToParent Whether to clip child bounds to the parent ones.
8927      * @hide
8928      */
8929     @UnsupportedAppUsage
8930     @TestApi
8931     public void getBoundsOnScreen(@NonNull Rect outRect, boolean clipToParent) {
8932         if (mAttachInfo == null) {
8933             return;
8934         }
8935         RectF position = mAttachInfo.mTmpTransformRect;
8936         getBoundsToScreenInternal(position, clipToParent);
8937         outRect.set(Math.round(position.left), Math.round(position.top),
8938                 Math.round(position.right), Math.round(position.bottom));
8939         // If "Sandboxing View Bounds APIs" override is enabled, applyViewBoundsSandboxingIfNeeded
8940         // will sandbox outRect within window bounds.
8941         mAttachInfo.mViewRootImpl.applyViewBoundsSandboxingIfNeeded(outRect);
8942     }
8943 
8944     /**
8945      * Gets the location of this view in screen coordinates.
8946      *
8947      * @param outRect The output location
8948      * @param clipToParent Whether to clip child bounds to the parent ones.
8949      * @hide
8950      */
8951     public void getBoundsOnScreen(RectF outRect, boolean clipToParent) {
8952         if (mAttachInfo == null) {
8953             return;
8954         }
8955         RectF position = mAttachInfo.mTmpTransformRect;
8956         getBoundsToScreenInternal(position, clipToParent);
8957         outRect.set(position.left, position.top, position.right, position.bottom);
8958     }
8959 
8960     /**
8961      * Gets the location of this view in window coordinates.
8962      *
8963      * @param outRect The output location
8964      * @param clipToParent Whether to clip child bounds to the parent ones.
8965      * @hide
8966      */
8967     public void getBoundsInWindow(Rect outRect, boolean clipToParent) {
8968         if (mAttachInfo == null) {
8969             return;
8970         }
8971         RectF position = mAttachInfo.mTmpTransformRect;
8972         getBoundsToWindowInternal(position, clipToParent);
8973         outRect.set(Math.round(position.left), Math.round(position.top),
8974                 Math.round(position.right), Math.round(position.bottom));
8975     }
8976 
8977     private void getBoundsToScreenInternal(RectF position, boolean clipToParent) {
8978         position.set(0, 0, mRight - mLeft, mBottom - mTop);
8979         mapRectFromViewToScreenCoords(position, clipToParent);
8980     }
8981 
8982     private void getBoundsToWindowInternal(RectF position, boolean clipToParent) {
8983         position.set(0, 0, mRight - mLeft, mBottom - mTop);
8984         mapRectFromViewToWindowCoords(position, clipToParent);
8985     }
8986 
8987     /**
8988      * Map a rectangle from view-relative coordinates to screen-relative coordinates
8989      *
8990      * @param rect The rectangle to be mapped
8991      * @param clipToParent Whether to clip child bounds to the parent ones.
8992      * @hide
8993      */
8994     public void mapRectFromViewToScreenCoords(RectF rect, boolean clipToParent) {
8995         mapRectFromViewToWindowCoords(rect, clipToParent);
8996         rect.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
8997     }
8998 
8999     /**
9000      * Map a rectangle from view-relative coordinates to window-relative coordinates
9001      *
9002      * @param rect The rectangle to be mapped
9003      * @param clipToParent Whether to clip child bounds to the parent ones.
9004      * @hide
9005      */
9006     public void mapRectFromViewToWindowCoords(RectF rect, boolean clipToParent) {
9007         if (!hasIdentityMatrix()) {
9008             getMatrix().mapRect(rect);
9009         }
9010 
9011         rect.offset(mLeft, mTop);
9012 
9013         ViewParent parent = mParent;
9014         while (parent instanceof View) {
9015             View parentView = (View) parent;
9016 
9017             rect.offset(-parentView.mScrollX, -parentView.mScrollY);
9018 
9019             if (clipToParent) {
9020                 rect.left = Math.max(rect.left, 0);
9021                 rect.top = Math.max(rect.top, 0);
9022                 rect.right = Math.min(rect.right, parentView.getWidth());
9023                 rect.bottom = Math.min(rect.bottom, parentView.getHeight());
9024             }
9025 
9026             if (!parentView.hasIdentityMatrix()) {
9027                 parentView.getMatrix().mapRect(rect);
9028             }
9029 
9030             rect.offset(parentView.mLeft, parentView.mTop);
9031 
9032             parent = parentView.mParent;
9033         }
9034 
9035         if (parent instanceof ViewRootImpl) {
9036             ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
9037             rect.offset(0, -viewRootImpl.mCurScrollY);
9038         }
9039     }
9040 
9041     /**
9042      * Return the class name of this object to be used for accessibility purposes.
9043      * Subclasses should only override this if they are implementing something that
9044      * should be seen as a completely new class of view when used by accessibility,
9045      * unrelated to the class it is deriving from.  This is used to fill in
9046      * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
9047      */
9048     public CharSequence getAccessibilityClassName() {
9049         return View.class.getName();
9050     }
9051 
9052     /**
9053      * Called when assist structure is being retrieved from a view as part of
9054      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
9055      * @param structure Fill in with structured view data.  The default implementation
9056      * fills in all data that can be inferred from the view itself.
9057      */
9058     public void onProvideStructure(ViewStructure structure) {
9059         onProvideStructure(structure, VIEW_STRUCTURE_FOR_ASSIST, /* flags= */ 0);
9060     }
9061 
9062     /**
9063      * Populates a {@link ViewStructure} to fullfil an autofill request.
9064      *
9065      * <p>The structure should contain at least the following properties:
9066      * <ul>
9067      *   <li>Autofill id ({@link ViewStructure#setAutofillId(AutofillId, int)}).
9068      *   <li>Autofill type ({@link ViewStructure#setAutofillType(int)}).
9069      *   <li>Autofill value ({@link ViewStructure#setAutofillValue(AutofillValue)}).
9070      *   <li>Whether the data is sensitive ({@link ViewStructure#setDataIsSensitive(boolean)}).
9071      * </ul>
9072      *
9073      * <p>It's also recommended to set the following properties - the more properties the structure
9074      * has, the higher the chances of an {@link android.service.autofill.AutofillService} properly
9075      * using the structure:
9076      *
9077      * <ul>
9078      *   <li>Autofill hints ({@link ViewStructure#setAutofillHints(String[])}).
9079      *   <li>Autofill options ({@link ViewStructure#setAutofillOptions(CharSequence[])}) when the
9080      *       view can only be filled with predefined values (typically used when the autofill type
9081      *       is {@link #AUTOFILL_TYPE_LIST}).
9082      *   <li>Resource id ({@link ViewStructure#setId(int, String, String, String)}).
9083      *   <li>Class name ({@link ViewStructure#setClassName(String)}).
9084      *   <li>Content description ({@link ViewStructure#setContentDescription(CharSequence)}).
9085      *   <li>Visual properties such as visibility ({@link ViewStructure#setVisibility(int)}),
9086      *       dimensions ({@link ViewStructure#setDimens(int, int, int, int, int, int)}), and
9087      *       opacity ({@link ViewStructure#setOpaque(boolean)}).
9088      *   <li>For views representing text fields, text properties such as the text itself
9089      *       ({@link ViewStructure#setText(CharSequence)}), text hints
9090      *       ({@link ViewStructure#setHint(CharSequence)}, input type
9091      *       ({@link ViewStructure#setInputType(int)}),
9092      *   <li>For views representing HTML nodes, its web domain
9093      *       ({@link ViewStructure#setWebDomain(String)}) and HTML properties
9094      *       (({@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}).
9095      * </ul>
9096      *
9097      * <p>The default implementation of this method already sets most of these properties based on
9098      * related {@link View} methods (for example, the autofill id is set using
9099      * {@link #getAutofillId()}, the autofill type set using {@link #getAutofillType()}, etc.),
9100      * and views in the standard Android widgets library also override it to set their
9101      * relevant properties (for example, {@link android.widget.TextView} already sets the text
9102      * properties), so it's recommended to only override this method
9103      * (and call {@code super.onProvideAutofillStructure()}) when:
9104      *
9105      * <ul>
9106      *   <li>The view contents does not include PII (Personally Identifiable Information), so it
9107      *       can call {@link ViewStructure#setDataIsSensitive(boolean)} passing {@code false}.
9108      *   <li>The view can only be autofilled with predefined options, so it can call
9109      *       {@link ViewStructure#setAutofillOptions(CharSequence[])}.
9110      * </ul>
9111      *
9112      * <p><b>Note:</b> The {@code left} and {@code top} values set in
9113      * {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the next
9114      * {@link ViewGroup#isImportantForAutofill()} predecessor view included in the structure.
9115      *
9116      * <p>Views support the Autofill Framework mainly by:
9117      * <ul>
9118      *   <li>Providing the metadata defining what the view means and how it can be autofilled.
9119      *   <li>Notifying the Android System when the view value changed by calling
9120      *       {@link AutofillManager#notifyValueChanged(View)}.
9121      *   <li>Implementing the methods that autofill the view.
9122      * </ul>
9123      * <p>This method is responsible for the former; {@link #autofill(AutofillValue)} is responsible
9124      * for the latter.
9125      *
9126      * @param structure fill in with structured view data for autofill purposes.
9127      * @param flags optional flags.
9128      *
9129      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
9130      */
9131     public void onProvideAutofillStructure(ViewStructure structure, @AutofillFlags int flags) {
9132         onProvideStructure(structure, VIEW_STRUCTURE_FOR_AUTOFILL, flags);
9133     }
9134 
9135     /**
9136      * Populates a {@link ViewStructure} for content capture.
9137      *
9138      * <p>This method is called after a view that is eligible for content capture
9139      * (for example, if it {@link #isImportantForContentCapture()}, an intelligence service is
9140      * enabled for the user, and the activity rendering the view is enabled for content capture)
9141      * is laid out and is visible. The populated structure is then passed to the service through
9142      * {@link ContentCaptureSession#notifyViewAppeared(ViewStructure)}.
9143      *
9144      * <p>The default implementation of this method sets the most relevant properties based on
9145      * related {@link View} methods, and views in the standard Android widgets library also
9146      * override it to set their relevant properties. Therefore, if overriding this method, it
9147      * is recommended to call {@code super.onProvideContentCaptureStructure()}.
9148      *
9149      * <p><b>Note: </b>views that manage a virtual structure under this view must populate just
9150      * the node representing this view and return right away, then asynchronously report (not
9151      * necessarily in the UI thread) when the children nodes appear, disappear or have their text
9152      * changed by calling
9153      * {@link ContentCaptureSession#notifyViewAppeared(ViewStructure)},
9154      * {@link ContentCaptureSession#notifyViewDisappeared(AutofillId)}, and
9155      * {@link ContentCaptureSession#notifyViewTextChanged(AutofillId, CharSequence)}
9156      * respectively. The structure for a child must be created using
9157      * {@link ContentCaptureSession#newVirtualViewStructure(AutofillId, long)}, and the
9158      * {@code autofillId} for a child can be obtained either through
9159      * {@code childStructure.getAutofillId()} or
9160      * {@link ContentCaptureSession#newAutofillId(AutofillId, long)}.
9161      *
9162      * <p>When the virtual view hierarchy represents a web page, you should also:
9163      *
9164      * <ul>
9165      *   <li>Call {@link ContentCaptureManager#getContentCaptureConditions()} to infer content
9166      *   capture events should be generate for that URL.
9167      *   <li>Create a new {@link ContentCaptureSession} child for every HTML element that
9168      *   renders a new URL (like an {@code IFRAME}) and use that session to notify events from
9169      *   that subtree.
9170      * </ul>
9171      *
9172      * <p><b>Note: </b>the following methods of the {@code structure} will be ignored:
9173      * <ul>
9174      *   <li>{@link ViewStructure#setChildCount(int)}
9175      *   <li>{@link ViewStructure#addChildCount(int)}
9176      *   <li>{@link ViewStructure#getChildCount()}
9177      *   <li>{@link ViewStructure#newChild(int)}
9178      *   <li>{@link ViewStructure#asyncNewChild(int)}
9179      *   <li>{@link ViewStructure#asyncCommit()}
9180      *   <li>{@link ViewStructure#setWebDomain(String)}
9181      *   <li>{@link ViewStructure#newHtmlInfoBuilder(String)}
9182      *   <li>{@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}
9183      *   <li>{@link ViewStructure#setDataIsSensitive(boolean)}
9184      *   <li>{@link ViewStructure#setAlpha(float)}
9185      *   <li>{@link ViewStructure#setElevation(float)}
9186      *   <li>{@link ViewStructure#setTransformation(Matrix)}
9187      *
9188      * </ul>
9189      */
9190     public void onProvideContentCaptureStructure(@NonNull ViewStructure structure, int flags) {
9191         onProvideStructure(structure, VIEW_STRUCTURE_FOR_CONTENT_CAPTURE, flags);
9192     }
9193 
9194     /** @hide */
9195     protected void onProvideStructure(@NonNull ViewStructure structure,
9196             @ViewStructureType int viewFor, int flags) {
9197         final int id = mID;
9198         if (id != NO_ID && !isViewIdGenerated(id)) {
9199             String pkg, type, entry;
9200             try {
9201                 final Resources res = getResources();
9202                 entry = res.getResourceEntryName(id);
9203                 type = res.getResourceTypeName(id);
9204                 pkg = res.getResourcePackageName(id);
9205             } catch (Resources.NotFoundException e) {
9206                 entry = type = pkg = null;
9207             }
9208             structure.setId(id, pkg, type, entry);
9209         } else {
9210             structure.setId(id, null, null, null);
9211         }
9212 
9213         if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
9214                 || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
9215             final @AutofillType int autofillType = getAutofillType();
9216             // Don't need to fill autofill info if view does not support it.
9217             // For example, only TextViews that are editable support autofill
9218             if (autofillType != AUTOFILL_TYPE_NONE) {
9219                 structure.setAutofillType(autofillType);
9220                 structure.setAutofillHints(getAutofillHints());
9221                 structure.setAutofillValue(getAutofillValue());
9222             }
9223             structure.setImportantForAutofill(getImportantForAutofill());
9224             structure.setReceiveContentMimeTypes(getReceiveContentMimeTypes());
9225         }
9226 
9227         int ignoredParentLeft = 0;
9228         int ignoredParentTop = 0;
9229         if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
9230                 && (flags & AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) {
9231             View parentGroup = null;
9232 
9233             ViewParent viewParent = getParent();
9234             if (viewParent instanceof View) {
9235                 parentGroup = (View) viewParent;
9236             }
9237 
9238             while (parentGroup != null && !parentGroup.isImportantForAutofill()) {
9239                 ignoredParentLeft += parentGroup.mLeft - parentGroup.mScrollX;
9240                 ignoredParentTop += parentGroup.mTop - parentGroup.mScrollY;
9241 
9242                 viewParent = parentGroup.getParent();
9243                 if (viewParent instanceof View) {
9244                     parentGroup = (View) viewParent;
9245                 } else {
9246                     break;
9247                 }
9248             }
9249         }
9250 
9251         structure.setDimens(ignoredParentLeft + mLeft, ignoredParentTop + mTop, mScrollX, mScrollY,
9252                 mRight - mLeft, mBottom - mTop);
9253         if (viewFor == VIEW_STRUCTURE_FOR_ASSIST) {
9254             if (!hasIdentityMatrix()) {
9255                 structure.setTransformation(getMatrix());
9256             }
9257             structure.setElevation(getZ());
9258         }
9259         structure.setVisibility(getVisibility());
9260         structure.setEnabled(isEnabled());
9261         if (isClickable()) {
9262             structure.setClickable(true);
9263         }
9264         if (isFocusable()) {
9265             structure.setFocusable(true);
9266         }
9267         if (isFocused()) {
9268             structure.setFocused(true);
9269         }
9270         if (isAccessibilityFocused()) {
9271             structure.setAccessibilityFocused(true);
9272         }
9273         if (isSelected()) {
9274             structure.setSelected(true);
9275         }
9276         if (isActivated()) {
9277             structure.setActivated(true);
9278         }
9279         if (isLongClickable()) {
9280             structure.setLongClickable(true);
9281         }
9282         if (this instanceof Checkable) {
9283             structure.setCheckable(true);
9284             if (((Checkable)this).isChecked()) {
9285                 structure.setChecked(true);
9286             }
9287         }
9288         if (isOpaque()) {
9289             structure.setOpaque(true);
9290         }
9291         if (isContextClickable()) {
9292             structure.setContextClickable(true);
9293         }
9294         structure.setClassName(getAccessibilityClassName().toString());
9295         structure.setContentDescription(getContentDescription());
9296     }
9297 
9298     /**
9299      * Called when assist structure is being retrieved from a view as part of
9300      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
9301      * generate additional virtual structure under this view.  The default implementation
9302      * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
9303      * view's virtual accessibility nodes, if any.  You can override this for a more
9304      * optimal implementation providing this data.
9305      */
9306     public void onProvideVirtualStructure(ViewStructure structure) {
9307         onProvideVirtualStructureCompat(structure, false);
9308     }
9309 
9310     /**
9311      * Fallback implementation to populate a ViewStructure from accessibility state.
9312      *
9313      * @param structure The structure to populate.
9314      * @param forAutofill Whether the structure is needed for autofill.
9315      */
9316     private void onProvideVirtualStructureCompat(ViewStructure structure, boolean forAutofill) {
9317         final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
9318         if (provider != null) {
9319             if (forAutofill && Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
9320                 Log.v(AUTOFILL_LOG_TAG, "onProvideVirtualStructureCompat() for " + this);
9321             }
9322             final AccessibilityNodeInfo info = createAccessibilityNodeInfo();
9323             structure.setChildCount(1);
9324             final ViewStructure root = structure.newChild(0);
9325             populateVirtualStructure(root, provider, info, forAutofill);
9326             info.recycle();
9327         }
9328     }
9329 
9330     /**
9331      * Populates a {@link ViewStructure} containing virtual children to fullfil an autofill
9332      * request.
9333      *
9334      * <p>This method should be used when the view manages a virtual structure under this view. For
9335      * example, a view that draws input fields using {@link #draw(Canvas)}.
9336      *
9337      * <p>When implementing this method, subclasses must follow the rules below:
9338      *
9339      * <ul>
9340      *   <li>Add virtual children by calling the {@link ViewStructure#newChild(int)} or
9341      *       {@link ViewStructure#asyncNewChild(int)} methods, where the {@code id} is an unique id
9342      *       identifying the children in the virtual structure.
9343      *   <li>The children hierarchy can have multiple levels if necessary, but ideally it should
9344      *       exclude intermediate levels that are irrelevant for autofill; that would improve the
9345      *       autofill performance.
9346      *   <li>Also implement {@link #autofill(SparseArray)} to autofill the virtual
9347      *       children.
9348      *   <li>Set the autofill properties of the child structure as defined by
9349      *       {@link #onProvideAutofillStructure(ViewStructure, int)}, using
9350      *       {@link ViewStructure#setAutofillId(AutofillId, int)} to set its autofill id.
9351      *   <li>Call {@link android.view.autofill.AutofillManager#notifyViewEntered(View, int, Rect)}
9352      *       and/or {@link android.view.autofill.AutofillManager#notifyViewExited(View, int)}
9353      *       when the focused virtual child changed.
9354      *   <li>Override {@link #isVisibleToUserForAutofill(int)} to allow the platform to query
9355      *       whether a given virtual view is visible to the user in order to support triggering
9356      *       save when all views of interest go away.
9357      *   <li>Call
9358      *    {@link android.view.autofill.AutofillManager#notifyValueChanged(View, int, AutofillValue)}
9359      *       when the value of a virtual child changed.
9360      *   <li>Call {@link
9361      *    android.view.autofill.AutofillManager#notifyViewVisibilityChanged(View, int, boolean)}
9362      *       when the visibility of a virtual child changed.
9363      *   <li>Call
9364      *    {@link android.view.autofill.AutofillManager#notifyViewClicked(View, int)} when a virtual
9365      *       child is clicked.
9366      *   <li>Call {@link AutofillManager#commit()} when the autofill context of the view structure
9367      *       changed and the current context should be committed (for example, when the user tapped
9368      *       a {@code SUBMIT} button in an HTML page).
9369      *   <li>Call {@link AutofillManager#cancel()} when the autofill context of the view structure
9370      *       changed and the current context should be canceled (for example, when the user tapped
9371      *       a {@code CANCEL} button in an HTML page).
9372      *   <li>Provide ways for users to manually request autofill by calling
9373      *       {@link AutofillManager#requestAutofill(View, int, Rect)}.
9374      *   <li>The {@code left} and {@code top} values set in
9375      *       {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the
9376      *       next {@link ViewGroup#isImportantForAutofill()} predecessor view included in the
9377      *       structure.
9378      * </ul>
9379      *
9380      * <p>Views with virtual children support the Autofill Framework mainly by:
9381      * <ul>
9382      *   <li>Providing the metadata defining what the virtual children mean and how they can be
9383      *       autofilled.
9384      *   <li>Implementing the methods that autofill the virtual children.
9385      * </ul>
9386      * <p>This method is responsible for the former; {@link #autofill(SparseArray)} is responsible
9387      * for the latter.
9388      *
9389      * @param structure fill in with virtual children data for autofill purposes.
9390      * @param flags optional flags.
9391      *
9392      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
9393      */
9394     public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
9395         if (mContext.isAutofillCompatibilityEnabled()) {
9396             onProvideVirtualStructureCompat(structure, true);
9397         }
9398     }
9399 
9400     /**
9401      * Sets the listener to be {@link #performReceiveContent used} to handle insertion of
9402      * content into this view.
9403      *
9404      * <p>Depending on the type of view, this listener may be invoked for different scenarios. For
9405      * example, for an editable {@link android.widget.TextView}, this listener will be invoked for
9406      * the following scenarios:
9407      * <ol>
9408      *     <li>Paste from the clipboard (e.g. "Paste" or "Paste as plain text" action in the
9409      *     insertion/selection menu)
9410      *     <li>Content insertion from the keyboard (from {@link InputConnection#commitContent})
9411      *     <li>Drag and drop (drop events from {@link #onDragEvent})
9412      *     <li>Autofill
9413      *     <li>Selection replacement via {@link Intent#ACTION_PROCESS_TEXT}
9414      * </ol>
9415      *
9416      * <p>When setting a listener, clients must also declare the accepted MIME types.
9417      * The listener will still be invoked even if the MIME type of the content is not one of the
9418      * declared MIME types (e.g. if the user pastes content whose type is not one of the declared
9419      * MIME types).
9420      * In that case, the listener may reject the content (defer to the default platform behavior)
9421      * or execute some other fallback logic (e.g. show an appropriate message to the user).
9422      * The declared MIME types serve as a hint to allow different features to optionally alter
9423      * their behavior. For example, a soft keyboard may optionally choose to hide its UI for
9424      * inserting GIFs for a particular input field if the MIME types set here for that field
9425      * don't include "image/gif" or "image/*".
9426      *
9427      * <p>Note: MIME type matching in the Android framework is case-sensitive, unlike formal RFC
9428      * MIME types. As a result, you should always write your MIME types with lowercase letters,
9429      * or use {@link android.content.Intent#normalizeMimeType} to ensure that it is converted to
9430      * lowercase.
9431      *
9432      * @param mimeTypes The MIME types accepted by the given listener. These may use patterns
9433      *                  such as "image/*", but may not start with a wildcard. This argument must
9434      *                  not be null or empty if a non-null listener is passed in.
9435      * @param listener The listener to use. This can be null to reset to the default behavior.
9436      */
9437     public void setOnReceiveContentListener(
9438             @SuppressLint("NullableCollection") @Nullable String[] mimeTypes,
9439             @Nullable OnReceiveContentListener listener) {
9440         if (listener != null) {
9441             Preconditions.checkArgument(mimeTypes != null && mimeTypes.length > 0,
9442                     "When the listener is set, MIME types must also be set");
9443         }
9444         if (mimeTypes != null) {
9445             Preconditions.checkArgument(Arrays.stream(mimeTypes).noneMatch(t -> t.startsWith("*")),
9446                     "A MIME type set here must not start with *: " + Arrays.toString(mimeTypes));
9447         }
9448         mReceiveContentMimeTypes = ArrayUtils.isEmpty(mimeTypes) ? null : mimeTypes;
9449         getListenerInfo().mOnReceiveContentListener = listener;
9450     }
9451 
9452     /**
9453      * Receives the given content. If no listener is set, invokes {@link #onReceiveContent}. If a
9454      * listener is {@link #setOnReceiveContentListener set}, invokes the listener instead; if the
9455      * listener returns a non-null result, invokes {@link #onReceiveContent} to handle it.
9456      *
9457      * @param payload The content to insert and related metadata.
9458      *
9459      * @return The portion of the passed-in content that was not accepted (may be all, some, or none
9460      * of the passed-in content).
9461      */
9462     @Nullable
performReceiveContent(@onNull ContentInfo payload)9463     public ContentInfo performReceiveContent(@NonNull ContentInfo payload) {
9464         final OnReceiveContentListener listener = (mListenerInfo == null) ? null
9465                 : getListenerInfo().mOnReceiveContentListener;
9466         if (listener != null) {
9467             final ContentInfo remaining = listener.onReceiveContent(this, payload);
9468             return (remaining == null) ? null : onReceiveContent(remaining);
9469         }
9470         return onReceiveContent(payload);
9471     }
9472 
9473     /**
9474      * Implements the default behavior for receiving content for this type of view. The default
9475      * view implementation is a no-op (returns the passed-in content without acting on it).
9476      *
9477      * <p>Widgets should override this method to define their default behavior for receiving
9478      * content. Apps should {@link #setOnReceiveContentListener set a listener} to provide
9479      * app-specific handling for receiving content.
9480      *
9481      * <p>See {@link #setOnReceiveContentListener} and {@link #performReceiveContent} for more info.
9482      *
9483      * @param payload The content to insert and related metadata.
9484      *
9485      * @return The portion of the passed-in content that was not handled (may be all, some, or none
9486      * of the passed-in content).
9487      */
9488     @Nullable
onReceiveContent(@onNull ContentInfo payload)9489     public ContentInfo onReceiveContent(@NonNull ContentInfo payload) {
9490         return payload;
9491     }
9492 
9493     /**
9494      * Returns the MIME types accepted by {@link #performReceiveContent} for this view, as
9495      * configured via {@link #setOnReceiveContentListener}. By default returns null.
9496      *
9497      * <p>Different features (e.g. pasting from the clipboard, inserting stickers from the soft
9498      * keyboard, etc) may optionally use this metadata to conditionally alter their behavior. For
9499      * example, a soft keyboard may choose to hide its UI for inserting GIFs for a particular
9500      * input field if the MIME types returned here for that field don't include "image/gif" or
9501      * "image/*".
9502      *
9503      * <p>Note: Comparisons of MIME types should be performed using utilities such as
9504      * {@link ClipDescription#compareMimeTypes} rather than simple string equality, in order to
9505      * correctly handle patterns such as "text/*", "image/*", etc. Note that MIME type matching
9506      * in the Android framework is case-sensitive, unlike formal RFC MIME types. As a result,
9507      * you should always write your MIME types with lowercase letters, or use
9508      * {@link android.content.Intent#normalizeMimeType} to ensure that it is converted to
9509      * lowercase.
9510      *
9511      * @return The MIME types accepted by {@link #performReceiveContent} for this view (may
9512      * include patterns such as "image/*").
9513      */
9514     @SuppressLint("NullableCollection")
9515     @Nullable
getReceiveContentMimeTypes()9516     public String[] getReceiveContentMimeTypes() {
9517         return mReceiveContentMimeTypes;
9518     }
9519 
9520     /**
9521      * Automatically fills the content of this view with the {@code value}.
9522      *
9523      * <p>Views support the Autofill Framework mainly by:
9524      * <ul>
9525      *   <li>Providing the metadata defining what the view means and how it can be autofilled.
9526      *   <li>Implementing the methods that autofill the view.
9527      * </ul>
9528      * <p>{@link #onProvideAutofillStructure(ViewStructure, int)} is responsible for the former,
9529      * this method is responsible for latter.
9530      *
9531      * <p>This method does nothing by default, but when overridden it typically:
9532      * <ol>
9533      *   <li>Checks if the provided value matches the expected type (which is defined by
9534      *       {@link #getAutofillType()}).
9535      *   <li>Checks if the view is editable - if it isn't, it should return right away.
9536      *   <li>Call the proper getter method on {@link AutofillValue} to fetch the actual value.
9537      *   <li>Pass the actual value to the equivalent setter in the view.
9538      * </ol>
9539      *
9540      * <p>For example, a text-field view could implement the method this way:
9541      *
9542      * <pre class="prettyprint">
9543      * &#64;Override
9544      * public void autofill(AutofillValue value) {
9545      *   if (!value.isText() || !this.isEditable()) {
9546      *      return;
9547      *   }
9548      *   CharSequence text = value.getTextValue();
9549      *   if (text != null) {
9550      *     this.setText(text);
9551      *   }
9552      * }
9553      * </pre>
9554      *
9555      * <p>If the value is updated asynchronously, the next call to
9556      * {@link AutofillManager#notifyValueChanged(View)} must happen <b>after</b> the value was
9557      * changed to the autofilled value. If not, the view will not be considered autofilled.
9558      *
9559      * <p><b>Note:</b> After this method is called, the value returned by
9560      * {@link #getAutofillValue()} must be equal to the {@code value} passed to it, otherwise the
9561      * view will not be highlighted as autofilled.
9562      *
9563      * @param value value to be autofilled.
9564      */
autofill(@uppressWarningsR) AutofillValue value)9565     public void autofill(@SuppressWarnings("unused") AutofillValue value) {
9566     }
9567 
9568     /**
9569      * Automatically fills the content of the virtual children within this view.
9570      *
9571      * <p>Views with virtual children support the Autofill Framework mainly by:
9572      * <ul>
9573      *   <li>Providing the metadata defining what the virtual children mean and how they can be
9574      *       autofilled.
9575      *   <li>Implementing the methods that autofill the virtual children.
9576      * </ul>
9577      * <p>{@link #onProvideAutofillVirtualStructure(ViewStructure, int)} is responsible for the
9578      * former, this method is responsible for the latter - see {@link #autofill(AutofillValue)} and
9579      * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} for more info about autofill.
9580      *
9581      * <p>If a child value is updated asynchronously, the next call to
9582      * {@link AutofillManager#notifyValueChanged(View, int, AutofillValue)} must happen
9583      * <b>after</b> the value was changed to the autofilled value. If not, the child will not be
9584      * considered autofilled.
9585      *
9586      * <p><b>Note:</b> To indicate that a virtual view was autofilled,
9587      * <code>?android:attr/autofilledHighlight</code> should be drawn over it until the data
9588      * changes.
9589      *
9590      * @param values map of values to be autofilled, keyed by virtual child id.
9591      *
9592      * @attr ref android.R.styleable#Theme_autofilledHighlight
9593      */
autofill(@onNull @uppressWarningsR) SparseArray<AutofillValue> values)9594     public void autofill(@NonNull @SuppressWarnings("unused") SparseArray<AutofillValue> values) {
9595         if (!mContext.isAutofillCompatibilityEnabled()) {
9596             return;
9597         }
9598         final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
9599         if (provider == null) {
9600             return;
9601         }
9602         final int valueCount = values.size();
9603         for (int i = 0; i < valueCount; i++) {
9604             final AutofillValue value = values.valueAt(i);
9605             if (value.isText()) {
9606                 final int virtualId = values.keyAt(i);
9607                 final CharSequence text = value.getTextValue();
9608                 final Bundle arguments = new Bundle();
9609                 arguments.putCharSequence(
9610                         AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text);
9611                 provider.performAction(virtualId, AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
9612             }
9613         }
9614     }
9615 
9616     /**
9617      * Gets the unique, logical identifier of this view in the activity, for autofill purposes.
9618      *
9619      * <p>The autofill id is created on demand, unless it is explicitly set by
9620      * {@link #setAutofillId(AutofillId)}.
9621      *
9622      * <p>See {@link #setAutofillId(AutofillId)} for more info.
9623      *
9624      * @return The View's autofill id.
9625      */
getAutofillId()9626     public final AutofillId getAutofillId() {
9627         if (mAutofillId == null) {
9628             // The autofill id needs to be unique, but its value doesn't matter,
9629             // so it's better to reuse the accessibility id to save space.
9630             mAutofillId = new AutofillId(getAutofillViewId());
9631         }
9632         return mAutofillId;
9633     }
9634 
9635     /**
9636      * Sets the unique, logical identifier of this view in the activity, for autofill purposes.
9637      *
9638      * <p>The autofill id is created on demand, and this method should only be called when a view is
9639      * reused after {@link #dispatchProvideAutofillStructure(ViewStructure, int)} is called, as
9640      * that method creates a snapshot of the view that is passed along to the autofill service.
9641      *
9642      * <p>This method is typically used when view subtrees are recycled to represent different
9643      * content* &mdash;in this case, the autofill id can be saved before the view content is swapped
9644      * out, and restored later when it's swapped back in. For example:
9645      *
9646      * <pre>
9647      * EditText reusableView = ...;
9648      * ViewGroup parentView = ...;
9649      * AutofillManager afm = ...;
9650      *
9651      * // Swap out the view and change its contents
9652      * AutofillId oldId = reusableView.getAutofillId();
9653      * CharSequence oldText = reusableView.getText();
9654      * parentView.removeView(reusableView);
9655      * AutofillId newId = afm.getNextAutofillId();
9656      * reusableView.setText("New I am");
9657      * reusableView.setAutofillId(newId);
9658      * parentView.addView(reusableView);
9659      *
9660      * // Later, swap the old content back in
9661      * parentView.removeView(reusableView);
9662      * reusableView.setAutofillId(oldId);
9663      * reusableView.setText(oldText);
9664      * parentView.addView(reusableView);
9665      * </pre>
9666      *
9667      * <p>NOTE: If this view is a descendant of an {@link android.widget.AdapterView}, the system
9668      * may reset its autofill id when this view is recycled. If the autofill ids need to be stable,
9669      * they should be set again in
9670      * {@link android.widget.Adapter#getView(int, android.view.View, android.view.ViewGroup)}.
9671      *
9672      * @param id an autofill ID that is unique in the {@link android.app.Activity} hosting the view,
9673      * or {@code null} to reset it. Usually it's an id previously allocated to another view (and
9674      * obtained through {@link #getAutofillId()}), or a new value obtained through
9675      * {@link AutofillManager#getNextAutofillId()}.
9676      *
9677      * @throws IllegalStateException if the view is already {@link #isAttachedToWindow() attached to
9678      * a window}.
9679      *
9680      * @throws IllegalArgumentException if the id is an autofill id associated with a virtual view.
9681      */
setAutofillId(@ullable AutofillId id)9682     public void setAutofillId(@Nullable AutofillId id) {
9683         // TODO(b/37566627): add unit / CTS test for all possible combinations below
9684         if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
9685             Log.v(AUTOFILL_LOG_TAG, "setAutofill(): from " + mAutofillId + " to " + id);
9686         }
9687         if (isAttachedToWindow()) {
9688             throw new IllegalStateException("Cannot set autofill id when view is attached");
9689         }
9690         if (id != null && !id.isNonVirtual()) {
9691             throw new IllegalStateException("Cannot set autofill id assigned to virtual views");
9692         }
9693         if (id == null && (mPrivateFlags3 & PFLAG3_AUTOFILLID_EXPLICITLY_SET) == 0) {
9694             // Ignore reset because it was never explicitly set before.
9695             return;
9696         }
9697         mAutofillId = id;
9698         if (id != null) {
9699             mAutofillViewId = id.getViewId();
9700             mPrivateFlags3 |= PFLAG3_AUTOFILLID_EXPLICITLY_SET;
9701         } else {
9702             mAutofillViewId = NO_ID;
9703             mPrivateFlags3 &= ~PFLAG3_AUTOFILLID_EXPLICITLY_SET;
9704         }
9705     }
9706 
9707     /**
9708      * Forces a reset of the autofill ids of the subtree rooted at this view. Like calling
9709      * {@link #setAutofillId(AutofillId) setAutofillId(null)} for each view, but works even if the
9710      * views are attached to a window.
9711      *
9712      * <p>This is useful if the views are being recycled, since an autofill id should uniquely
9713      * identify a particular piece of content.
9714      *
9715      * @hide
9716      */
resetSubtreeAutofillIds()9717     public void resetSubtreeAutofillIds() {
9718         if (mAutofillViewId == NO_ID) {
9719             return;
9720         }
9721         if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
9722             Log.v(CONTENT_CAPTURE_LOG_TAG, "resetAutofillId() for " + mAutofillViewId);
9723         } else if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
9724             Log.v(AUTOFILL_LOG_TAG, "resetAutofillId() for " + mAutofillViewId);
9725         }
9726         mAutofillId = null;
9727         mAutofillViewId = NO_ID;
9728         mPrivateFlags3 &= ~PFLAG3_AUTOFILLID_EXPLICITLY_SET;
9729     }
9730 
9731     /**
9732      * Describes the autofill type of this view, so an
9733      * {@link android.service.autofill.AutofillService} can create the proper {@link AutofillValue}
9734      * when autofilling the view.
9735      *
9736      * <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it to properly
9737      * support the Autofill Framework.
9738      *
9739      * @return either {@link #AUTOFILL_TYPE_NONE}, {@link #AUTOFILL_TYPE_TEXT},
9740      * {@link #AUTOFILL_TYPE_LIST}, {@link #AUTOFILL_TYPE_DATE}, or {@link #AUTOFILL_TYPE_TOGGLE}.
9741      *
9742      * @see #onProvideAutofillStructure(ViewStructure, int)
9743      * @see #autofill(AutofillValue)
9744      */
getAutofillType()9745     public @AutofillType int getAutofillType() {
9746         return AUTOFILL_TYPE_NONE;
9747     }
9748 
9749     /**
9750      * Gets the hints that help an {@link android.service.autofill.AutofillService} determine how
9751      * to autofill the view with the user's data.
9752      *
9753      * <p>See {@link #setAutofillHints(String...)} for more info about these hints.
9754      *
9755      * @return The hints set via the attribute or {@link #setAutofillHints(String...)}, or
9756      * {@code null} if no hints were set.
9757      *
9758      * @attr ref android.R.styleable#View_autofillHints
9759      */
9760     @ViewDebug.ExportedProperty()
9761     @InspectableProperty
getAutofillHints()9762     @Nullable public String[] getAutofillHints() {
9763         return mAutofillHints;
9764     }
9765 
9766     /**
9767      * @hide
9768      */
9769     @TestApi
isAutofilled()9770     public boolean isAutofilled() {
9771         return (mPrivateFlags3 & PFLAG3_IS_AUTOFILLED) != 0;
9772     }
9773 
9774     /**
9775      * @hide
9776      */
hideAutofillHighlight()9777     public boolean hideAutofillHighlight() {
9778         return (mPrivateFlags4 & PFLAG4_AUTOFILL_HIDE_HIGHLIGHT) != 0;
9779     }
9780 
9781     /**
9782      * Gets the {@link View}'s current autofill value.
9783      *
9784      * <p>By default returns {@code null}, but subclasses should override it and return an
9785      * appropriate value to properly support the Autofill Framework.
9786      *
9787      * @see #onProvideAutofillStructure(ViewStructure, int)
9788      * @see #autofill(AutofillValue)
9789      */
9790     @Nullable
getAutofillValue()9791     public AutofillValue getAutofillValue() {
9792         return null;
9793     }
9794 
9795     /**
9796      * Gets the mode for determining whether this view is important for autofill.
9797      *
9798      * <p>See {@link #setImportantForAutofill(int)} and {@link #isImportantForAutofill()} for more
9799      * info about this mode.
9800      *
9801      * @return {@link #IMPORTANT_FOR_AUTOFILL_AUTO} by default, or value passed to
9802      * {@link #setImportantForAutofill(int)}.
9803      *
9804      * @attr ref android.R.styleable#View_importantForAutofill
9805      */
9806     @ViewDebug.ExportedProperty(mapping = {
9807             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_AUTO, to = "auto"),
9808             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES, to = "yes"),
9809             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO, to = "no"),
9810             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
9811                 to = "yesExcludeDescendants"),
9812             @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
9813                 to = "noExcludeDescendants")})
9814     @InspectableProperty(enumMapping = {
9815             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_AUTO, name = "auto"),
9816             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_YES, name = "yes"),
9817             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_NO, name = "no"),
9818             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
9819                     name = "yesExcludeDescendants"),
9820             @EnumEntry(value = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
9821                     name = "noExcludeDescendants"),
9822     })
getImportantForAutofill()9823     public @AutofillImportance int getImportantForAutofill() {
9824         return (mPrivateFlags3
9825                 & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK) >> PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
9826     }
9827 
9828     /**
9829      * Sets the mode for determining whether this view is considered important for autofill.
9830      *
9831      * <p>The platform determines the importance for autofill automatically but you
9832      * can use this method to customize the behavior. For example:
9833      *
9834      * <ol>
9835      *   <li>When the view contents is irrelevant for autofill (for example, a text field used in a
9836      *       "Captcha" challenge), it should be {@link #IMPORTANT_FOR_AUTOFILL_NO}.
9837      *   <li>When both the view and its children are irrelevant for autofill (for example, the root
9838      *       view of an activity containing a spreadhseet editor), it should be
9839      *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
9840      *   <li>When the view content is relevant for autofill but its children aren't (for example,
9841      *       a credit card expiration date represented by a custom view that overrides the proper
9842      *       autofill methods and has 2 children representing the month and year), it should
9843      *       be {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}.
9844      * </ol>
9845      *
9846      * <p><b>Note:</b> Setting the mode as {@link #IMPORTANT_FOR_AUTOFILL_NO} or
9847      * {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS} does not guarantee the view (and its
9848      * children) will not be used for autofill purpose; for example, when the user explicitly
9849      * makes an autofill request, all views are included in the ViewStructure, and starting in
9850      * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} the system uses other factors along
9851      * with importance to determine the autofill behavior. See {@link #isImportantForAutofill()}
9852      * for more details about how the View's importance for autofill is used.
9853      *
9854      * @param mode {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, {@link #IMPORTANT_FOR_AUTOFILL_YES},
9855      * {@link #IMPORTANT_FOR_AUTOFILL_NO}, {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS},
9856      * or {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
9857      *
9858      * @attr ref android.R.styleable#View_importantForAutofill
9859      */
setImportantForAutofill(@utofillImportance int mode)9860     public void setImportantForAutofill(@AutofillImportance int mode) {
9861         mPrivateFlags3 &= ~PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
9862         mPrivateFlags3 |= (mode << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT)
9863                 & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
9864     }
9865 
9866     /**
9867      * Hints the Android System whether the {@link android.app.assist.AssistStructure.ViewNode}
9868      * associated with this view is considered important for autofill purposes.
9869      *
9870      * <p>Generally speaking, a view is important for autofill if:
9871      * <ol>
9872      * <li>The view can be autofilled by an {@link android.service.autofill.AutofillService}.
9873      * <li>The view contents can help an {@link android.service.autofill.AutofillService}
9874      *     determine how other views can be autofilled.
9875      * <ol>
9876      *
9877      * <p>For example, view containers should typically return {@code false} for performance reasons
9878      * (since the important info is provided by their children), but if its properties have relevant
9879      * information (for example, a resource id called {@code credentials}, it should return
9880      * {@code true}. On the other hand, views representing labels or editable fields should
9881      * typically return {@code true}, but in some cases they could return {@code false}
9882      * (for example, if they're part of a "Captcha" mechanism).
9883      *
9884      * <p>The value returned by this method depends on the value returned by
9885      * {@link #getImportantForAutofill()}:
9886      *
9887      * <ol>
9888      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_YES} or
9889      *       {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}, then it returns {@code true}
9890      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_NO} or
9891      *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}, then it returns {@code false}
9892      *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, then it uses some simple heuristics
9893      *       that can return {@code true} in some cases (like a container with a resource id),
9894      *       but {@code false} in most.
9895      *   <li>otherwise, it returns {@code false}.
9896      * </ol>
9897      *
9898      * <p> The behavior of importances depends on Android version:
9899      * <ol>
9900      *   <li>For {@link android.os.Build.VERSION_CODES#TIRAMISU} and below:
9901      *     <ol>
9902      *       <li>When a view is considered important for autofill:
9903      *          <ol>
9904      *            <li>The view might automatically trigger an autofill request when focused on.
9905      *            <li>The contents of the view are included in the {@link ViewStructure} used in an
9906      *                autofill request.
9907      *          </ol>
9908      *        <li>On the other hand, when a view is considered not important for autofill:
9909      *          <ol>
9910      *            <li>The view never automatically triggers autofill requests, but it can trigger a
9911      *                manual request through {@link AutofillManager#requestAutofill(View)}.
9912      *            <li>The contents of the view are not included in the {@link ViewStructure} used in
9913      *                an autofill request, unless the request has the
9914      *                {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag.
9915      *          </ol>
9916      *      </ol>
9917      *  <li>For {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} and above:
9918      *    <ol>
9919      *      <li>The system uses importance, along with other view properties and other optimization
9920      *          factors, to determine if a view should trigger autofill on focus.
9921      *      <li>The contents of {@link #IMPORTANT_FOR_AUTOFILL_AUTO},
9922      *        {@link #IMPORTANT_FOR_AUTOFILL_YES}, {@link #IMPORTANT_FOR_AUTOFILL_NO},
9923      *        {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}, and
9924      *        {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS} views will be included in the
9925      *        {@link ViewStructure} used in an autofill request.
9926      *    </ol>
9927      * </ol>
9928      *
9929      * @return whether the view is considered important for autofill.
9930      *
9931      * @see #setImportantForAutofill(int)
9932      * @see #IMPORTANT_FOR_AUTOFILL_AUTO
9933      * @see #IMPORTANT_FOR_AUTOFILL_YES
9934      * @see #IMPORTANT_FOR_AUTOFILL_NO
9935      * @see #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
9936      * @see #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
9937      * @see AutofillManager#requestAutofill(View)
9938      */
isImportantForAutofill()9939     public final boolean isImportantForAutofill() {
9940         // Check parent mode to ensure we're not hidden.
9941         ViewParent parent = mParent;
9942         while (parent instanceof View) {
9943             final int parentImportance = ((View) parent).getImportantForAutofill();
9944             if (parentImportance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
9945                     || parentImportance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS) {
9946                 if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
9947                     Log.v(AUTOFILL_LOG_TAG, "View (" +  this + ") is not important for autofill "
9948                             + "because parent " + parent + "'s importance is " + parentImportance);
9949                 }
9950                 return false;
9951             }
9952             parent = parent.getParent();
9953         }
9954 
9955         final int importance = getImportantForAutofill();
9956 
9957         // First, check the explicit states.
9958         if (importance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
9959                 || importance == IMPORTANT_FOR_AUTOFILL_YES) {
9960             return true;
9961         }
9962         if (importance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
9963                 || importance == IMPORTANT_FOR_AUTOFILL_NO) {
9964             if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
9965                 Log.v(AUTOFILL_LOG_TAG, "View (" +  this + ") is not important for autofill "
9966                         + "because its importance is " + importance);
9967             }
9968             return false;
9969         }
9970 
9971         // Then use some heuristics to handle AUTO.
9972         if (importance != IMPORTANT_FOR_AUTOFILL_AUTO) {
9973             Log.w(AUTOFILL_LOG_TAG, "invalid autofill importance (" + importance + " on view "
9974                     + this);
9975             return false;
9976         }
9977 
9978         // Always include views that have an explicit resource id.
9979         final int id = mID;
9980         if (id != NO_ID && !isViewIdGenerated(id)) {
9981             final Resources res = getResources();
9982             String entry = null;
9983             String pkg = null;
9984             try {
9985                 entry = res.getResourceEntryName(id);
9986                 pkg = res.getResourcePackageName(id);
9987             } catch (Resources.NotFoundException e) {
9988                 // ignore
9989             }
9990             if (entry != null && pkg != null && pkg.equals(mContext.getPackageName())) {
9991                 return true;
9992             }
9993         }
9994 
9995         // If the app developer explicitly set hints for it, it's important.
9996         if (getAutofillHints() != null) {
9997             return true;
9998         }
9999 
10000         // Otherwise, assume it's not important...
10001         return false;
10002     }
10003 
10004     /**
10005      * Gets the mode for determining whether this view is important for content capture.
10006      *
10007      * <p>See {@link #setImportantForContentCapture(int)} and
10008      * {@link #isImportantForContentCapture()} for more info about this mode.
10009      *
10010      * @return {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO} by default, or value passed to
10011      * {@link #setImportantForContentCapture(int)}.
10012      *
10013      * @attr ref android.R.styleable#View_importantForContentCapture
10014      */
10015     @ViewDebug.ExportedProperty(mapping = {
10016             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_AUTO, to = "auto"),
10017             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_YES, to = "yes"),
10018             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_NO, to = "no"),
10019             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
10020                 to = "yesExcludeDescendants"),
10021             @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS,
10022                 to = "noExcludeDescendants")})
10023     @InspectableProperty(enumMapping = {
10024             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_AUTO, name = "auto"),
10025             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_YES, name = "yes"),
10026             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_NO, name = "no"),
10027             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
10028                     name = "yesExcludeDescendants"),
10029             @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS,
10030                     name = "noExcludeDescendants"),
10031     })
getImportantForContentCapture()10032     public @ContentCaptureImportance int getImportantForContentCapture() {
10033         // NOTE: the important for content capture values were the first flags added and are set in
10034         // the rightmost position, so we don't need to shift them
10035         return mPrivateFlags4 & PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK;
10036     }
10037 
10038     /**
10039      * Sets the mode for determining whether this view is considered important for content capture.
10040      *
10041      * <p>The platform determines the importance for autofill automatically but you
10042      * can use this method to customize the behavior. Typically, a view that provides text should
10043      * be marked as {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES}.
10044      *
10045      * @param mode {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO},
10046      * {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES}, {@link #IMPORTANT_FOR_CONTENT_CAPTURE_NO},
10047      * {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS},
10048      * or {@link #IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS}.
10049      *
10050      * @attr ref android.R.styleable#View_importantForContentCapture
10051      */
setImportantForContentCapture(@ontentCaptureImportance int mode)10052     public void setImportantForContentCapture(@ContentCaptureImportance int mode) {
10053         // Reset first
10054         mPrivateFlags4 &= ~PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK;
10055         // Then set again
10056         // NOTE: the important for content capture values were the first flags added and are set in
10057         // the rightmost position, so we don't need to shift them
10058         mPrivateFlags4 |= (mode & PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK);
10059     }
10060 
10061     /**
10062      * Hints the Android System whether this view is considered important for content capture, based
10063      * on the value explicitly set by {@link #setImportantForContentCapture(int)} and heuristics
10064      * when it's {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO}.
10065      *
10066      * <p>See {@link ContentCaptureManager} for more info about content capture.
10067      *
10068      * @return whether the view is considered important for content capture.
10069      *
10070      * @see #setImportantForContentCapture(int)
10071      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO
10072      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_YES
10073      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_NO
10074      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
10075      * @see #IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
10076      */
isImportantForContentCapture()10077     public final boolean isImportantForContentCapture() {
10078         boolean isImportant;
10079         if ((mPrivateFlags4 & PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED) != 0) {
10080             isImportant = (mPrivateFlags4 & PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE) != 0;
10081             return isImportant;
10082         }
10083 
10084         isImportant = calculateIsImportantForContentCapture();
10085 
10086         mPrivateFlags4 &= ~PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
10087         if (isImportant) {
10088             mPrivateFlags4 |= PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
10089         }
10090         mPrivateFlags4 |= PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED;
10091         return isImportant;
10092     }
10093 
10094     /**
10095      * Calculates whether the flag is important for content capture so it can be used by
10096      * {@link #isImportantForContentCapture()} while the tree is traversed.
10097      */
calculateIsImportantForContentCapture()10098     private boolean calculateIsImportantForContentCapture() {
10099         // Check parent mode to ensure we're important
10100         ViewParent parent = mParent;
10101         while (parent instanceof View) {
10102             final int parentImportance = ((View) parent).getImportantForContentCapture();
10103             if (parentImportance == IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
10104                     || parentImportance == IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS) {
10105                 if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
10106                     Log.v(CONTENT_CAPTURE_LOG_TAG, "View (" +  this + ") is not important for "
10107                             + "content capture because parent " + parent + "'s importance is "
10108                             + parentImportance);
10109                 }
10110                 return false;
10111             }
10112             parent = parent.getParent();
10113         }
10114 
10115         final int importance = getImportantForContentCapture();
10116 
10117         // First, check the explicit states.
10118         if (importance == IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
10119                 || importance == IMPORTANT_FOR_CONTENT_CAPTURE_YES) {
10120             return true;
10121         }
10122         if (importance == IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
10123                 || importance == IMPORTANT_FOR_CONTENT_CAPTURE_NO) {
10124             if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
10125                 Log.v(CONTENT_CAPTURE_LOG_TAG, "View (" +  this + ") is not important for content "
10126                         + "capture because its importance is " + importance);
10127             }
10128             return false;
10129         }
10130 
10131         // Then use some heuristics to handle AUTO.
10132         if (importance != IMPORTANT_FOR_CONTENT_CAPTURE_AUTO) {
10133             Log.w(CONTENT_CAPTURE_LOG_TAG, "invalid content capture importance (" + importance
10134                     + " on view " + this);
10135             return false;
10136         }
10137 
10138         // View group is important if at least one children also is
10139         if (this instanceof ViewGroup) {
10140             final ViewGroup group = (ViewGroup) this;
10141             for (int i = 0; i < group.getChildCount(); i++) {
10142                 final View child = group.getChildAt(i);
10143                 if (child.isImportantForContentCapture()) {
10144                     return true;
10145                 }
10146             }
10147         }
10148 
10149         // If the app developer explicitly set hints or autofill hintsfor it, it's important.
10150         if (getAutofillHints() != null) {
10151             return true;
10152         }
10153 
10154         // Otherwise, assume it's not important...
10155         return false;
10156     }
10157 
10158     /**
10159      * Helper used to notify the {@link ContentCaptureManager} when the view is removed or
10160      * added, based on whether it's laid out and visible, and without knowing if the parent removed
10161      * it from the view hierarchy.
10162      *
10163      * <p>This method is called from many places (visibility changed, view laid out, view attached
10164      * or detached to/from window, etc...) and hence must contain the logic to call the manager, as
10165      * described below:
10166      *
10167      * <ol>
10168      *   <li>It should only be called when content capture is enabled for the view.
10169      *   <li>It must call viewAppeared() before viewDisappeared()
10170      *   <li>viewAppeared() can only be called when the view is visible and laid out
10171      *   <li>It should not call the same event twice.
10172      * </ol>
10173      */
notifyAppearedOrDisappearedForContentCaptureIfNeeded(boolean appeared)10174     private void notifyAppearedOrDisappearedForContentCaptureIfNeeded(boolean appeared) {
10175         AttachInfo ai = mAttachInfo;
10176         // Skip it while the view is being laid out for the first time
10177         if (ai != null && !ai.mReadyForContentCaptureUpdates) return;
10178 
10179         // First check if context has client, so it saves a service lookup when it doesn't
10180         if (mContext.getContentCaptureOptions() == null) return;
10181 
10182         if (appeared) {
10183             // The appeared event stops sending to AiAi.
10184             // 1. The view is hidden.
10185             // 2. The same event was sent.
10186             // 3. The view is not laid out, and it will be laid out in the future.
10187             //    Some recycled views cached its layout and a relayout is unnecessary. In this case,
10188             // system still needs to notify content capture the view appeared. When a view is
10189             // recycled, it will set the flag PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED.
10190             final boolean isRecycledWithoutRelayout = getNotifiedContentCaptureDisappeared()
10191                     && getVisibility() == VISIBLE
10192                     && !isLayoutRequested();
10193             if (getVisibility() != VISIBLE || getNotifiedContentCaptureAppeared()
10194                     || !(isLaidOut() || isRecycledWithoutRelayout)) {
10195                 if (DEBUG_CONTENT_CAPTURE) {
10196                     Log.v(CONTENT_CAPTURE_LOG_TAG, "Ignoring 'appeared' on " + this + ": laid="
10197                             + isLaidOut() + ", visibleToUser=" + isVisibleToUser()
10198                             + ", visible=" + (getVisibility() == VISIBLE)
10199                             + ": alreadyNotifiedAppeared=" + getNotifiedContentCaptureAppeared()
10200                             + ", alreadyNotifiedDisappeared="
10201                             + getNotifiedContentCaptureDisappeared());
10202                 }
10203                 return;
10204             }
10205         } else {
10206             if (!getNotifiedContentCaptureAppeared() || getNotifiedContentCaptureDisappeared()) {
10207                 if (DEBUG_CONTENT_CAPTURE) {
10208                     Log.v(CONTENT_CAPTURE_LOG_TAG, "Ignoring 'disappeared' on " + this + ": laid="
10209                             + isLaidOut() + ", visibleToUser=" + isVisibleToUser()
10210                             + ", visible=" + (getVisibility() == VISIBLE)
10211                             + ": alreadyNotifiedAppeared=" + getNotifiedContentCaptureAppeared()
10212                             + ", alreadyNotifiedDisappeared="
10213                             + getNotifiedContentCaptureDisappeared());
10214                 }
10215                 return;
10216             }
10217         }
10218 
10219         ContentCaptureSession session = getContentCaptureSession();
10220         if (session == null) return;
10221 
10222         // ... and finally at the view level
10223         // NOTE: isImportantForContentCapture() is more expensive than cm.isContentCaptureEnabled()
10224         if (!isImportantForContentCapture()) return;
10225 
10226         if (appeared) {
10227             setNotifiedContentCaptureAppeared();
10228 
10229             if (ai != null) {
10230                 makeParentImportantAndNotifyAppearedEventIfNeed();
10231                 ai.delayNotifyContentCaptureEvent(session, this, appeared);
10232             } else {
10233                 if (DEBUG_CONTENT_CAPTURE) {
10234                     Log.w(CONTENT_CAPTURE_LOG_TAG, "no AttachInfo on appeared for " + this);
10235                 }
10236             }
10237         } else {
10238             mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED;
10239             mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED;
10240 
10241             if (ai != null) {
10242                 ai.delayNotifyContentCaptureEvent(session, this, appeared);
10243             } else {
10244                 if (DEBUG_CONTENT_CAPTURE) {
10245                     Log.v(CONTENT_CAPTURE_LOG_TAG, "no AttachInfo on disappeared for " + this);
10246                 }
10247             }
10248 
10249             // We reset any translation state as views may be re-used (e.g., as in ListView and
10250             // RecyclerView). We only need to do this for views important for content capture since
10251             // views unimportant for content capture won't be translated anyway.
10252             if (!isTemporarilyDetached()) {
10253                 clearTranslationState();
10254             }
10255         }
10256     }
10257 
makeParentImportantAndNotifyAppearedEventIfNeed()10258     private void makeParentImportantAndNotifyAppearedEventIfNeed() {
10259         // If view sent the appeared event to Content Capture, Content Capture also
10260         // would like to receive its parents' appeared events. So checks its parents
10261         // whether the appeared event is sent or not. If not, send the appeared event.
10262         final ViewParent parent = getParent();
10263         if (parent instanceof View) {
10264             View p = ((View) parent);
10265             if (p.getNotifiedContentCaptureAppeared()) {
10266                 return;
10267             }
10268             // Set important for content capture in the cache.
10269             p.mPrivateFlags4 |= PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK;
10270             p.notifyAppearedOrDisappearedForContentCaptureIfNeeded(/* appeared */ true);
10271         }
10272     }
10273 
setNotifiedContentCaptureAppeared()10274     private void setNotifiedContentCaptureAppeared() {
10275         mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED;
10276         mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED;
10277     }
10278 
10279     /** @hide */
getNotifiedContentCaptureAppeared()10280     protected boolean getNotifiedContentCaptureAppeared() {
10281         return (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) != 0;
10282     }
10283 
10284 
getNotifiedContentCaptureDisappeared()10285     private boolean getNotifiedContentCaptureDisappeared() {
10286         return (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED) != 0;
10287     }
10288 
10289     /**
10290      * Sets the (optional) {@link ContentCaptureSession} associated with this view.
10291      *
10292      * <p>This method should be called when you need to associate a {@link ContentCaptureContext} to
10293      * the content capture events associated with this view or its view hierarchy (if it's a
10294      * {@link ViewGroup}).
10295      *
10296      * <p>For example, if your activity is associated with a web domain, first you would need to
10297      * set the context for the main DOM:
10298      *
10299      * <pre>
10300      *   ContentCaptureSession mainSession = rootView.getContentCaptureSession();
10301      *   mainSession.setContentCaptureContext(ContentCaptureContext.forLocusId(Uri.parse(myUrl));
10302      * </pre>
10303      *
10304      * <p>Then if the page had an {@code IFRAME}, you would create a new session for it:
10305      *
10306      * <pre>
10307      *   ContentCaptureSession iframeSession = mainSession.createContentCaptureSession(
10308      *       ContentCaptureContext.forLocusId(Uri.parse(iframeUrl)));
10309      *   iframeView.setContentCaptureSession(iframeSession);
10310      * </pre>
10311      *
10312      * @param contentCaptureSession a session created by
10313      * {@link ContentCaptureSession#createContentCaptureSession(
10314      *        android.view.contentcapture.ContentCaptureContext)}.
10315      */
setContentCaptureSession(@ullable ContentCaptureSession contentCaptureSession)10316     public void setContentCaptureSession(@Nullable ContentCaptureSession contentCaptureSession) {
10317         mContentCaptureSession = contentCaptureSession;
10318     }
10319 
10320     /**
10321      * Gets the session used to notify content capture events.
10322      *
10323      * @return session explicitly set by {@link #setContentCaptureSession(ContentCaptureSession)},
10324      * inherited by ancestors, default session or {@code null} if content capture is disabled for
10325      * this view.
10326      */
10327     @Nullable
getContentCaptureSession()10328     public final ContentCaptureSession getContentCaptureSession() {
10329         if (mContentCaptureSessionCached) {
10330             return mContentCaptureSession;
10331         }
10332 
10333         mContentCaptureSession = getAndCacheContentCaptureSession();
10334         mContentCaptureSessionCached = true;
10335         return mContentCaptureSession;
10336     }
10337 
10338     @Nullable
getAndCacheContentCaptureSession()10339     private ContentCaptureSession getAndCacheContentCaptureSession() {
10340         // First try the session explicitly set by setContentCaptureSession()
10341         if (mContentCaptureSession != null) {
10342             return mContentCaptureSession;
10343         }
10344 
10345         // Then the session explicitly set in an ancestor
10346         ContentCaptureSession session = null;
10347         if (mParent instanceof View) {
10348             session = ((View) mParent).getContentCaptureSession();
10349         }
10350 
10351         // Finally, if no session was explicitly set, use the context's default session.
10352         if (session == null) {
10353             final ContentCaptureManager ccm = mContext
10354                     .getSystemService(ContentCaptureManager.class);
10355             return ccm == null ? null : ccm.getMainContentCaptureSession();
10356         }
10357         return session;
10358     }
10359 
10360     @Nullable
getAutofillManager()10361     private AutofillManager getAutofillManager() {
10362         return mContext.getSystemService(AutofillManager.class);
10363     }
10364 
10365     /**
10366      * Check whether current activity / package is in autofill denylist.
10367      *
10368      * Called by viewGroup#populateChildrenForAutofill() to determine whether to include view in
10369      * assist structure
10370      */
isActivityDeniedForAutofillForUnimportantView()10371     final boolean isActivityDeniedForAutofillForUnimportantView() {
10372         final AutofillManager afm = getAutofillManager();
10373         if (afm == null) return false;
10374         return afm.isActivityDeniedForAutofill();
10375     }
10376 
10377     /**
10378      * Check whether current view matches autofillable heuristics
10379      *
10380      * Called by viewGroup#populateChildrenForAutofill() to determine whether to include view in
10381      * assist structure
10382      */
isMatchingAutofillableHeuristics()10383     final boolean isMatchingAutofillableHeuristics() {
10384         final AutofillManager afm = getAutofillManager();
10385         if (afm == null) return false;
10386         // check the flag to see if trigger fill request on not important views is enabled
10387         return afm.isTriggerFillRequestOnUnimportantViewEnabled()
10388             ? afm.isAutofillable(this) : false;
10389     }
10390 
isAutofillable()10391     private boolean isAutofillable() {
10392         if (getAutofillType() == AUTOFILL_TYPE_NONE) return false;
10393 
10394         final AutofillManager afm = getAutofillManager();
10395         if (afm == null) {
10396             return false;
10397         }
10398 
10399         // Check whether view is not part of an activity. If it's not, return false.
10400         if (getAutofillViewId() <= LAST_APP_AUTOFILL_ID) {
10401             return false;
10402         }
10403 
10404         // If view is important and filter important view flag is turned on, or view is not
10405         // important and trigger fill request on not important view flag is turned on, then use
10406         // AutofillManager.isAutofillable() to decide whether view is autofillable instead.
10407         if ((isImportantForAutofill() && afm.isTriggerFillRequestOnFilteredImportantViewsEnabled())
10408                 || (!isImportantForAutofill()
10409                     && afm.isTriggerFillRequestOnUnimportantViewEnabled())) {
10410             return afm.isAutofillable(this) ? true : notifyAugmentedAutofillIfNeeded(afm);
10411         }
10412 
10413         // If the previous condition is not met, fall back to the previous way to trigger fill
10414         // request based on autofill importance instead.
10415         return isImportantForAutofill() ? true : notifyAugmentedAutofillIfNeeded(afm);
10416     }
10417 
notifyAugmentedAutofillIfNeeded(AutofillManager afm)10418     private boolean notifyAugmentedAutofillIfNeeded(AutofillManager afm) {
10419         final AutofillOptions options = mContext.getAutofillOptions();
10420         if (options == null || !options.isAugmentedAutofillEnabled(mContext)) {
10421             return false;
10422         }
10423         afm.notifyViewEnteredForAugmentedAutofill(this);
10424         return true;
10425     }
10426 
10427     /** @hide */
canNotifyAutofillEnterExitEvent()10428     public boolean canNotifyAutofillEnterExitEvent() {
10429         return isAutofillable() && isAttachedToWindow();
10430     }
10431 
populateVirtualStructure(ViewStructure structure, AccessibilityNodeProvider provider, AccessibilityNodeInfo info, boolean forAutofill)10432     private void populateVirtualStructure(ViewStructure structure,
10433             AccessibilityNodeProvider provider, AccessibilityNodeInfo info,
10434             boolean forAutofill) {
10435         structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
10436                 null, null, info.getViewIdResourceName());
10437         Rect rect = structure.getTempRect();
10438         info.getBoundsInParent(rect);
10439         structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
10440         structure.setVisibility(VISIBLE);
10441         structure.setEnabled(info.isEnabled());
10442         if (info.isClickable()) {
10443             structure.setClickable(true);
10444         }
10445         if (info.isFocusable()) {
10446             structure.setFocusable(true);
10447         }
10448         if (info.isFocused()) {
10449             structure.setFocused(true);
10450         }
10451         if (info.isAccessibilityFocused()) {
10452             structure.setAccessibilityFocused(true);
10453         }
10454         if (info.isSelected()) {
10455             structure.setSelected(true);
10456         }
10457         if (info.isLongClickable()) {
10458             structure.setLongClickable(true);
10459         }
10460         if (info.isCheckable()) {
10461             structure.setCheckable(true);
10462             if (info.isChecked()) {
10463                 structure.setChecked(true);
10464             }
10465         }
10466         if (info.isContextClickable()) {
10467             structure.setContextClickable(true);
10468         }
10469         if (forAutofill) {
10470             structure.setAutofillId(new AutofillId(getAutofillId(),
10471                     AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId())));
10472         }
10473         CharSequence cname = info.getClassName();
10474         structure.setClassName(cname != null ? cname.toString() : null);
10475         structure.setContentDescription(info.getContentDescription());
10476         if (forAutofill) {
10477             final int maxTextLength = info.getMaxTextLength();
10478             if (maxTextLength != -1) {
10479                 structure.setMaxTextLength(maxTextLength);
10480             }
10481             structure.setHint(info.getHintText());
10482         }
10483         CharSequence text = info.getText();
10484         boolean hasText = text != null || info.getError() != null;
10485         if (hasText) {
10486             structure.setText(text, info.getTextSelectionStart(), info.getTextSelectionEnd());
10487         }
10488         if (forAutofill) {
10489             if (info.isEditable()) {
10490                 structure.setDataIsSensitive(true);
10491                 if (hasText) {
10492                     structure.setAutofillType(AUTOFILL_TYPE_TEXT);
10493                     structure.setAutofillValue(AutofillValue.forText(text));
10494                 }
10495                 int inputType = info.getInputType();
10496                 if (inputType == 0 && info.isPassword()) {
10497                     inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD;
10498                 }
10499                 structure.setInputType(inputType);
10500             } else {
10501                 structure.setDataIsSensitive(false);
10502             }
10503         }
10504         final int NCHILDREN = info.getChildCount();
10505         if (NCHILDREN > 0) {
10506             structure.setChildCount(NCHILDREN);
10507             for (int i=0; i<NCHILDREN; i++) {
10508                 if (AccessibilityNodeInfo.getVirtualDescendantId(info.getChildNodeIds().get(i))
10509                         == AccessibilityNodeProvider.HOST_VIEW_ID) {
10510                     Log.e(VIEW_LOG_TAG, "Virtual view pointing to its host. Ignoring");
10511                     continue;
10512                 }
10513                 AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
10514                         AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
10515                 if (cinfo != null) {
10516                     ViewStructure child = structure.newChild(i);
10517                     populateVirtualStructure(child, provider, cinfo, forAutofill);
10518                     cinfo.recycle();
10519                 }
10520             }
10521         }
10522     }
10523 
10524     /**
10525      * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
10526      * implementation calls {@link #onProvideStructure} and
10527      * {@link #onProvideVirtualStructure}.
10528      */
dispatchProvideStructure(ViewStructure structure)10529     public void dispatchProvideStructure(ViewStructure structure) {
10530         dispatchProvideStructure(structure, VIEW_STRUCTURE_FOR_ASSIST, /* flags= */ 0);
10531     }
10532 
10533     /**
10534      * Dispatches creation of a {@link ViewStructure}s for autofill purposes down the hierarchy,
10535      * when an Assist structure is being created as part of an autofill request.
10536      *
10537      * <p>The default implementation does the following:
10538      * <ul>
10539      *   <li>Sets the {@link AutofillId} in the structure.
10540      *   <li>Calls {@link #onProvideAutofillStructure(ViewStructure, int)}.
10541      *   <li>Calls {@link #onProvideAutofillVirtualStructure(ViewStructure, int)}.
10542      * </ul>
10543      *
10544      * <p>Typically, this method should only be overridden by subclasses that provide a view
10545      * hierarchy (such as {@link ViewGroup}) - other classes should override
10546      * {@link #onProvideAutofillStructure(ViewStructure, int)} or
10547      * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} instead.
10548      *
10549      * <p>When overridden, it must:
10550      *
10551      * <ul>
10552      *   <li>Either call
10553      *       {@code super.dispatchProvideAutofillStructure(structure, flags)} or explicitly
10554      *       set the {@link AutofillId} in the structure (for example, by calling
10555      *       {@code structure.setAutofillId(getAutofillId())}).
10556      *   <li>Decide how to handle the {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag - when
10557      *       set, all views in the structure should be considered important for autofill,
10558      *       regardless of what {@link #isImportantForAutofill()} returns. We encourage you to
10559      *       respect this flag to provide a better user experience - this flag is typically used
10560      *       when an user explicitly requested autofill. If the flag is not set,
10561      *       then only views marked as important for autofill should be included in the
10562      *       structure - skipping non-important views optimizes the overall autofill performance.
10563      * </ul>
10564      *
10565      * @param structure fill in with structured view data for autofill purposes.
10566      * @param flags optional flags.
10567      *
10568      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
10569      */
dispatchProvideAutofillStructure(@onNull ViewStructure structure, @AutofillFlags int flags)10570     public void dispatchProvideAutofillStructure(@NonNull ViewStructure structure,
10571             @AutofillFlags int flags) {
10572         dispatchProvideStructure(structure, VIEW_STRUCTURE_FOR_AUTOFILL, flags);
10573     }
10574 
dispatchProvideStructure(@onNull ViewStructure structure, @ViewStructureType int viewFor, @AutofillFlags int flags)10575     private void dispatchProvideStructure(@NonNull ViewStructure structure,
10576             @ViewStructureType int viewFor, @AutofillFlags int flags) {
10577         if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
10578             structure.setAutofillId(getAutofillId());
10579             onProvideAutofillStructure(structure, flags);
10580             onProvideAutofillVirtualStructure(structure, flags);
10581         } else if (!isAssistBlocked()) {
10582             onProvideStructure(structure);
10583             onProvideVirtualStructure(structure);
10584         } else {
10585             structure.setClassName(getAccessibilityClassName().toString());
10586             structure.setAssistBlocked(true);
10587         }
10588     }
10589 
10590     /**
10591      * Dispatches the initial content capture events for a view structure.
10592      *
10593      * @hide
10594      */
dispatchInitialProvideContentCaptureStructure()10595     public void dispatchInitialProvideContentCaptureStructure() {
10596         AttachInfo ai = mAttachInfo;
10597         if (ai == null) {
10598             Log.w(CONTENT_CAPTURE_LOG_TAG,
10599                     "dispatchProvideContentCaptureStructure(): no AttachInfo for " + this);
10600             return;
10601         }
10602         ContentCaptureManager ccm = ai.mContentCaptureManager;
10603         if (ccm == null) {
10604             Log.w(CONTENT_CAPTURE_LOG_TAG, "dispatchProvideContentCaptureStructure(): "
10605                     + "no ContentCaptureManager for " + this);
10606             return;
10607         }
10608 
10609         // We must set it before checkign if the view itself is important, because it might
10610         // initially not be (for example, if it's empty), although that might change later (for
10611         // example, if important views are added)
10612         ai.mReadyForContentCaptureUpdates = true;
10613 
10614         if (!isImportantForContentCapture()) {
10615             if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.DEBUG)) {
10616                 Log.d(CONTENT_CAPTURE_LOG_TAG,
10617                         "dispatchProvideContentCaptureStructure(): decorView is not important");
10618             }
10619             return;
10620         }
10621 
10622         ai.mContentCaptureManager = ccm;
10623 
10624         ContentCaptureSession session = getContentCaptureSession();
10625         if (session == null) {
10626             if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.DEBUG)) {
10627                 Log.d(CONTENT_CAPTURE_LOG_TAG,
10628                         "dispatchProvideContentCaptureStructure(): no session for " + this);
10629             }
10630             return;
10631         }
10632 
10633         session.internalNotifyViewTreeEvent(/* started= */ true);
10634         try {
10635             dispatchProvideContentCaptureStructure();
10636         } finally {
10637             session.internalNotifyViewTreeEvent(/* started= */ false);
10638         }
10639     }
10640 
10641     /** @hide */
dispatchProvideContentCaptureStructure()10642     void dispatchProvideContentCaptureStructure() {
10643         ContentCaptureSession session = getContentCaptureSession();
10644         if (session != null) {
10645             ViewStructure structure = session.newViewStructure(this);
10646             onProvideContentCaptureStructure(structure, /* flags= */ 0);
10647             setNotifiedContentCaptureAppeared();
10648             session.notifyViewAppeared(structure);
10649         }
10650     }
10651 
10652     /**
10653      * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
10654      *
10655      * Note: Called from the default {@link AccessibilityDelegate}.
10656      *
10657      * @hide
10658      */
onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info)10659     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
10660         if (mAttachInfo == null) {
10661             return;
10662         }
10663 
10664         Rect bounds = mAttachInfo.mTmpInvalRect;
10665 
10666         getDrawingRect(bounds);
10667         info.setBoundsInParent(bounds);
10668 
10669         getBoundsOnScreen(bounds, true);
10670         info.setBoundsInScreen(bounds);
10671         getBoundsInWindow(bounds, true);
10672         info.setBoundsInWindow(bounds);
10673 
10674         ViewParent parent = getParentForAccessibility();
10675         if (parent instanceof View) {
10676             info.setParent((View) parent);
10677         }
10678 
10679         if (mID != View.NO_ID) {
10680             View rootView = getRootView();
10681             if (rootView == null) {
10682                 rootView = this;
10683             }
10684 
10685             View label = rootView.findLabelForView(this, mID);
10686             if (label != null) {
10687                 info.setLabeledBy(label);
10688             }
10689 
10690             if ((mAttachInfo.mAccessibilityFetchFlags
10691                     & AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS) != 0
10692                     && Resources.resourceHasPackage(mID)) {
10693                 try {
10694                     String viewId = getResources().getResourceName(mID);
10695                     info.setViewIdResourceName(viewId);
10696                 } catch (Resources.NotFoundException nfe) {
10697                     /* ignore */
10698                 }
10699             }
10700         }
10701 
10702         if (mLabelForId != View.NO_ID) {
10703             View rootView = getRootView();
10704             if (rootView == null) {
10705                 rootView = this;
10706             }
10707             View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
10708             if (labeled != null) {
10709                 info.setLabelFor(labeled);
10710             }
10711         }
10712 
10713         if (mAccessibilityTraversalBeforeId != View.NO_ID) {
10714             View rootView = getRootView();
10715             if (rootView == null) {
10716                 rootView = this;
10717             }
10718             View next = rootView.findViewInsideOutShouldExist(this,
10719                     mAccessibilityTraversalBeforeId);
10720             if (next != null && next.includeForAccessibility()) {
10721                 info.setTraversalBefore(next);
10722             }
10723         }
10724 
10725         if (mAccessibilityTraversalAfterId != View.NO_ID) {
10726             View rootView = getRootView();
10727             if (rootView == null) {
10728                 rootView = this;
10729             }
10730             View next = rootView.findViewInsideOutShouldExist(this,
10731                     mAccessibilityTraversalAfterId);
10732             if (next != null && next.includeForAccessibility()) {
10733                 info.setTraversalAfter(next);
10734             }
10735         }
10736 
10737         info.setVisibleToUser(isVisibleToUser());
10738 
10739         info.setImportantForAccessibility(isImportantForAccessibility());
10740         info.setAccessibilityDataSensitive(isAccessibilityDataSensitive());
10741         info.setPackageName(mContext.getPackageName());
10742         info.setClassName(getAccessibilityClassName());
10743         info.setStateDescription(getStateDescription());
10744         info.setContentDescription(getContentDescription());
10745 
10746         info.setEnabled(isEnabled());
10747         info.setClickable(isClickable());
10748         info.setFocusable(isFocusable());
10749         info.setScreenReaderFocusable(isScreenReaderFocusable());
10750         info.setFocused(isFocused());
10751         info.setAccessibilityFocused(isAccessibilityFocused());
10752         info.setSelected(isSelected());
10753         info.setLongClickable(isLongClickable());
10754         info.setContextClickable(isContextClickable());
10755         info.setLiveRegion(getAccessibilityLiveRegion());
10756         if ((mTooltipInfo != null) && (mTooltipInfo.mTooltipText != null)) {
10757             info.setTooltipText(mTooltipInfo.mTooltipText);
10758             info.addAction((mTooltipInfo.mTooltipPopup == null)
10759                     ? AccessibilityNodeInfo.AccessibilityAction.ACTION_SHOW_TOOLTIP
10760                     : AccessibilityNodeInfo.AccessibilityAction.ACTION_HIDE_TOOLTIP);
10761         }
10762 
10763         // TODO: These make sense only if we are in an AdapterView but all
10764         // views can be selected. Maybe from accessibility perspective
10765         // we should report as selectable view in an AdapterView.
10766         info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
10767         info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
10768 
10769         if (isFocusable()) {
10770             if (isFocused()) {
10771                 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
10772             } else {
10773                 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
10774             }
10775         }
10776 
10777         if (!isAccessibilityFocused()) {
10778             info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
10779         } else {
10780             info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
10781         }
10782 
10783         if (isClickable() && isEnabled()) {
10784             info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
10785         }
10786 
10787         if (isLongClickable() && isEnabled()) {
10788             info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
10789         }
10790 
10791         if (isContextClickable() && isEnabled()) {
10792             info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
10793         }
10794 
10795         CharSequence text = getIterableTextForAccessibility();
10796         if (text != null && text.length() > 0) {
10797             info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
10798 
10799             info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
10800             info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
10801             info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
10802             info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
10803                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
10804                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
10805         }
10806 
10807         info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
10808         populateAccessibilityNodeInfoDrawingOrderInParent(info);
10809         info.setPaneTitle(mAccessibilityPaneTitle);
10810         info.setHeading(isAccessibilityHeading());
10811 
10812         if (mTouchDelegate != null) {
10813             info.setTouchDelegateInfo(mTouchDelegate.getTouchDelegateInfo());
10814         }
10815 
10816         if (startedSystemDragForAccessibility()) {
10817             info.addAction(AccessibilityAction.ACTION_DRAG_CANCEL);
10818         }
10819 
10820         if (canAcceptAccessibilityDrop()) {
10821             info.addAction(AccessibilityAction.ACTION_DRAG_DROP);
10822         }
10823     }
10824 
10825 
10826     /**
10827      * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
10828      * additional data.
10829      * <p>
10830      * This method only needs overloading if the node is marked as having extra data available.
10831      * </p>
10832      *
10833      * @param info The info to which to add the extra data. Never {@code null}.
10834      * @param extraDataKey A key specifying the type of extra data to add to the info. The
10835      *                     extra data should be added to the {@link Bundle} returned by
10836      *                     the info's {@link AccessibilityNodeInfo#getExtras} method. Never
10837      *                     {@code null}.
10838      * @param arguments A {@link Bundle} holding any arguments relevant for this request. May be
10839      *                  {@code null} if the service provided no arguments.
10840      *
10841      * @see AccessibilityNodeInfo#setAvailableExtraData(List)
10842      */
addExtraDataToAccessibilityNodeInfo( @onNull AccessibilityNodeInfo info, @NonNull String extraDataKey, @Nullable Bundle arguments)10843     public void addExtraDataToAccessibilityNodeInfo(
10844             @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
10845             @Nullable Bundle arguments) {
10846     }
10847 
10848     /**
10849      * Determine the order in which this view will be drawn relative to its siblings for a11y
10850      *
10851      * @param info The info whose drawing order should be populated
10852      */
populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info)10853     private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
10854         /*
10855          * If the view's bounds haven't been set yet, layout has not completed. In that situation,
10856          * drawing order may not be well-defined, and some Views with custom drawing order may
10857          * not be initialized sufficiently to respond properly getChildDrawingOrder.
10858          */
10859         if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
10860             info.setDrawingOrder(0);
10861             return;
10862         }
10863         int drawingOrderInParent = 1;
10864         // Iterate up the hierarchy if parents are not important for a11y
10865         View viewAtDrawingLevel = this;
10866         final ViewParent parent = getParentForAccessibility();
10867         while (viewAtDrawingLevel != parent) {
10868             final ViewParent currentParent = viewAtDrawingLevel.getParent();
10869             if (!(currentParent instanceof ViewGroup)) {
10870                 // Should only happen for the Decor
10871                 drawingOrderInParent = 0;
10872                 break;
10873             } else {
10874                 final ViewGroup parentGroup = (ViewGroup) currentParent;
10875                 final int childCount = parentGroup.getChildCount();
10876                 if (childCount > 1) {
10877                     List<View> preorderedList = parentGroup.buildOrderedChildList();
10878                     if (preorderedList != null) {
10879                         final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
10880                         for (int i = 0; i < childDrawIndex; i++) {
10881                             drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
10882                         }
10883                         preorderedList.clear();
10884                     } else {
10885                         final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
10886                         final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
10887                         final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
10888                                 .getChildDrawingOrder(childCount, childIndex) : childIndex;
10889                         final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
10890                         if (childDrawIndex != 0) {
10891                             for (int i = 0; i < numChildrenToIterate; i++) {
10892                                 final int otherDrawIndex = (customOrder ?
10893                                         parentGroup.getChildDrawingOrder(childCount, i) : i);
10894                                 if (otherDrawIndex < childDrawIndex) {
10895                                     drawingOrderInParent +=
10896                                             numViewsForAccessibility(parentGroup.getChildAt(i));
10897                                 }
10898                             }
10899                         }
10900                     }
10901                 }
10902             }
10903             viewAtDrawingLevel = (View) currentParent;
10904         }
10905         info.setDrawingOrder(drawingOrderInParent);
10906     }
10907 
numViewsForAccessibility(View view)10908     private static int numViewsForAccessibility(View view) {
10909         if (view != null) {
10910             if (view.includeForAccessibility()) {
10911                 return 1;
10912             } else if (view instanceof ViewGroup) {
10913                 return ((ViewGroup) view).getNumChildrenForAccessibility();
10914             }
10915         }
10916         return 0;
10917     }
10918 
findLabelForView(View view, int labeledId)10919     private View findLabelForView(View view, int labeledId) {
10920         if (mMatchLabelForPredicate == null) {
10921             mMatchLabelForPredicate = new MatchLabelForPredicate();
10922         }
10923         mMatchLabelForPredicate.mLabeledId = labeledId;
10924         return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
10925     }
10926 
10927     /**
10928      * Computes whether this virtual autofill view is visible to the user.
10929      *
10930      * <p><b>Note: </b>By default it returns {@code true}, but views providing a virtual hierarchy
10931      * view must override it.
10932      *
10933      * @return Whether the view is visible on the screen.
10934      */
isVisibleToUserForAutofill(int virtualId)10935     public boolean isVisibleToUserForAutofill(int virtualId) {
10936         if (mContext.isAutofillCompatibilityEnabled()) {
10937             final AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
10938             if (provider != null) {
10939                 final AccessibilityNodeInfo node = provider.createAccessibilityNodeInfo(virtualId);
10940                 if (node != null) {
10941                     return node.isVisibleToUser();
10942                 }
10943                 // if node is null, assume it's not visible anymore
10944             } else {
10945                 Log.w(VIEW_LOG_TAG, "isVisibleToUserForAutofill(" + virtualId + "): no provider");
10946             }
10947             return false;
10948         }
10949         return true;
10950     }
10951 
10952     /**
10953      * Computes whether this view is visible to the user. Such a view is
10954      * attached, visible, all its predecessors are visible, it is not clipped
10955      * entirely by its predecessors, and has an alpha greater than zero.
10956      *
10957      * @return Whether the view is visible on the screen.
10958      *
10959      * @hide
10960      */
10961     @UnsupportedAppUsage
isVisibleToUser()10962     public boolean isVisibleToUser() {
10963         return isVisibleToUser(null);
10964     }
10965 
10966     /**
10967      * Computes whether the given portion of this view is visible to the user.
10968      * Such a view is attached, visible, all its predecessors are visible,
10969      * has an alpha greater than zero, and the specified portion is not
10970      * clipped entirely by its predecessors.
10971      *
10972      * @param boundInView the portion of the view to test; coordinates should be relative; may be
10973      *                    <code>null</code>, and the entire view will be tested in this case.
10974      *                    When <code>true</code> is returned by the function, the actual visible
10975      *                    region will be stored in this parameter; that is, if boundInView is fully
10976      *                    contained within the view, no modification will be made, otherwise regions
10977      *                    outside of the visible area of the view will be clipped.
10978      *
10979      * @return Whether the specified portion of the view is visible on the screen.
10980      *
10981      * @hide
10982      */
10983     @UnsupportedAppUsage(trackingBug = 171933273)
isVisibleToUser(Rect boundInView)10984     protected boolean isVisibleToUser(Rect boundInView) {
10985         if (mAttachInfo != null) {
10986             // Attached to invisible window means this view is not visible.
10987             if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
10988                 return false;
10989             }
10990             // An invisible predecessor or one with alpha zero means
10991             // that this view is not visible to the user.
10992             Object current = this;
10993             while (current instanceof View) {
10994                 View view = (View) current;
10995                 // We have attach info so this view is attached and there is no
10996                 // need to check whether we reach to ViewRootImpl on the way up.
10997                 if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
10998                         view.getVisibility() != VISIBLE) {
10999                     return false;
11000                 }
11001                 current = view.mParent;
11002             }
11003             // Check if the view is entirely covered by its predecessors.
11004             Rect visibleRect = mAttachInfo.mTmpInvalRect;
11005             Point offset = mAttachInfo.mPoint;
11006             if (!getGlobalVisibleRect(visibleRect, offset)) {
11007                 return false;
11008             }
11009             // Check if the visible portion intersects the rectangle of interest.
11010             if (boundInView != null) {
11011                 visibleRect.offset(-offset.x, -offset.y);
11012                 return boundInView.intersect(visibleRect);
11013             }
11014             return true;
11015         }
11016         return false;
11017     }
11018 
11019     /**
11020      * Returns the delegate for implementing accessibility support via
11021      * composition. For more details see {@link AccessibilityDelegate}.
11022      *
11023      * @return The delegate, or null if none set.
11024      */
getAccessibilityDelegate()11025     public AccessibilityDelegate getAccessibilityDelegate() {
11026         return mAccessibilityDelegate;
11027     }
11028 
11029     /**
11030      * Sets a delegate for implementing accessibility support via composition
11031      * (as opposed to inheritance). For more details, see
11032      * {@link AccessibilityDelegate}.
11033      * <p>
11034      * <strong>Note:</strong> On platform versions prior to
11035      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
11036      * views in the {@code android.widget.*} package are called <i>before</i>
11037      * host methods. This prevents certain properties such as class name from
11038      * being modified by overriding
11039      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
11040      * as any changes will be overwritten by the host class.
11041      * <p>
11042      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
11043      * methods are called <i>after</i> host methods, which all properties to be
11044      * modified without being overwritten by the host class.
11045      *
11046      * @param delegate the object to which accessibility method calls should be
11047      *                 delegated
11048      * @see AccessibilityDelegate
11049      */
setAccessibilityDelegate(@ullable AccessibilityDelegate delegate)11050     public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
11051         mAccessibilityDelegate = delegate;
11052     }
11053 
11054     /**
11055      * Gets the provider for managing a virtual view hierarchy rooted at this View
11056      * and reported to {@link android.accessibilityservice.AccessibilityService}s
11057      * that explore the window content.
11058      * <p>
11059      * If this method returns an instance, this instance is responsible for managing
11060      * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
11061      * View including the one representing the View itself. Similarly the returned
11062      * instance is responsible for performing accessibility actions on any virtual
11063      * view or the root view itself.
11064      * </p>
11065      * <p>
11066      * If an {@link AccessibilityDelegate} has been specified via calling
11067      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
11068      * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
11069      * is responsible for handling this call.
11070      * </p>
11071      *
11072      * @return The provider.
11073      *
11074      * @see AccessibilityNodeProvider
11075      */
getAccessibilityNodeProvider()11076     public AccessibilityNodeProvider getAccessibilityNodeProvider() {
11077         if (mAccessibilityDelegate != null) {
11078             return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
11079         } else {
11080             return null;
11081         }
11082     }
11083 
11084     /**
11085      * Gets the unique identifier of this view on the screen for accessibility purposes.
11086      *
11087      * @return The view accessibility id.
11088      *
11089      * @hide
11090      */
11091     @UnsupportedAppUsage
getAccessibilityViewId()11092     public int getAccessibilityViewId() {
11093         if (mAccessibilityViewId == NO_ID) {
11094             mAccessibilityViewId = sNextAccessibilityViewId++;
11095         }
11096         return mAccessibilityViewId;
11097     }
11098 
11099     /**
11100      * Gets the unique identifier of this view on the screen for autofill purposes.
11101      *
11102      * @return The view autofill id.
11103      *
11104      * @hide
11105      */
getAutofillViewId()11106     public int getAutofillViewId() {
11107         if (mAutofillViewId == NO_ID) {
11108             mAutofillViewId = mContext.getNextAutofillId();
11109         }
11110         return mAutofillViewId;
11111     }
11112 
11113     /**
11114      * Gets the unique identifier of the window in which this View resides.
11115      *
11116      * @return The window accessibility id.
11117      *
11118      * @hide
11119      */
getAccessibilityWindowId()11120     public int getAccessibilityWindowId() {
11121         return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
11122                 : AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
11123     }
11124 
11125     /**
11126      * Returns the {@link View}'s state description.
11127      * <p>
11128      * <strong>Note:</strong> Do not override this method, as it will have no
11129      * effect on the state description presented to accessibility services.
11130      * You must call {@link #setStateDescription(CharSequence)} to modify the
11131      * state description.
11132      *
11133      * @return the state description
11134      * @see #setStateDescription(CharSequence)
11135      */
11136     @ViewDebug.ExportedProperty(category = "accessibility")
getStateDescription()11137     public final @Nullable CharSequence getStateDescription() {
11138         return mStateDescription;
11139     }
11140 
11141     /**
11142      * Returns the {@link View}'s content description.
11143      * <p>
11144      * <strong>Note:</strong> Do not override this method, as it will have no
11145      * effect on the content description presented to accessibility services.
11146      * You must call {@link #setContentDescription(CharSequence)} to modify the
11147      * content description.
11148      *
11149      * @return the content description
11150      * @see #setContentDescription(CharSequence)
11151      * @attr ref android.R.styleable#View_contentDescription
11152      */
11153     @ViewDebug.ExportedProperty(category = "accessibility")
11154     @InspectableProperty
getContentDescription()11155     public CharSequence getContentDescription() {
11156         return mContentDescription;
11157     }
11158 
11159     /**
11160      * Sets the {@link View}'s state description.
11161      * <p>
11162      * A state description briefly describes the states of the view and is primarily used
11163      * for accessibility support to determine how the states of a view should be presented to
11164      * the user. It is a supplement to the boolean states (for example, checked/unchecked) and
11165      * it is used for customized state description (for example, "wifi, connected, three bars").
11166      * State description changes frequently while content description should change less often.
11167      * State description should be localized. For android widgets which have default state
11168      * descriptions, app developers can call this method to override the state descriptions.
11169      * Setting state description to null restores the default behavior.
11170      *
11171      * @param stateDescription The state description.
11172      * @see #getStateDescription()
11173      */
11174     @RemotableViewMethod
setStateDescription(@ullable CharSequence stateDescription)11175     public void setStateDescription(@Nullable CharSequence stateDescription) {
11176         if (mStateDescription == null) {
11177             if (stateDescription == null) {
11178                 return;
11179             }
11180         } else if (mStateDescription.equals(stateDescription)) {
11181             return;
11182         }
11183         mStateDescription = stateDescription;
11184         if (!TextUtils.isEmpty(stateDescription)
11185                 && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
11186             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
11187         }
11188         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
11189             AccessibilityEvent event = AccessibilityEvent.obtain();
11190             event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
11191             event.setContentChangeTypes(AccessibilityEvent.CONTENT_CHANGE_TYPE_STATE_DESCRIPTION);
11192             sendAccessibilityEventUnchecked(event);
11193         }
11194     }
11195 
11196     /**
11197      * Sets the {@link View}'s content description.
11198      * <p>
11199      * A content description briefly describes the view and is primarily used
11200      * for accessibility support to determine how a view should be presented to
11201      * the user. In the case of a view with no textual representation, such as
11202      * {@link android.widget.ImageButton}, a useful content description
11203      * explains what the view does. For example, an image button with a phone
11204      * icon that is used to place a call may use "Call" as its content
11205      * description. An image of a floppy disk that is used to save a file may
11206      * use "Save".
11207      *
11208      * <p>
11209      * This should omit role or state. Role refers to the kind of user-interface element the View
11210      * is, such as a Button or Checkbox. State refers to a frequently changing property of the View,
11211      * such as an On/Off state of a button or the audio level of a volume slider.
11212      *
11213      * <p>
11214      * Content description updates are not frequent, and are used when the semantic content - not
11215      * the state - of the element changes. For example, a Play button might change to a Pause
11216      * button during music playback.
11217      *
11218      * @param contentDescription The content description.
11219      * @see #getContentDescription()
11220      * @see #setStateDescription(CharSequence)} for state changes.
11221      * @attr ref android.R.styleable#View_contentDescription
11222      */
11223     @RemotableViewMethod
setContentDescription(CharSequence contentDescription)11224     public void setContentDescription(CharSequence contentDescription) {
11225         if (mContentDescription == null) {
11226             if (contentDescription == null) {
11227                 return;
11228             }
11229         } else if (mContentDescription.equals(contentDescription)) {
11230             return;
11231         }
11232         mContentDescription = contentDescription;
11233         final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
11234         if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
11235             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
11236             notifySubtreeAccessibilityStateChangedIfNeeded();
11237         } else {
11238             notifyViewAccessibilityStateChangedIfNeeded(
11239                     AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
11240         }
11241     }
11242 
11243     /**
11244      * Sets the id of a view before which this one is visited in accessibility traversal.
11245      * A screen-reader must visit the content of this view before the content of the one
11246      * it precedes. For example, if view B is set to be before view A, then a screen-reader
11247      * will traverse the entire content of B before traversing the entire content of A,
11248      * regardles of what traversal strategy it is using.
11249      * <p>
11250      * Views that do not have specified before/after relationships are traversed in order
11251      * determined by the screen-reader.
11252      * </p>
11253      * <p>
11254      * Setting that this view is before a view that is not important for accessibility
11255      * or if this view is not important for accessibility will have no effect as the
11256      * screen-reader is not aware of unimportant views.
11257      * </p>
11258      *
11259      * @param beforeId The id of a view this one precedes in accessibility traversal.
11260      *
11261      * @attr ref android.R.styleable#View_accessibilityTraversalBefore
11262      *
11263      * @see #setImportantForAccessibility(int)
11264      */
11265     @RemotableViewMethod
setAccessibilityTraversalBefore(@dRes int beforeId)11266     public void setAccessibilityTraversalBefore(@IdRes int beforeId) {
11267         if (mAccessibilityTraversalBeforeId == beforeId) {
11268             return;
11269         }
11270         mAccessibilityTraversalBeforeId = beforeId;
11271         notifyViewAccessibilityStateChangedIfNeeded(
11272                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11273     }
11274 
11275     /**
11276      * Gets the id of a view before which this one is visited in accessibility traversal.
11277      *
11278      * @return The id of a view this one precedes in accessibility traversal if
11279      *         specified, otherwise {@link #NO_ID}.
11280      *
11281      * @see #setAccessibilityTraversalBefore(int)
11282      */
11283     @IdRes
11284     @InspectableProperty
getAccessibilityTraversalBefore()11285     public int getAccessibilityTraversalBefore() {
11286         return mAccessibilityTraversalBeforeId;
11287     }
11288 
11289     /**
11290      * Sets the id of a view after which this one is visited in accessibility traversal.
11291      * A screen-reader must visit the content of the other view before the content of this
11292      * one. For example, if view B is set to be after view A, then a screen-reader
11293      * will traverse the entire content of A before traversing the entire content of B,
11294      * regardles of what traversal strategy it is using.
11295      * <p>
11296      * Views that do not have specified before/after relationships are traversed in order
11297      * determined by the screen-reader.
11298      * </p>
11299      * <p>
11300      * Setting that this view is after a view that is not important for accessibility
11301      * or if this view is not important for accessibility will have no effect as the
11302      * screen-reader is not aware of unimportant views.
11303      * </p>
11304      *
11305      * @param afterId The id of a view this one succedees in accessibility traversal.
11306      *
11307      * @attr ref android.R.styleable#View_accessibilityTraversalAfter
11308      *
11309      * @see #setImportantForAccessibility(int)
11310      */
11311     @RemotableViewMethod
setAccessibilityTraversalAfter(@dRes int afterId)11312     public void setAccessibilityTraversalAfter(@IdRes int afterId) {
11313         if (mAccessibilityTraversalAfterId == afterId) {
11314             return;
11315         }
11316         mAccessibilityTraversalAfterId = afterId;
11317         notifyViewAccessibilityStateChangedIfNeeded(
11318                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11319     }
11320 
11321     /**
11322      * Gets the id of a view after which this one is visited in accessibility traversal.
11323      *
11324      * @return The id of a view this one succeedes in accessibility traversal if
11325      *         specified, otherwise {@link #NO_ID}.
11326      *
11327      * @see #setAccessibilityTraversalAfter(int)
11328      */
11329     @IdRes
11330     @InspectableProperty
getAccessibilityTraversalAfter()11331     public int getAccessibilityTraversalAfter() {
11332         return mAccessibilityTraversalAfterId;
11333     }
11334 
11335     /**
11336      * Gets the id of a view for which this view serves as a label for
11337      * accessibility purposes.
11338      *
11339      * @return The labeled view id.
11340      */
11341     @IdRes
11342     @ViewDebug.ExportedProperty(category = "accessibility")
11343     @InspectableProperty
getLabelFor()11344     public int getLabelFor() {
11345         return mLabelForId;
11346     }
11347 
11348     /**
11349      * Sets the id of a view for which this view serves as a label for
11350      * accessibility purposes.
11351      *
11352      * @param id The labeled view id.
11353      */
11354     @RemotableViewMethod
setLabelFor(@dRes int id)11355     public void setLabelFor(@IdRes int id) {
11356         if (mLabelForId == id) {
11357             return;
11358         }
11359         mLabelForId = id;
11360         if (mLabelForId != View.NO_ID
11361                 && mID == View.NO_ID) {
11362             mID = generateViewId();
11363         }
11364         notifyViewAccessibilityStateChangedIfNeeded(
11365                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11366     }
11367 
11368     /**
11369      * Invoked whenever this view loses focus, either by losing window focus or by losing
11370      * focus within its window. This method can be used to clear any state tied to the
11371      * focus. For instance, if a button is held pressed with the trackball and the window
11372      * loses focus, this method can be used to cancel the press.
11373      *
11374      * Subclasses of View overriding this method should always call super.onFocusLost().
11375      *
11376      * @see #onFocusChanged(boolean, int, android.graphics.Rect)
11377      * @see #onWindowFocusChanged(boolean)
11378      *
11379      * @hide pending API council approval
11380      */
11381     @CallSuper
11382     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
onFocusLost()11383     protected void onFocusLost() {
11384         resetPressedState();
11385     }
11386 
resetPressedState()11387     private void resetPressedState() {
11388         if ((mViewFlags & ENABLED_MASK) == DISABLED) {
11389             return;
11390         }
11391 
11392         if (isPressed()) {
11393             setPressed(false);
11394 
11395             if (!mHasPerformedLongPress) {
11396                 removeLongPressCallback();
11397             }
11398         }
11399     }
11400 
11401     /**
11402      * Returns true if this view has focus
11403      *
11404      * @return True if this view has focus, false otherwise.
11405      */
11406     @ViewDebug.ExportedProperty(category = "focus")
11407     @InspectableProperty(hasAttributeId = false)
isFocused()11408     public boolean isFocused() {
11409         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
11410     }
11411 
11412     /**
11413      * Find the view in the hierarchy rooted at this view that currently has
11414      * focus.
11415      *
11416      * @return The view that currently has focus, or null if no focused view can
11417      *         be found.
11418      */
findFocus()11419     public View findFocus() {
11420         return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
11421     }
11422 
11423     /**
11424      * Indicates whether this view is one of the set of scrollable containers in
11425      * its window.
11426      *
11427      * @return whether this view is one of the set of scrollable containers in
11428      * its window
11429      *
11430      * @attr ref android.R.styleable#View_isScrollContainer
11431      */
11432     @InspectableProperty(name = "isScrollContainer")
isScrollContainer()11433     public boolean isScrollContainer() {
11434         return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
11435     }
11436 
11437     /**
11438      * Change whether this view is one of the set of scrollable containers in
11439      * its window.  This will be used to determine whether the window can
11440      * resize or must pan when a soft input area is open -- scrollable
11441      * containers allow the window to use resize mode since the container
11442      * will appropriately shrink.
11443      *
11444      * @attr ref android.R.styleable#View_isScrollContainer
11445      */
setScrollContainer(boolean isScrollContainer)11446     public void setScrollContainer(boolean isScrollContainer) {
11447         if (isScrollContainer) {
11448             if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
11449                 mAttachInfo.mScrollContainers.add(this);
11450                 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
11451             }
11452             mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
11453         } else {
11454             if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
11455                 mAttachInfo.mScrollContainers.remove(this);
11456             }
11457             mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
11458         }
11459     }
11460 
11461     /**
11462      * Returns the quality of the drawing cache.
11463      *
11464      * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
11465      *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
11466      *
11467      * @see #setDrawingCacheQuality(int)
11468      * @see #setDrawingCacheEnabled(boolean)
11469      * @see #isDrawingCacheEnabled()
11470      *
11471      * @attr ref android.R.styleable#View_drawingCacheQuality
11472      *
11473      * @deprecated The view drawing cache was largely made obsolete with the introduction of
11474      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
11475      * layers are largely unnecessary and can easily result in a net loss in performance due to the
11476      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
11477      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
11478      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
11479      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
11480      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
11481      * software-rendered usages are discouraged and have compatibility issues with hardware-only
11482      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
11483      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
11484      * reports or unit testing the {@link PixelCopy} API is recommended.
11485      */
11486     @Deprecated
11487     @DrawingCacheQuality
11488     @InspectableProperty(enumMapping = {
11489             @EnumEntry(value = DRAWING_CACHE_QUALITY_LOW, name = "low"),
11490             @EnumEntry(value = DRAWING_CACHE_QUALITY_HIGH, name = "high"),
11491             @EnumEntry(value = DRAWING_CACHE_QUALITY_AUTO, name = "auto")
11492     })
getDrawingCacheQuality()11493     public int getDrawingCacheQuality() {
11494         return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
11495     }
11496 
11497     /**
11498      * Set the drawing cache quality of this view. This value is used only when the
11499      * drawing cache is enabled
11500      *
11501      * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
11502      *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
11503      *
11504      * @see #getDrawingCacheQuality()
11505      * @see #setDrawingCacheEnabled(boolean)
11506      * @see #isDrawingCacheEnabled()
11507      *
11508      * @attr ref android.R.styleable#View_drawingCacheQuality
11509      *
11510      * @deprecated The view drawing cache was largely made obsolete with the introduction of
11511      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
11512      * layers are largely unnecessary and can easily result in a net loss in performance due to the
11513      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
11514      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
11515      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
11516      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
11517      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
11518      * software-rendered usages are discouraged and have compatibility issues with hardware-only
11519      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
11520      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
11521      * reports or unit testing the {@link PixelCopy} API is recommended.
11522      */
11523     @Deprecated
setDrawingCacheQuality(@rawingCacheQuality int quality)11524     public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
11525         setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
11526     }
11527 
11528     /**
11529      * Returns whether the screen should remain on, corresponding to the current
11530      * value of {@link #KEEP_SCREEN_ON}.
11531      *
11532      * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
11533      *
11534      * @see #setKeepScreenOn(boolean)
11535      *
11536      * @attr ref android.R.styleable#View_keepScreenOn
11537      */
11538     @InspectableProperty
getKeepScreenOn()11539     public boolean getKeepScreenOn() {
11540         return (mViewFlags & KEEP_SCREEN_ON) != 0;
11541     }
11542 
11543     /**
11544      * Controls whether the screen should remain on, modifying the
11545      * value of {@link #KEEP_SCREEN_ON}.
11546      *
11547      * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
11548      *
11549      * @see #getKeepScreenOn()
11550      *
11551      * @attr ref android.R.styleable#View_keepScreenOn
11552      */
setKeepScreenOn(boolean keepScreenOn)11553     public void setKeepScreenOn(boolean keepScreenOn) {
11554         setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
11555     }
11556 
11557     /**
11558      * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
11559      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
11560      *
11561      * @attr ref android.R.styleable#View_nextFocusLeft
11562      */
11563     @IdRes
11564     @InspectableProperty(name = "nextFocusLeft")
getNextFocusLeftId()11565     public int getNextFocusLeftId() {
11566         return mNextFocusLeftId;
11567     }
11568 
11569     /**
11570      * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
11571      * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
11572      * decide automatically.
11573      *
11574      * @attr ref android.R.styleable#View_nextFocusLeft
11575      */
setNextFocusLeftId(@dRes int nextFocusLeftId)11576     public void setNextFocusLeftId(@IdRes int nextFocusLeftId) {
11577         mNextFocusLeftId = nextFocusLeftId;
11578     }
11579 
11580     /**
11581      * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
11582      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
11583      *
11584      * @attr ref android.R.styleable#View_nextFocusRight
11585      */
11586     @IdRes
11587     @InspectableProperty(name = "nextFocusRight")
getNextFocusRightId()11588     public int getNextFocusRightId() {
11589         return mNextFocusRightId;
11590     }
11591 
11592     /**
11593      * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
11594      * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
11595      * decide automatically.
11596      *
11597      * @attr ref android.R.styleable#View_nextFocusRight
11598      */
setNextFocusRightId(@dRes int nextFocusRightId)11599     public void setNextFocusRightId(@IdRes int nextFocusRightId) {
11600         mNextFocusRightId = nextFocusRightId;
11601     }
11602 
11603     /**
11604      * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
11605      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
11606      *
11607      * @attr ref android.R.styleable#View_nextFocusUp
11608      */
11609     @IdRes
11610     @InspectableProperty(name = "nextFocusUp")
getNextFocusUpId()11611     public int getNextFocusUpId() {
11612         return mNextFocusUpId;
11613     }
11614 
11615     /**
11616      * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
11617      * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
11618      * decide automatically.
11619      *
11620      * @attr ref android.R.styleable#View_nextFocusUp
11621      */
setNextFocusUpId(@dRes int nextFocusUpId)11622     public void setNextFocusUpId(@IdRes int nextFocusUpId) {
11623         mNextFocusUpId = nextFocusUpId;
11624     }
11625 
11626     /**
11627      * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
11628      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
11629      *
11630      * @attr ref android.R.styleable#View_nextFocusDown
11631      */
11632     @IdRes
11633     @InspectableProperty(name = "nextFocusDown")
getNextFocusDownId()11634     public int getNextFocusDownId() {
11635         return mNextFocusDownId;
11636     }
11637 
11638     /**
11639      * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
11640      * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
11641      * decide automatically.
11642      *
11643      * @attr ref android.R.styleable#View_nextFocusDown
11644      */
setNextFocusDownId(@dRes int nextFocusDownId)11645     public void setNextFocusDownId(@IdRes int nextFocusDownId) {
11646         mNextFocusDownId = nextFocusDownId;
11647     }
11648 
11649     /**
11650      * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
11651      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
11652      *
11653      * @attr ref android.R.styleable#View_nextFocusForward
11654      */
11655     @IdRes
11656     @InspectableProperty(name = "nextFocusForward")
getNextFocusForwardId()11657     public int getNextFocusForwardId() {
11658         return mNextFocusForwardId;
11659     }
11660 
11661     /**
11662      * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
11663      * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
11664      * decide automatically.
11665      *
11666      * @attr ref android.R.styleable#View_nextFocusForward
11667      */
setNextFocusForwardId(@dRes int nextFocusForwardId)11668     public void setNextFocusForwardId(@IdRes int nextFocusForwardId) {
11669         mNextFocusForwardId = nextFocusForwardId;
11670     }
11671 
11672     /**
11673      * Gets the id of the root of the next keyboard navigation cluster.
11674      * @return The next keyboard navigation cluster ID, or {@link #NO_ID} if the framework should
11675      * decide automatically.
11676      *
11677      * @attr ref android.R.styleable#View_nextClusterForward
11678      */
11679     @IdRes
11680     @InspectableProperty(name = "nextClusterForward")
getNextClusterForwardId()11681     public int getNextClusterForwardId() {
11682         return mNextClusterForwardId;
11683     }
11684 
11685     /**
11686      * Sets the id of the view to use as the root of the next keyboard navigation cluster.
11687      * @param nextClusterForwardId The next cluster ID, or {@link #NO_ID} if the framework should
11688      * decide automatically.
11689      *
11690      * @attr ref android.R.styleable#View_nextClusterForward
11691      */
setNextClusterForwardId(@dRes int nextClusterForwardId)11692     public void setNextClusterForwardId(@IdRes int nextClusterForwardId) {
11693         mNextClusterForwardId = nextClusterForwardId;
11694     }
11695 
11696     /**
11697      * Returns the visibility of this view and all of its ancestors
11698      *
11699      * @return True if this view and all of its ancestors are {@link #VISIBLE}
11700      */
isShown()11701     public boolean isShown() {
11702         View current = this;
11703         //noinspection ConstantConditions
11704         do {
11705             if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
11706                 return false;
11707             }
11708             ViewParent parent = current.mParent;
11709             if (parent == null) {
11710                 return false; // We are not attached to the view root
11711             }
11712             if (!(parent instanceof View)) {
11713                 return true;
11714             }
11715             current = (View) parent;
11716         } while (current != null);
11717 
11718         return false;
11719     }
11720 
detached()11721     private boolean detached() {
11722         View current = this;
11723         //noinspection ConstantConditions
11724         do {
11725             if ((current.mPrivateFlags4 & PFLAG4_DETACHED) != 0) {
11726                 return true;
11727             }
11728             ViewParent parent = current.mParent;
11729             if (parent == null) {
11730                 return false;
11731             }
11732             if (!(parent instanceof View)) {
11733                 return false;
11734             }
11735             current = (View) parent;
11736         } while (current != null);
11737 
11738         return false;
11739     }
11740 
11741     /**
11742      * Called by the view hierarchy when the content insets for a window have
11743      * changed, to allow it to adjust its content to fit within those windows.
11744      * The content insets tell you the space that the status bar, input method,
11745      * and other system windows infringe on the application's window.
11746      *
11747      * <p>You do not normally need to deal with this function, since the default
11748      * window decoration given to applications takes care of applying it to the
11749      * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
11750      * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
11751      * and your content can be placed under those system elements.  You can then
11752      * use this method within your view hierarchy if you have parts of your UI
11753      * which you would like to ensure are not being covered.
11754      *
11755      * <p>The default implementation of this method simply applies the content
11756      * insets to the view's padding, consuming that content (modifying the
11757      * insets to be 0), and returning true.  This behavior is off by default, but can
11758      * be enabled through {@link #setFitsSystemWindows(boolean)}.
11759      *
11760      * <p>This function's traversal down the hierarchy is depth-first.  The same content
11761      * insets object is propagated down the hierarchy, so any changes made to it will
11762      * be seen by all following views (including potentially ones above in
11763      * the hierarchy since this is a depth-first traversal).  The first view
11764      * that returns true will abort the entire traversal.
11765      *
11766      * <p>The default implementation works well for a situation where it is
11767      * used with a container that covers the entire window, allowing it to
11768      * apply the appropriate insets to its content on all edges.  If you need
11769      * a more complicated layout (such as two different views fitting system
11770      * windows, one on the top of the window, and one on the bottom),
11771      * you can override the method and handle the insets however you would like.
11772      * Note that the insets provided by the framework are always relative to the
11773      * far edges of the window, not accounting for the location of the called view
11774      * within that window.  (In fact when this method is called you do not yet know
11775      * where the layout will place the view, as it is done before layout happens.)
11776      *
11777      * <p>Note: unlike many View methods, there is no dispatch phase to this
11778      * call.  If you are overriding it in a ViewGroup and want to allow the
11779      * call to continue to your children, you must be sure to call the super
11780      * implementation.
11781      *
11782      * <p>Here is a sample layout that makes use of fitting system windows
11783      * to have controls for a video view placed inside of the window decorations
11784      * that it hides and shows.  This can be used with code like the second
11785      * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
11786      *
11787      * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
11788      *
11789      * @param insets Current content insets of the window.  Prior to
11790      * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
11791      * the insets or else you and Android will be unhappy.
11792      *
11793      * @return {@code true} if this view applied the insets and it should not
11794      * continue propagating further down the hierarchy, {@code false} otherwise.
11795      * @see #getFitsSystemWindows()
11796      * @see #setFitsSystemWindows(boolean)
11797      * @see #setSystemUiVisibility(int)
11798      *
11799      * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
11800      * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
11801      * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
11802      * to implement handling their own insets.
11803      */
11804     @Deprecated
fitSystemWindows(Rect insets)11805     protected boolean fitSystemWindows(Rect insets) {
11806         if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
11807             if (insets == null) {
11808                 // Null insets by definition have already been consumed.
11809                 // This call cannot apply insets since there are none to apply,
11810                 // so return false.
11811                 return false;
11812             }
11813             // If we're not in the process of dispatching the newer apply insets call,
11814             // that means we're not in the compatibility path. Dispatch into the newer
11815             // apply insets path and take things from there.
11816             try {
11817                 mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
11818                 return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
11819             } finally {
11820                 mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
11821             }
11822         } else {
11823             // We're being called from the newer apply insets path.
11824             // Perform the standard fallback behavior.
11825             return fitSystemWindowsInt(insets);
11826         }
11827     }
11828 
fitSystemWindowsInt(Rect insets)11829     private boolean fitSystemWindowsInt(Rect insets) {
11830         if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
11831             Rect localInsets = sThreadLocal.get();
11832             boolean res = computeFitSystemWindows(insets, localInsets);
11833             applyInsets(localInsets);
11834             return res;
11835         }
11836         return false;
11837     }
11838 
applyInsets(Rect insets)11839     private void applyInsets(Rect insets) {
11840         mUserPaddingStart = UNDEFINED_PADDING;
11841         mUserPaddingEnd = UNDEFINED_PADDING;
11842         mUserPaddingLeftInitial = insets.left;
11843         mUserPaddingRightInitial = insets.right;
11844         internalSetPadding(insets.left, insets.top, insets.right, insets.bottom);
11845     }
11846 
11847     /**
11848      * Called when the view should apply {@link WindowInsets} according to its internal policy.
11849      *
11850      * <p>This method should be overridden by views that wish to apply a policy different from or
11851      * in addition to the default behavior. Clients that wish to force a view subtree
11852      * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
11853      *
11854      * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
11855      * it will be called during dispatch instead of this method. The listener may optionally
11856      * call this method from its own implementation if it wishes to apply the view's default
11857      * insets policy in addition to its own.</p>
11858      *
11859      * <p>Implementations of this method should either return the insets parameter unchanged
11860      * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
11861      * that this view applied itself. This allows new inset types added in future platform
11862      * versions to pass through existing implementations unchanged without being erroneously
11863      * consumed.</p>
11864      *
11865      * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
11866      * property is set then the view will consume the system window insets and apply them
11867      * as padding for the view.</p>
11868      *
11869      * @param insets Insets to apply
11870      * @return The supplied insets with any applied insets consumed
11871      */
onApplyWindowInsets(WindowInsets insets)11872     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
11873         if ((mPrivateFlags4 & PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS) != 0
11874                 && (mViewFlags & FITS_SYSTEM_WINDOWS) != 0) {
11875             return onApplyFrameworkOptionalFitSystemWindows(insets);
11876         }
11877         if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
11878             // We weren't called from within a direct call to fitSystemWindows,
11879             // call into it as a fallback in case we're in a class that overrides it
11880             // and has logic to perform.
11881             if (fitSystemWindows(insets.getSystemWindowInsetsAsRect())) {
11882                 return insets.consumeSystemWindowInsets();
11883             }
11884         } else {
11885             // We were called from within a direct call to fitSystemWindows.
11886             if (fitSystemWindowsInt(insets.getSystemWindowInsetsAsRect())) {
11887                 return insets.consumeSystemWindowInsets();
11888             }
11889         }
11890         return insets;
11891     }
11892 
onApplyFrameworkOptionalFitSystemWindows(WindowInsets insets)11893     private WindowInsets onApplyFrameworkOptionalFitSystemWindows(WindowInsets insets) {
11894         Rect localInsets = sThreadLocal.get();
11895         WindowInsets result = computeSystemWindowInsets(insets, localInsets);
11896         applyInsets(localInsets);
11897         return result;
11898     }
11899 
11900     /**
11901      * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
11902      * window insets to this view. The listener's
11903      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
11904      * method will be called instead of the view's
11905      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
11906      *
11907      * @param listener Listener to set
11908      *
11909      * @see #onApplyWindowInsets(WindowInsets)
11910      */
setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener)11911     public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
11912         getListenerInfo().mOnApplyWindowInsetsListener = listener;
11913     }
11914 
11915     /**
11916      * Request to apply the given window insets to this view or another view in its subtree.
11917      *
11918      * <p>This method should be called by clients wishing to apply insets corresponding to areas
11919      * obscured by window decorations or overlays. This can include the status and navigation bars,
11920      * action bars, input methods and more. New inset categories may be added in the future.
11921      * The method returns the insets provided minus any that were applied by this view or its
11922      * children.</p>
11923      *
11924      * <p>Clients wishing to provide custom behavior should override the
11925      * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
11926      * {@link OnApplyWindowInsetsListener} via the
11927      * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
11928      * method.</p>
11929      *
11930      * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
11931      * </p>
11932      *
11933      * @param insets Insets to apply
11934      * @return The provided insets minus the insets that were consumed
11935      */
dispatchApplyWindowInsets(WindowInsets insets)11936     public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
11937         try {
11938             mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
11939             if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
11940                 return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
11941             } else {
11942                 return onApplyWindowInsets(insets);
11943             }
11944         } finally {
11945             mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
11946         }
11947     }
11948 
11949     /**
11950      * Sets a {@link WindowInsetsAnimation.Callback} to be notified about animations of windows that
11951      * cause insets.
11952      * <p>
11953      * The callback's {@link WindowInsetsAnimation.Callback#getDispatchMode()
11954      * dispatch mode} will affect whether animation callbacks are dispatched to the children of
11955      * this view.
11956      * </p>
11957      * @param callback The callback to set.
11958      */
setWindowInsetsAnimationCallback( @ullable WindowInsetsAnimation.Callback callback)11959     public void setWindowInsetsAnimationCallback(
11960             @Nullable WindowInsetsAnimation.Callback callback) {
11961         getListenerInfo().mWindowInsetsAnimationCallback = callback;
11962     }
11963 
11964     /**
11965      * @return {@code true} if any {@link WindowInsetsAnimation.Callback} is registered on the view
11966      *         or view tree of the sub-hierarchy {@code false} otherwise.
11967      * @hide
11968      */
hasWindowInsetsAnimationCallback()11969     public boolean hasWindowInsetsAnimationCallback() {
11970         return getListenerInfo().mWindowInsetsAnimationCallback != null;
11971     }
11972 
11973     /**
11974      * Dispatches {@link WindowInsetsAnimation.Callback#onPrepare(WindowInsetsAnimation)}
11975      * when Window Insets animation is being prepared.
11976      * @param animation current animation
11977      *
11978      * @see WindowInsetsAnimation.Callback#onPrepare(WindowInsetsAnimation)
11979      */
dispatchWindowInsetsAnimationPrepare( @onNull WindowInsetsAnimation animation)11980     public void dispatchWindowInsetsAnimationPrepare(
11981             @NonNull WindowInsetsAnimation animation) {
11982         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
11983             mListenerInfo.mWindowInsetsAnimationCallback.onPrepare(animation);
11984         }
11985     }
11986 
11987     /**
11988      * Dispatches {@link WindowInsetsAnimation.Callback#onStart(WindowInsetsAnimation, Bounds)}
11989      * when Window Insets animation is started.
11990      * @param animation current animation
11991      * @param bounds the upper and lower {@link Bounds} that provides range of
11992      *  {@link WindowInsetsAnimation}.
11993      * @return the upper and lower {@link Bounds}.
11994      */
11995     @NonNull
dispatchWindowInsetsAnimationStart( @onNull WindowInsetsAnimation animation, @NonNull Bounds bounds)11996     public Bounds dispatchWindowInsetsAnimationStart(
11997             @NonNull WindowInsetsAnimation animation, @NonNull Bounds bounds) {
11998         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
11999             return mListenerInfo.mWindowInsetsAnimationCallback.onStart(animation, bounds);
12000         }
12001         return bounds;
12002     }
12003 
12004     /**
12005      * Dispatches {@link WindowInsetsAnimation.Callback#onProgress(WindowInsets, List)}
12006      * when Window Insets animation makes progress.
12007      * @param insets The current {@link WindowInsets}.
12008      * @param runningAnimations The currently running {@link WindowInsetsAnimation}s.
12009      * @return current {@link WindowInsets}.
12010      */
12011     @NonNull
dispatchWindowInsetsAnimationProgress(@onNull WindowInsets insets, @NonNull List<WindowInsetsAnimation> runningAnimations)12012     public WindowInsets dispatchWindowInsetsAnimationProgress(@NonNull WindowInsets insets,
12013             @NonNull List<WindowInsetsAnimation> runningAnimations) {
12014         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
12015             return mListenerInfo.mWindowInsetsAnimationCallback.onProgress(insets,
12016                     runningAnimations);
12017         } else {
12018             return insets;
12019         }
12020     }
12021 
12022     /**
12023      * Dispatches {@link WindowInsetsAnimation.Callback#onEnd(WindowInsetsAnimation)}
12024      * when Window Insets animation ends.
12025      * @param animation The current ongoing {@link WindowInsetsAnimation}.
12026      */
dispatchWindowInsetsAnimationEnd(@onNull WindowInsetsAnimation animation)12027     public void dispatchWindowInsetsAnimationEnd(@NonNull WindowInsetsAnimation animation) {
12028         if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
12029             mListenerInfo.mWindowInsetsAnimationCallback.onEnd(animation);
12030         }
12031     }
12032 
12033     /**
12034      * Sets a list of areas within this view's post-layout coordinate space where the system
12035      * should not intercept touch or other pointing device gestures. <em>This method should
12036      * be called by {@link #onLayout(boolean, int, int, int, int)} or {@link #onDraw(Canvas)}.</em>
12037      *
12038      * <p>Use this to tell the system which specific sub-areas of a view need to receive gesture
12039      * input in order to function correctly in the presence of global system gestures that may
12040      * conflict. For example, if the system wishes to capture swipe-in-from-screen-edge gestures
12041      * to provide system-level navigation functionality, a view such as a navigation drawer
12042      * container can mark the left (or starting) edge of itself as requiring gesture capture
12043      * priority using this API. The system may then choose to relax its own gesture recognition
12044      * to allow the app to consume the user's gesture. It is not necessary for an app to register
12045      * exclusion rects for broadly spanning regions such as the entirety of a
12046      * <code>ScrollView</code> or for simple press and release click targets such as
12047      * <code>Button</code>. Mark an exclusion rect when interacting with a view requires
12048      * a precision touch gesture in a small area in either the X or Y dimension, such as
12049      * an edge swipe or dragging a <code>SeekBar</code> thumb.</p>
12050      *
12051      * <p>Note: the system will put a limit of <code>200dp</code> on the vertical extent of the
12052      * exclusions it takes into account. The limit does not apply while the navigation
12053      * bar is {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY stickily} hidden, nor to the
12054      * {@link android.inputmethodservice.InputMethodService input method} and
12055      * {@link Intent#CATEGORY_HOME home activity}.
12056      * </p>
12057      *
12058      * @param rects A list of precision gesture regions that this view needs to function correctly
12059      */
setSystemGestureExclusionRects(@onNull List<Rect> rects)12060     public void setSystemGestureExclusionRects(@NonNull List<Rect> rects) {
12061         if (rects.isEmpty() && mListenerInfo == null) return;
12062 
12063         final ListenerInfo info = getListenerInfo();
12064         if (info.mSystemGestureExclusionRects != null) {
12065             info.mSystemGestureExclusionRects.clear();
12066             info.mSystemGestureExclusionRects.addAll(rects);
12067         } else {
12068             info.mSystemGestureExclusionRects = new ArrayList<>(rects);
12069         }
12070 
12071         updatePositionUpdateListener();
12072         postUpdate(this::updateSystemGestureExclusionRects);
12073     }
12074 
updatePositionUpdateListener()12075     private void updatePositionUpdateListener() {
12076         final ListenerInfo info = getListenerInfo();
12077         if (getSystemGestureExclusionRects().isEmpty()
12078                 && collectPreferKeepClearRects().isEmpty()
12079                 && collectUnrestrictedPreferKeepClearRects().isEmpty()
12080                 && (info.mHandwritingArea == null || !shouldInitiateHandwriting())) {
12081             if (info.mPositionUpdateListener != null) {
12082                 mRenderNode.removePositionUpdateListener(info.mPositionUpdateListener);
12083                 info.mPositionUpdateListener = null;
12084                 info.mPositionChangedUpdate = null;
12085             }
12086         } else {
12087             if (info.mPositionUpdateListener == null) {
12088                 info.mPositionChangedUpdate = () -> {
12089                     updateSystemGestureExclusionRects();
12090                     updateKeepClearRects();
12091                     updateHandwritingArea();
12092                 };
12093                 info.mPositionUpdateListener = new RenderNode.PositionUpdateListener() {
12094                     @Override
12095                     public void positionChanged(long n, int l, int t, int r, int b) {
12096                         postUpdate(info.mPositionChangedUpdate);
12097                     }
12098 
12099                     @Override
12100                     public void positionLost(long frameNumber) {
12101                         postUpdate(info.mPositionChangedUpdate);
12102                     }
12103                 };
12104                 mRenderNode.addPositionUpdateListener(info.mPositionUpdateListener);
12105             }
12106         }
12107     }
12108 
12109     /**
12110      * WARNING: this can be called by a hwui worker thread, not just the UI thread!
12111      */
postUpdate(Runnable r)12112     private void postUpdate(Runnable r) {
12113         // Potentially racey from a background thread. It's ok if it's not perfect.
12114         final Handler h = getHandler();
12115         if (h != null) {
12116             h.postAtFrontOfQueue(r);
12117         }
12118     }
12119 
updateSystemGestureExclusionRects()12120     void updateSystemGestureExclusionRects() {
12121         final AttachInfo ai = mAttachInfo;
12122         if (ai != null) {
12123             ai.mViewRootImpl.updateSystemGestureExclusionRectsForView(this);
12124         }
12125     }
12126 
12127     /**
12128      * Retrieve the list of areas within this view's post-layout coordinate space where the system
12129      * should not intercept touch or other pointing device gestures.
12130      *
12131      * <p>Do not modify the returned list.</p>
12132      *
12133      * @return the list set by {@link #setSystemGestureExclusionRects(List)}
12134      */
12135     @NonNull
getSystemGestureExclusionRects()12136     public List<Rect> getSystemGestureExclusionRects() {
12137         final ListenerInfo info = mListenerInfo;
12138         if (info != null) {
12139             final List<Rect> list = info.mSystemGestureExclusionRects;
12140             if (list != null) {
12141                 return list;
12142             }
12143         }
12144         return Collections.emptyList();
12145     }
12146 
12147     /**
12148      * Set a preference to keep the bounds of this view clear from floating windows above this
12149      * view's window. This informs the system that the view is considered a vital area for the
12150      * user and that ideally it should not be covered. Setting this is only appropriate for UI
12151      * where the user would likely take action to uncover it.
12152      * <p>
12153      * The system will try to respect this preference, but when not possible will ignore it.
12154      * <p>
12155      * Note: This is independent from {@link #setPreferKeepClearRects}. If both are set, both will
12156      * be taken into account.
12157      * <p>
12158      * @see #setPreferKeepClearRects
12159      * @see #isPreferKeepClear
12160      * @attr ref android.R.styleable#View_preferKeepClear
12161      */
setPreferKeepClear(boolean preferKeepClear)12162     public final void setPreferKeepClear(boolean preferKeepClear) {
12163         getListenerInfo().mPreferKeepClear = preferKeepClear;
12164         updatePositionUpdateListener();
12165         postUpdate(this::updateKeepClearRects);
12166     }
12167 
12168     /**
12169      * Retrieve the preference for this view to be kept clear. This is set either by
12170      * {@link #setPreferKeepClear} or via the attribute android.R.styleable#View_preferKeepClear.
12171      * <p>
12172      * If this is {@code true}, the system will ignore the Rects set by
12173      * {@link #setPreferKeepClearRects} and try to keep the whole view clear.
12174      * <p>
12175      * @see #setPreferKeepClear
12176      * @attr ref android.R.styleable#View_preferKeepClear
12177      */
isPreferKeepClear()12178     public final boolean isPreferKeepClear() {
12179         return mListenerInfo != null && mListenerInfo.mPreferKeepClear;
12180     }
12181 
12182     /**
12183      * Set a preference to keep the provided rects clear from floating windows above this
12184      * view's window. This informs the system that these rects are considered vital areas for the
12185      * user and that ideally they should not be covered. Setting this is only appropriate for UI
12186      * where the user would likely take action to uncover it.
12187      * <p>
12188      * The system will try to respect this preference, but when not possible will ignore it.
12189      * <p>
12190      * Note: This is independent from {@link #setPreferKeepClear}. If both are set, both will be
12191      * taken into account.
12192      * <p>
12193      * @see #setPreferKeepClear
12194      * @see #getPreferKeepClearRects
12195      *
12196      * @param rects A list of rects in this view's local coordinate system
12197      */
setPreferKeepClearRects(@onNull List<Rect> rects)12198     public final void setPreferKeepClearRects(@NonNull List<Rect> rects) {
12199         final ListenerInfo info = getListenerInfo();
12200         if (info.mKeepClearRects != null) {
12201             info.mKeepClearRects.clear();
12202             info.mKeepClearRects.addAll(rects);
12203         } else {
12204             info.mKeepClearRects = new ArrayList<>(rects);
12205         }
12206         updatePositionUpdateListener();
12207         postUpdate(this::updateKeepClearRects);
12208     }
12209 
12210     /**
12211      * @return the list of rects, set by {@link #setPreferKeepClearRects}.
12212      *
12213      * @see #setPreferKeepClearRects
12214      */
12215     @NonNull
getPreferKeepClearRects()12216     public final List<Rect> getPreferKeepClearRects() {
12217         final ListenerInfo info = mListenerInfo;
12218         if (info != null && info.mKeepClearRects != null) {
12219             return new ArrayList(info.mKeepClearRects);
12220         }
12221 
12222         return Collections.emptyList();
12223     }
12224 
12225     /**
12226      * Set a preference to keep the provided rects clear from floating windows above this
12227      * view's window. This informs the system that these rects are considered vital areas for the
12228      * user and that ideally they should not be covered. Setting this is only appropriate for UI
12229      * where the user would likely take action to uncover it.
12230      * <p>
12231      * Note: The difference with {@link #setPreferKeepClearRects} is that the system won't apply
12232      * restrictions to the rects set here.
12233      * <p>
12234      * @see #setPreferKeepClear
12235      * @see #getPreferKeepClearRects
12236      *
12237      * @param rects A list of rects in this view's local coordinate system
12238      *
12239      * @hide
12240      */
12241     @SystemApi
12242     @RequiresPermission(android.Manifest.permission.SET_UNRESTRICTED_KEEP_CLEAR_AREAS)
setUnrestrictedPreferKeepClearRects(@onNull List<Rect> rects)12243     public final void setUnrestrictedPreferKeepClearRects(@NonNull List<Rect> rects) {
12244         final ListenerInfo info = getListenerInfo();
12245         if (info.mUnrestrictedKeepClearRects != null) {
12246             info.mUnrestrictedKeepClearRects.clear();
12247             info.mUnrestrictedKeepClearRects.addAll(rects);
12248         } else {
12249             info.mUnrestrictedKeepClearRects = new ArrayList<>(rects);
12250         }
12251         updatePositionUpdateListener();
12252         postUpdate(this::updateKeepClearRects);
12253     }
12254 
12255     /**
12256      * @return the list of rects, set by {@link #setPreferKeepClearRects}.
12257      *
12258      * @see #setPreferKeepClearRects
12259      *
12260      * @hide
12261      */
12262     @SystemApi
12263     @NonNull
getUnrestrictedPreferKeepClearRects()12264     public final List<Rect> getUnrestrictedPreferKeepClearRects() {
12265         final ListenerInfo info = mListenerInfo;
12266         if (info != null && info.mUnrestrictedKeepClearRects != null) {
12267             return new ArrayList(info.mUnrestrictedKeepClearRects);
12268         }
12269 
12270         return Collections.emptyList();
12271     }
12272 
updateKeepClearRects()12273     void updateKeepClearRects() {
12274         final AttachInfo ai = mAttachInfo;
12275         if (ai != null) {
12276             ai.mViewRootImpl.updateKeepClearRectsForView(this);
12277         }
12278     }
12279 
12280     /**
12281      * Retrieve the list of areas within this view's post-layout coordinate space which the
12282      * system will try to not cover with other floating elements, like the pip window.
12283      */
12284     @NonNull
collectPreferKeepClearRects()12285     List<Rect> collectPreferKeepClearRects() {
12286         ListenerInfo info = mListenerInfo;
12287         boolean keepClearForFocus = isFocused()
12288                 && ViewConfiguration.get(mContext).isPreferKeepClearForFocusEnabled();
12289         boolean keepBoundsClear = (info != null && info.mPreferKeepClear) || keepClearForFocus;
12290         boolean hasCustomKeepClearRects = info != null && info.mKeepClearRects != null;
12291 
12292         if (!keepBoundsClear && !hasCustomKeepClearRects) {
12293             return Collections.emptyList();
12294         } else if (keepBoundsClear && !hasCustomKeepClearRects) {
12295             return Collections.singletonList(new Rect(0, 0, getWidth(), getHeight()));
12296         }
12297 
12298         final List<Rect> list = new ArrayList<>();
12299         if (keepBoundsClear) {
12300             list.add(new Rect(0, 0, getWidth(), getHeight()));
12301         }
12302 
12303         if (hasCustomKeepClearRects) {
12304             list.addAll(info.mKeepClearRects);
12305         }
12306 
12307         return list;
12308     }
12309 
updatePreferKeepClearForFocus()12310     private void updatePreferKeepClearForFocus() {
12311         if (ViewConfiguration.get(mContext).isPreferKeepClearForFocusEnabled()) {
12312             updatePositionUpdateListener();
12313             post(this::updateKeepClearRects);
12314         }
12315     }
12316 
12317     /**
12318      * Retrieve the list of unrestricted areas within this view's post-layout coordinate space
12319      * which the system will try to not cover with other floating elements, like the pip window.
12320      */
12321     @NonNull
collectUnrestrictedPreferKeepClearRects()12322     List<Rect> collectUnrestrictedPreferKeepClearRects() {
12323         final ListenerInfo info = mListenerInfo;
12324         if (info != null && info.mUnrestrictedKeepClearRects != null) {
12325             return info.mUnrestrictedKeepClearRects;
12326         }
12327 
12328         return Collections.emptyList();
12329     }
12330 
12331     /**
12332      * Set the amount of offset applied to this view's stylus handwriting bounds. A positive offset
12333      * will offset the edge outwards.The base handwriting bounds of a view is its visible bounds.
12334      * The handwriting bounds offsets are applied to the base handwriting bounds to determine the
12335      * final handwriting bounds.
12336      * <p> This method is mainly used to enlarge the view's handwriting bounds for a better user
12337      * experience.
12338      * <p> Note that when the view is clipped (e.g. the view is in a
12339      * {@link android.widget.ScrollView}), the offsets are applied after the view's handwriting
12340      * bounds is clipped.
12341      *
12342      * @param offsetLeft the amount of pixel offset applied to the left edge outwards of the view's
12343      *                   handwriting bounds.
12344      * @param offsetTop the amount of pixel offset applied to the top edge outwards of the view's
12345      *                  handwriting bounds.
12346      * @param offsetRight the amount of pixel offset applied to the right edge outwards of the
12347      *                    view's handwriting bounds.
12348      * @param offsetBottom the amount of pixel offset applied to the bottom edge outwards of the
12349      *                     view's handwriting bounds.
12350      *
12351      * @see #setAutoHandwritingEnabled(boolean)
12352      * @see #getHandwritingBoundsOffsetLeft()
12353      * @see #getHandwritingBoundsOffsetTop()
12354      * @see #getHandwritingBoundsOffsetRight()
12355      * @see #getHandwritingBoundsOffsetBottom()
12356      */
setHandwritingBoundsOffsets(float offsetLeft, float offsetTop, float offsetRight, float offsetBottom)12357     public void setHandwritingBoundsOffsets(float offsetLeft, float offsetTop,
12358             float offsetRight, float offsetBottom) {
12359         mHandwritingBoundsOffsetLeft = offsetLeft;
12360         mHandwritingBoundsOffsetTop = offsetTop;
12361         mHandwritingBoundsOffsetRight = offsetRight;
12362         mHandwritingBoundsOffsetBottom = offsetBottom;
12363     }
12364 
12365     /**
12366      * Return the amount of offset applied to the left edge of this view's handwriting bounds,
12367      * in the unit of pixel.
12368      *
12369      * @see #setAutoHandwritingEnabled(boolean)
12370      * @see #setHandwritingBoundsOffsets(float, float, float, float)
12371      */
getHandwritingBoundsOffsetLeft()12372     public float getHandwritingBoundsOffsetLeft() {
12373         return mHandwritingBoundsOffsetLeft;
12374     }
12375 
12376     /**
12377      * Return the amount of offset applied to the top edge of this view's handwriting bounds,
12378      * in the unit of pixel.
12379      *
12380      * @see #setAutoHandwritingEnabled(boolean)
12381      * @see #setHandwritingBoundsOffsets(float, float, float, float)
12382      */
getHandwritingBoundsOffsetTop()12383     public float getHandwritingBoundsOffsetTop() {
12384         return mHandwritingBoundsOffsetTop;
12385     }
12386 
12387     /**
12388      * Return the amount of offset applied to the right edge of this view's handwriting bounds, in
12389      * the unit of pixel.
12390      *
12391      * @see #setAutoHandwritingEnabled(boolean)
12392      * @see #setHandwritingBoundsOffsets(float, float, float, float)
12393      */
getHandwritingBoundsOffsetRight()12394     public float getHandwritingBoundsOffsetRight() {
12395         return mHandwritingBoundsOffsetRight;
12396     }
12397 
12398     /**
12399      * Return the amount of offset applied to the bottom edge of this view's handwriting bounds, in
12400      * the unit of pixel.
12401      *
12402      * @see #setAutoHandwritingEnabled(boolean)
12403      * @see #setHandwritingBoundsOffsets(float, float, float, float)
12404      */
getHandwritingBoundsOffsetBottom()12405     public float getHandwritingBoundsOffsetBottom() {
12406         return mHandwritingBoundsOffsetBottom;
12407     }
12408 
12409 
12410     /**
12411      * Set a handwriting area in this view. If there is any stylus {@link MotionEvent}
12412      * occurs within this area, it will trigger stylus handwriting mode. This can be disabled by
12413      * disabling the auto handwriting initiation by calling
12414      * {@link #setAutoHandwritingEnabled(boolean)} with false.
12415      *
12416      * @attr rect the handwriting area in the view's local coordiniates.
12417      *
12418      * @see android.view.inputmethod.InputMethodManager#startStylusHandwriting(View)
12419      * @see #setAutoHandwritingEnabled(boolean)
12420      *
12421      * @hide
12422      */
setHandwritingArea(@ullable Rect rect)12423     public void setHandwritingArea(@Nullable Rect rect) {
12424         final ListenerInfo info = getListenerInfo();
12425         info.mHandwritingArea = rect;
12426         updatePositionUpdateListener();
12427         postUpdate(this::updateHandwritingArea);
12428     }
12429 
12430     /**
12431      * Return the handwriting areas set on this view, in its local coordinates.
12432      * @see #setHandwritingArea(Rect)
12433      *
12434      * @hide
12435      */
12436     @Nullable
getHandwritingArea()12437     public Rect getHandwritingArea() {
12438         final ListenerInfo info = mListenerInfo;
12439         if (info != null && info.mHandwritingArea != null) {
12440             return new Rect(info.mHandwritingArea);
12441         }
12442         return null;
12443     }
12444 
updateHandwritingArea()12445     void updateHandwritingArea() {
12446         // If autoHandwritingArea is not enabled, do nothing.
12447         if (!shouldInitiateHandwriting()) return;
12448         final AttachInfo ai = mAttachInfo;
12449         if (ai != null) {
12450             ai.mViewRootImpl.getHandwritingInitiator().updateHandwritingAreasForView(this);
12451         }
12452     }
12453 
12454     /**
12455      * Returns true if a stylus {@link MotionEvent} within this view's bounds should initiate
12456      * handwriting mode, either for this view ({@link #isAutoHandwritingEnabled()} is {@code true})
12457      * or for a handwriting delegate view ({@link #getHandwritingDelegatorCallback()} is not {@code
12458      * null}).
12459      */
shouldInitiateHandwriting()12460     boolean shouldInitiateHandwriting() {
12461         return isAutoHandwritingEnabled() || getHandwritingDelegatorCallback() != null;
12462     }
12463 
12464     /**
12465      * Sets a callback which should be called when a stylus {@link MotionEvent} occurs within this
12466      * view's bounds. The callback will be called from the UI thread.
12467      *
12468      * <p>Setting a callback allows this view to act as a handwriting delegator, so that handwriting
12469      * mode for a delegate editor view can be initiated by stylus movement on this delegator view.
12470      * The callback implementation is expected to show and focus the delegate editor view. If a view
12471      * which returns {@code true} for {@link #isHandwritingDelegate()} creates an input connection
12472      * while the same stylus {@link MotionEvent} sequence is ongoing, handwriting mode will be
12473      * initiated for that view.
12474      *
12475      * <p>A common use case is a custom view which looks like a text editor but does not actually
12476      * support text editing itself, and clicking on the custom view causes an EditText to be shown.
12477      * To support handwriting initiation in this case, this method can be called on the custom view
12478      * to configure it as a delegator. The EditText should call {@link #setIsHandwritingDelegate} to
12479      * set it as a delegate. The {@code callback} implementation is typically the same as the click
12480      * listener implementation which shows the EditText.
12481      *
12482      * <p>If {@code null} is passed, this view will no longer act as a handwriting initiation
12483      * delegator.
12484      *
12485      * @param callback a callback which should be called when a stylus {@link MotionEvent} occurs
12486      *     within this view's bounds
12487      */
setHandwritingDelegatorCallback(@ullable Runnable callback)12488     public void setHandwritingDelegatorCallback(@Nullable Runnable callback) {
12489         mHandwritingDelegatorCallback = callback;
12490         if (callback != null) {
12491             setHandwritingArea(new Rect(0, 0, getWidth(), getHeight()));
12492         }
12493     }
12494 
12495     /**
12496      * Returns the callback set by {@link #setHandwritingDelegatorCallback} which should be called
12497      * when a stylus {@link MotionEvent} occurs within this view's bounds. The callback should only
12498      * be called from the UI thread.
12499      */
12500     @Nullable
getHandwritingDelegatorCallback()12501     public Runnable getHandwritingDelegatorCallback() {
12502         return mHandwritingDelegatorCallback;
12503     }
12504 
12505     /**
12506      * Specifies that this view may act as a handwriting initiation delegator for a delegate editor
12507      * view from the specified package. If this method is not called, delegators may only be used to
12508      * initiate handwriting mode for a delegate editor view from the same package as the delegator
12509      * view. This method allows specifying a different trusted package which may contain a delegate
12510      * editor view linked to this delegator view.
12511      *
12512      * <p>This method has no effect unless {@link #setHandwritingDelegatorCallback} is also called
12513      * to configure this view to act as a handwriting delegator.
12514      *
12515      * <p>If this method is called on the delegator view, then {@link
12516      * #setAllowedHandwritingDelegatorPackage} should also be called on the delegate editor view.
12517      *
12518      * <p>For example, to configure a delegator view in package 1:
12519      *
12520      * <pre>
12521      * delegatorView.setHandwritingDelegatorCallback(callback);
12522      * delegatorView.setAllowedHandwritingDelegatePackage(package2);</pre>
12523      *
12524      * Then to configure the corresponding delegate editor view in package 2:
12525      *
12526      * <pre>
12527      * delegateEditorView.setIsHandwritingDelegate(true);
12528      * delegateEditorView.setAllowedHandwritingDelegatorPackage(package1);</pre>
12529      *
12530      * @param allowedPackageName the package name of a delegate editor view linked to this delegator
12531      *     view, or {@code null} to restore the default behavior of only allowing delegate editor
12532      *     views from the same package as this delegator view
12533      */
setAllowedHandwritingDelegatePackage(@ullable String allowedPackageName)12534     public void setAllowedHandwritingDelegatePackage(@Nullable String allowedPackageName) {
12535         mAllowedHandwritingDelegatePackageName = allowedPackageName;
12536     }
12537 
12538     /**
12539      * Returns the allowed package for delegate editor views for which this view may act as a
12540      * handwriting delegator, as set by {@link #setAllowedHandwritingDelegatePackage}. If {@link
12541      * #setAllowedHandwritingDelegatePackage} has not been called, or called with {@code null}
12542      * argument, this will return {@code null}, meaning that this delegator view may only be used to
12543      * initiate handwriting mode for a delegate editor view from the same package as this delegator
12544      * view.
12545      */
12546     @Nullable
getAllowedHandwritingDelegatePackageName()12547     public String getAllowedHandwritingDelegatePackageName() {
12548         return mAllowedHandwritingDelegatePackageName;
12549     }
12550 
12551     /**
12552      * Sets this view to be a handwriting delegate. If a delegate view creates an input connection
12553      * while a stylus {@link MotionEvent} sequence from a delegator view is ongoing, handwriting
12554      * mode will be initiated for the delegate view.
12555      *
12556      * @param isHandwritingDelegate whether this view is a handwriting initiation delegate
12557      * @see #setHandwritingDelegatorCallback(Runnable)
12558      */
setIsHandwritingDelegate(boolean isHandwritingDelegate)12559     public void setIsHandwritingDelegate(boolean isHandwritingDelegate) {
12560         mIsHandwritingDelegate = isHandwritingDelegate;
12561     }
12562 
12563     /**
12564      * Returns whether this view has been set as a handwriting delegate by {@link
12565      * #setIsHandwritingDelegate}.
12566      */
isHandwritingDelegate()12567     public boolean isHandwritingDelegate() {
12568         return mIsHandwritingDelegate;
12569     }
12570 
12571     /**
12572      * Specifies that a view from the specified package may act as a handwriting delegator for this
12573      * delegate editor view. If this method is not called, only views from the same package as this
12574      * delegate editor view may act as a handwriting delegator. This method allows specifying a
12575      * different trusted package which may contain a delegator view linked to this delegate editor
12576      * view.
12577      *
12578      * <p>This method has no effect unless {@link #setIsHandwritingDelegate} is also called to
12579      * configure this view to act as a handwriting delegate.
12580      *
12581      * <p>If this method is called on the delegate editor view, then {@link
12582      * #setAllowedHandwritingDelegatePackage} should also be called on the delegator view.
12583      *
12584      * @param allowedPackageName the package name of a delegator view linked to this delegate editor
12585      *     view, or {@code null} to restore the default behavior of only allowing delegator views
12586      *     from the same package as this delegate editor view
12587      */
setAllowedHandwritingDelegatorPackage(@ullable String allowedPackageName)12588     public void setAllowedHandwritingDelegatorPackage(@Nullable String allowedPackageName) {
12589         mAllowedHandwritingDelegatorPackageName = allowedPackageName;
12590     }
12591 
12592     /**
12593      * Returns the allowed package for views which may act as a handwriting delegator for this
12594      * delegate editor view, as set by {@link #setAllowedHandwritingDelegatorPackage}. If {@link
12595      * #setAllowedHandwritingDelegatorPackage} has not been called, or called with {@code null}
12596      * argument, this will return {@code null}, meaning that only views from the same package as
12597      * this delegator editor view may act as a handwriting delegator.
12598      */
12599     @Nullable
getAllowedHandwritingDelegatorPackageName()12600     public String getAllowedHandwritingDelegatorPackageName() {
12601         return mAllowedHandwritingDelegatorPackageName;
12602     }
12603 
12604     /**
12605      * Gets the coordinates of this view in the coordinate space of the
12606      * {@link Surface} that contains the view.
12607      *
12608      * <p>In multiple-screen scenarios, if the surface spans multiple screens,
12609      * the coordinate space of the surface also spans multiple screens.
12610      *
12611      * <p>After the method returns, the argument array contains the x and y
12612      * coordinates of the view relative to the view's left and top edges,
12613      * respectively.
12614      *
12615      * @param location A two-element integer array in which the view coordinates
12616      *      are stored. The x-coordinate is at index 0; the y-coordinate, at
12617      *      index 1.
12618      */
getLocationInSurface(@onNull @ize2) int[] location)12619     public void getLocationInSurface(@NonNull @Size(2) int[] location) {
12620         getLocationInWindow(location);
12621         if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
12622             location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
12623             location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
12624         }
12625     }
12626 
12627     /**
12628      * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
12629      * only available if the view is attached.
12630      *
12631      * @return WindowInsets from the top of the view hierarchy or null if View is detached
12632      */
getRootWindowInsets()12633     public WindowInsets getRootWindowInsets() {
12634         if (mAttachInfo != null) {
12635             return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
12636         }
12637         return null;
12638     }
12639 
12640     /**
12641      * Retrieves the single {@link WindowInsetsController} of the window this view is attached to.
12642      *
12643      * @return The {@link WindowInsetsController} or {@code null} if the view is neither attached to
12644      *         a window nor a view tree with a decor.
12645      * @see Window#getInsetsController()
12646      */
getWindowInsetsController()12647     public @Nullable WindowInsetsController getWindowInsetsController() {
12648         if (mAttachInfo != null) {
12649             return mAttachInfo.mViewRootImpl.getInsetsController();
12650         }
12651         ViewParent parent = getParent();
12652         if (parent instanceof View) {
12653             return ((View) parent).getWindowInsetsController();
12654         } else if (parent instanceof ViewRootImpl) {
12655             // Between WindowManager.addView() and the first traversal AttachInfo isn't set yet.
12656             return ((ViewRootImpl) parent).getInsetsController();
12657         }
12658         return null;
12659     }
12660 
12661 
12662     /**
12663      * Walk up the View hierarchy to find the nearest {@link OnBackInvokedDispatcher}.
12664      *
12665      * @return The {@link OnBackInvokedDispatcher} from this or the nearest
12666      * ancestor, or null if this view is both not attached and have no ancestor providing an
12667      * {@link OnBackInvokedDispatcher}.
12668      */
12669     @Nullable
findOnBackInvokedDispatcher()12670     public final OnBackInvokedDispatcher findOnBackInvokedDispatcher() {
12671         ViewParent parent = getParent();
12672         if (parent != null) {
12673             return parent.findOnBackInvokedDispatcherForChild(this, this);
12674         }
12675         return null;
12676     }
12677 
12678     /**
12679      * @hide Compute the insets that should be consumed by this view and the ones
12680      * that should propagate to those under it.
12681      *
12682      * Note: This is used by appcompat's ActionBarOverlayLayout through reflection.
12683      *
12684      * @param inoutInsets the insets given to this view
12685      * @param outLocalInsets the insets that should be applied to this view
12686      * @deprecated use {@link #computeSystemWindowInsets}
12687      * @return
12688      */
12689     @Deprecated
12690     @UnsupportedAppUsage
computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets)12691     protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
12692         WindowInsets innerInsets = computeSystemWindowInsets(new WindowInsets(inoutInsets),
12693                 outLocalInsets);
12694         inoutInsets.set(innerInsets.getSystemWindowInsetsAsRect());
12695         return innerInsets.isSystemWindowInsetsConsumed();
12696     }
12697 
12698     /**
12699      * Compute insets that should be consumed by this view and the ones that should propagate
12700      * to those under it.
12701      *
12702      * @param in Insets currently being processed by this View, likely received as a parameter
12703      *           to {@link #onApplyWindowInsets(WindowInsets)}.
12704      * @param outLocalInsets A Rect that will receive the insets that should be consumed
12705      *                       by this view
12706      * @return Insets that should be passed along to views under this one
12707      */
computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets)12708     public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
12709         boolean isOptionalFitSystemWindows = (mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) != 0
12710                 || (mPrivateFlags4 & PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS) != 0;
12711         if (isOptionalFitSystemWindows && mAttachInfo != null) {
12712             OnContentApplyWindowInsetsListener listener =
12713                     mAttachInfo.mContentOnApplyWindowInsetsListener;
12714             if (listener == null) {
12715                 // The application wants to take care of fitting system window for
12716                 // the content.
12717                 outLocalInsets.setEmpty();
12718                 return in;
12719             }
12720             Pair<Insets, WindowInsets> result = listener.onContentApplyWindowInsets(this, in);
12721             outLocalInsets.set(result.first.toRect());
12722             return result.second;
12723         } else {
12724             outLocalInsets.set(in.getSystemWindowInsetsAsRect());
12725             return in.consumeSystemWindowInsets().inset(outLocalInsets);
12726         }
12727     }
12728 
12729     /**
12730      * Sets whether or not this view should account for system screen decorations
12731      * such as the status bar and inset its content; that is, controlling whether
12732      * the default implementation of {@link #fitSystemWindows(Rect)} will be
12733      * executed.  See that method for more details.
12734      *
12735      * <p>Note that if you are providing your own implementation of
12736      * {@link #fitSystemWindows(Rect)}, then there is no need to set this
12737      * flag to true -- your implementation will be overriding the default
12738      * implementation that checks this flag.
12739      *
12740      * @param fitSystemWindows If true, then the default implementation of
12741      * {@link #fitSystemWindows(Rect)} will be executed.
12742      *
12743      * @attr ref android.R.styleable#View_fitsSystemWindows
12744      * @see #getFitsSystemWindows()
12745      * @see #fitSystemWindows(Rect)
12746      * @see #setSystemUiVisibility(int)
12747      */
setFitsSystemWindows(boolean fitSystemWindows)12748     public void setFitsSystemWindows(boolean fitSystemWindows) {
12749         setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
12750     }
12751 
12752     /**
12753      * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
12754      * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
12755      * will be executed.
12756      *
12757      * @return {@code true} if the default implementation of
12758      * {@link #fitSystemWindows(Rect)} will be executed.
12759      *
12760      * @attr ref android.R.styleable#View_fitsSystemWindows
12761      * @see #setFitsSystemWindows(boolean)
12762      * @see #fitSystemWindows(Rect)
12763      * @see #setSystemUiVisibility(int)
12764      */
12765     @ViewDebug.ExportedProperty
12766     @InspectableProperty
getFitsSystemWindows()12767     public boolean getFitsSystemWindows() {
12768         return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
12769     }
12770 
12771     /** @hide */
12772     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
fitsSystemWindows()12773     public boolean fitsSystemWindows() {
12774         return getFitsSystemWindows();
12775     }
12776 
12777     /**
12778      * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
12779      * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
12780      */
12781     @Deprecated
requestFitSystemWindows()12782     public void requestFitSystemWindows() {
12783         if (mParent != null) {
12784             mParent.requestFitSystemWindows();
12785         }
12786     }
12787 
12788     /**
12789      * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
12790      */
requestApplyInsets()12791     public void requestApplyInsets() {
12792         requestFitSystemWindows();
12793     }
12794 
12795     /**
12796      * @see #OPTIONAL_FITS_SYSTEM_WINDOWS
12797      * @hide
12798      */
12799     @UnsupportedAppUsage
makeOptionalFitsSystemWindows()12800     public void makeOptionalFitsSystemWindows() {
12801         setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
12802     }
12803 
12804     /**
12805      * @see #PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS
12806      * @hide
12807      */
makeFrameworkOptionalFitsSystemWindows()12808     public void makeFrameworkOptionalFitsSystemWindows() {
12809         mPrivateFlags4 |= PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS;
12810     }
12811 
12812     /**
12813      * @hide
12814      */
isFrameworkOptionalFitsSystemWindows()12815     public boolean isFrameworkOptionalFitsSystemWindows() {
12816         return (mPrivateFlags4 & PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS) != 0;
12817     }
12818 
12819     /**
12820      * Returns the visibility status for this view.
12821      *
12822      * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
12823      * @attr ref android.R.styleable#View_visibility
12824      */
12825     @ViewDebug.ExportedProperty(mapping = {
12826         @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
12827         @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
12828         @ViewDebug.IntToString(from = GONE,      to = "GONE")
12829     })
12830     @InspectableProperty(enumMapping = {
12831             @EnumEntry(value = VISIBLE, name = "visible"),
12832             @EnumEntry(value = INVISIBLE, name = "invisible"),
12833             @EnumEntry(value = GONE, name = "gone")
12834     })
12835     @Visibility
getVisibility()12836     public int getVisibility() {
12837         return mViewFlags & VISIBILITY_MASK;
12838     }
12839 
12840     /**
12841      * Set the visibility state of this view.
12842      *
12843      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
12844      * @attr ref android.R.styleable#View_visibility
12845      */
12846     @RemotableViewMethod
setVisibility(@isibility int visibility)12847     public void setVisibility(@Visibility int visibility) {
12848         setFlags(visibility, VISIBILITY_MASK);
12849     }
12850 
12851     /**
12852      * Returns the enabled status for this view. The interpretation of the
12853      * enabled state varies by subclass.
12854      *
12855      * @return True if this view is enabled, false otherwise.
12856      */
12857     @ViewDebug.ExportedProperty
12858     @InspectableProperty
isEnabled()12859     public boolean isEnabled() {
12860         return (mViewFlags & ENABLED_MASK) == ENABLED;
12861     }
12862 
12863     /**
12864      * Set the enabled state of this view. The interpretation of the enabled
12865      * state varies by subclass.
12866      *
12867      * @param enabled True if this view is enabled, false otherwise.
12868      */
12869     @RemotableViewMethod
setEnabled(boolean enabled)12870     public void setEnabled(boolean enabled) {
12871         if (enabled == isEnabled()) return;
12872 
12873         setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
12874 
12875         /*
12876          * The View most likely has to change its appearance, so refresh
12877          * the drawable state.
12878          */
12879         refreshDrawableState();
12880 
12881         // Invalidate too, since the default behavior for views is to be
12882         // be drawn at 50% alpha rather than to change the drawable.
12883         invalidate(true);
12884 
12885         if (!enabled) {
12886             cancelPendingInputEvents();
12887         }
12888         notifyViewAccessibilityStateChangedIfNeeded(
12889                 AccessibilityEvent.CONTENT_CHANGE_TYPE_ENABLED);
12890     }
12891 
12892     /**
12893      * Set whether this view can receive the focus.
12894      * <p>
12895      * Setting this to false will also ensure that this view is not focusable
12896      * in touch mode.
12897      *
12898      * @param focusable If true, this view can receive the focus.
12899      *
12900      * @see #setFocusableInTouchMode(boolean)
12901      * @see #setFocusable(int)
12902      * @attr ref android.R.styleable#View_focusable
12903      */
12904     @RemotableViewMethod
setFocusable(boolean focusable)12905     public void setFocusable(boolean focusable) {
12906         setFocusable(focusable ? FOCUSABLE : NOT_FOCUSABLE);
12907     }
12908 
12909     /**
12910      * Sets whether this view can receive focus.
12911      * <p>
12912      * Setting this to {@link #FOCUSABLE_AUTO} tells the framework to determine focusability
12913      * automatically based on the view's interactivity. This is the default.
12914      * <p>
12915      * Setting this to NOT_FOCUSABLE will ensure that this view is also not focusable
12916      * in touch mode.
12917      *
12918      * @param focusable One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE},
12919      *                  or {@link #FOCUSABLE_AUTO}.
12920      * @see #setFocusableInTouchMode(boolean)
12921      * @attr ref android.R.styleable#View_focusable
12922      */
12923     @RemotableViewMethod
setFocusable(@ocusable int focusable)12924     public void setFocusable(@Focusable int focusable) {
12925         if ((focusable & (FOCUSABLE_AUTO | FOCUSABLE)) == 0) {
12926             setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
12927         }
12928         setFlags(focusable, FOCUSABLE_MASK);
12929     }
12930 
12931     /**
12932      * Set whether this view can receive focus while in touch mode.
12933      *
12934      * Setting this to true will also ensure that this view is focusable.
12935      *
12936      * @param focusableInTouchMode If true, this view can receive the focus while
12937      *   in touch mode.
12938      *
12939      * @see #setFocusable(boolean)
12940      * @attr ref android.R.styleable#View_focusableInTouchMode
12941      */
12942     @RemotableViewMethod
setFocusableInTouchMode(boolean focusableInTouchMode)12943     public void setFocusableInTouchMode(boolean focusableInTouchMode) {
12944         // Focusable in touch mode should always be set before the focusable flag
12945         // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
12946         // which, in touch mode, will not successfully request focus on this view
12947         // because the focusable in touch mode flag is not set
12948         setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
12949 
12950         // Clear FOCUSABLE_AUTO if set.
12951         if (focusableInTouchMode) {
12952             // Clears FOCUSABLE_AUTO if set.
12953             setFlags(FOCUSABLE, FOCUSABLE_MASK);
12954         }
12955     }
12956 
12957     /**
12958      * Sets the hints that help an {@link android.service.autofill.AutofillService} determine how
12959      * to autofill the view with the user's data.
12960      *
12961      * <p>Typically, there is only one way to autofill a view, but there could be more than one.
12962      * For example, if the application accepts either an username or email address to identify
12963      * an user.
12964      *
12965      * <p>These hints are not validated by the Android System, but passed "as is" to the service.
12966      * Hence, they can have any value, but it's recommended to use the {@code AUTOFILL_HINT_}
12967      * constants such as:
12968      * {@link #AUTOFILL_HINT_USERNAME}, {@link #AUTOFILL_HINT_PASSWORD},
12969      * {@link #AUTOFILL_HINT_EMAIL_ADDRESS},
12970      * {@link #AUTOFILL_HINT_NAME},
12971      * {@link #AUTOFILL_HINT_PHONE},
12972      * {@link #AUTOFILL_HINT_POSTAL_ADDRESS}, {@link #AUTOFILL_HINT_POSTAL_CODE},
12973      * {@link #AUTOFILL_HINT_CREDIT_CARD_NUMBER}, {@link #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE},
12974      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE},
12975      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
12976      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH} or
12977      * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}.
12978      *
12979      * @param autofillHints The autofill hints to set. If the array is emtpy, {@code null} is set.
12980      * @attr ref android.R.styleable#View_autofillHints
12981      */
setAutofillHints(@ullable String... autofillHints)12982     public void setAutofillHints(@Nullable String... autofillHints) {
12983         if (autofillHints == null || autofillHints.length == 0) {
12984             mAutofillHints = null;
12985         } else {
12986             mAutofillHints = autofillHints;
12987         }
12988     }
12989 
12990     /**
12991      * @hide
12992      */
12993     @TestApi
setAutofilled(boolean isAutofilled, boolean hideHighlight)12994     public void setAutofilled(boolean isAutofilled, boolean hideHighlight) {
12995         boolean wasChanged = isAutofilled != isAutofilled();
12996 
12997         if (wasChanged) {
12998             if (isAutofilled) {
12999                 mPrivateFlags3 |= PFLAG3_IS_AUTOFILLED;
13000             } else {
13001                 mPrivateFlags3 &= ~PFLAG3_IS_AUTOFILLED;
13002             }
13003 
13004             if (hideHighlight) {
13005                 mPrivateFlags4 |= PFLAG4_AUTOFILL_HIDE_HIGHLIGHT;
13006             } else {
13007                 mPrivateFlags4 &= ~PFLAG4_AUTOFILL_HIDE_HIGHLIGHT;
13008             }
13009 
13010             invalidate();
13011         }
13012     }
13013 
13014     /**
13015      * Set whether this view should have sound effects enabled for events such as
13016      * clicking and touching.
13017      *
13018      * <p>You may wish to disable sound effects for a view if you already play sounds,
13019      * for instance, a dial key that plays dtmf tones.
13020      *
13021      * @param soundEffectsEnabled whether sound effects are enabled for this view.
13022      * @see #isSoundEffectsEnabled()
13023      * @see #playSoundEffect(int)
13024      * @attr ref android.R.styleable#View_soundEffectsEnabled
13025      */
setSoundEffectsEnabled(boolean soundEffectsEnabled)13026     public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
13027         setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
13028     }
13029 
13030     /**
13031      * @return whether this view should have sound effects enabled for events such as
13032      *     clicking and touching.
13033      *
13034      * @see #setSoundEffectsEnabled(boolean)
13035      * @see #playSoundEffect(int)
13036      * @attr ref android.R.styleable#View_soundEffectsEnabled
13037      */
13038     @ViewDebug.ExportedProperty
13039     @InspectableProperty
isSoundEffectsEnabled()13040     public boolean isSoundEffectsEnabled() {
13041         return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
13042     }
13043 
13044     /**
13045      * Set whether this view should have haptic feedback for events such as
13046      * long presses.
13047      *
13048      * <p>You may wish to disable haptic feedback if your view already controls
13049      * its own haptic feedback.
13050      *
13051      * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
13052      * @see #isHapticFeedbackEnabled()
13053      * @see #performHapticFeedback(int)
13054      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
13055      */
setHapticFeedbackEnabled(boolean hapticFeedbackEnabled)13056     public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
13057         setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
13058     }
13059 
13060     /**
13061      * @return whether this view should have haptic feedback enabled for events
13062      * such as long presses.
13063      *
13064      * @see #setHapticFeedbackEnabled(boolean)
13065      * @see #performHapticFeedback(int)
13066      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
13067      */
13068     @ViewDebug.ExportedProperty
13069     @InspectableProperty
isHapticFeedbackEnabled()13070     public boolean isHapticFeedbackEnabled() {
13071         return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
13072     }
13073 
13074     /**
13075      * Returns the layout direction for this view.
13076      *
13077      * @return One of {@link #LAYOUT_DIRECTION_LTR},
13078      *   {@link #LAYOUT_DIRECTION_RTL},
13079      *   {@link #LAYOUT_DIRECTION_INHERIT} or
13080      *   {@link #LAYOUT_DIRECTION_LOCALE}.
13081      *
13082      * @attr ref android.R.styleable#View_layoutDirection
13083      *
13084      * @hide
13085      */
13086     @ViewDebug.ExportedProperty(category = "layout", mapping = {
13087         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
13088         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
13089         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
13090         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
13091     })
13092     @InspectableProperty(hasAttributeId = false, enumMapping = {
13093             @EnumEntry(value = LAYOUT_DIRECTION_LTR, name = "ltr"),
13094             @EnumEntry(value = LAYOUT_DIRECTION_RTL, name = "rtl"),
13095             @EnumEntry(value = LAYOUT_DIRECTION_INHERIT, name = "inherit"),
13096             @EnumEntry(value = LAYOUT_DIRECTION_LOCALE, name = "locale")
13097     })
13098     @LayoutDir
getRawLayoutDirection()13099     public int getRawLayoutDirection() {
13100         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
13101     }
13102 
13103     /**
13104      * Set the layout direction for this view. This will propagate a reset of layout direction
13105      * resolution to the view's children and resolve layout direction for this view.
13106      *
13107      * @param layoutDirection the layout direction to set. Should be one of:
13108      *
13109      * {@link #LAYOUT_DIRECTION_LTR},
13110      * {@link #LAYOUT_DIRECTION_RTL},
13111      * {@link #LAYOUT_DIRECTION_INHERIT},
13112      * {@link #LAYOUT_DIRECTION_LOCALE}.
13113      *
13114      * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
13115      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
13116      * will return the default {@link #LAYOUT_DIRECTION_LTR}.
13117      *
13118      * @attr ref android.R.styleable#View_layoutDirection
13119      */
13120     @RemotableViewMethod
setLayoutDirection(@ayoutDir int layoutDirection)13121     public void setLayoutDirection(@LayoutDir int layoutDirection) {
13122         if (getRawLayoutDirection() != layoutDirection) {
13123             // Reset the current layout direction and the resolved one
13124             mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
13125             resetRtlProperties();
13126             // Set the new layout direction (filtered)
13127             mPrivateFlags2 |=
13128                     ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
13129             // We need to resolve all RTL properties as they all depend on layout direction
13130             resolveRtlPropertiesIfNeeded();
13131             requestLayout();
13132             invalidate(true);
13133         }
13134     }
13135 
13136     /**
13137      * Returns the resolved layout direction for this view.
13138      *
13139      * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
13140      * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
13141      *
13142      * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
13143      * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
13144      *
13145      * @attr ref android.R.styleable#View_layoutDirection
13146      */
13147     @ViewDebug.ExportedProperty(category = "layout", mapping = {
13148         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
13149         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
13150     })
13151     @InspectableProperty(enumMapping = {
13152             @EnumEntry(value = LAYOUT_DIRECTION_LTR, name = "ltr"),
13153             @EnumEntry(value = LAYOUT_DIRECTION_RTL, name = "rtl")
13154     })
13155     @ResolvedLayoutDir
getLayoutDirection()13156     public int getLayoutDirection() {
13157         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
13158         if (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
13159             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
13160             return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
13161         }
13162         return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
13163                 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
13164     }
13165 
13166     /**
13167      * Indicates whether or not this view's layout is right-to-left. This is resolved from
13168      * layout attribute and/or the inherited value from the parent
13169      *
13170      * @return true if the layout is right-to-left.
13171      *
13172      * @hide
13173      */
13174     @ViewDebug.ExportedProperty(category = "layout")
13175     @UnsupportedAppUsage
isLayoutRtl()13176     public boolean isLayoutRtl() {
13177         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
13178     }
13179 
13180     /**
13181      * Indicates whether the view is currently tracking transient state that the
13182      * app should not need to concern itself with saving and restoring, but that
13183      * the framework should take special note to preserve when possible.
13184      *
13185      * <p>A view with transient state cannot be trivially rebound from an external
13186      * data source, such as an adapter binding item views in a list. This may be
13187      * because the view is performing an animation, tracking user selection
13188      * of content, or similar.</p>
13189      *
13190      * @return true if the view has transient state
13191      */
13192     @ViewDebug.ExportedProperty(category = "layout")
hasTransientState()13193     public boolean hasTransientState() {
13194         return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
13195     }
13196 
13197     /**
13198      * Set whether this view is currently tracking transient state that the
13199      * framework should attempt to preserve when possible. This flag is reference counted,
13200      * so every call to setHasTransientState(true) should be paired with a later call
13201      * to setHasTransientState(false).
13202      *
13203      * <p>A view with transient state cannot be trivially rebound from an external
13204      * data source, such as an adapter binding item views in a list. This may be
13205      * because the view is performing an animation, tracking user selection
13206      * of content, or similar.</p>
13207      *
13208      * @param hasTransientState true if this view has transient state
13209      */
setHasTransientState(boolean hasTransientState)13210     public void setHasTransientState(boolean hasTransientState) {
13211         final boolean oldHasTransientState = hasTransientState();
13212         mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
13213                 mTransientStateCount - 1;
13214         if (mTransientStateCount < 0) {
13215             mTransientStateCount = 0;
13216             Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
13217                     "unmatched pair of setHasTransientState calls");
13218         } else if ((hasTransientState && mTransientStateCount == 1) ||
13219                 (!hasTransientState && mTransientStateCount == 0)) {
13220             // update flag if we've just incremented up from 0 or decremented down to 0
13221             mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
13222                     (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
13223             final boolean newHasTransientState = hasTransientState();
13224             if (mParent != null && newHasTransientState != oldHasTransientState) {
13225                 try {
13226                     mParent.childHasTransientStateChanged(this, newHasTransientState);
13227                 } catch (AbstractMethodError e) {
13228                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
13229                             " does not fully implement ViewParent", e);
13230                 }
13231             }
13232         }
13233     }
13234 
13235     /**
13236      * Set the view is tracking translation transient state. This flag is used to check if the view
13237      * need to call setHasTransientState(false) to reset transient state that set when starting
13238      * translation.
13239      *
13240      * @param hasTranslationTransientState true if this view has translation transient state
13241      * @hide
13242      */
setHasTranslationTransientState(boolean hasTranslationTransientState)13243     public void setHasTranslationTransientState(boolean hasTranslationTransientState) {
13244         if (hasTranslationTransientState) {
13245             mPrivateFlags4 |= PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE;
13246         } else {
13247             mPrivateFlags4 &= ~PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE;
13248         }
13249     }
13250 
13251     /**
13252      * @hide
13253      */
hasTranslationTransientState()13254     public boolean hasTranslationTransientState() {
13255         return (mPrivateFlags4 & PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE)
13256                 == PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE;
13257     }
13258 
13259     /**
13260      * @hide
13261      */
clearTranslationState()13262     public void clearTranslationState() {
13263         if (mViewTranslationCallback != null) {
13264             mViewTranslationCallback.onClearTranslation(this);
13265         }
13266         clearViewTranslationResponse();
13267         if (hasTranslationTransientState()) {
13268             setHasTransientState(false);
13269             setHasTranslationTransientState(false);
13270         }
13271     }
13272 
13273     /**
13274      * Returns true if this view is currently attached to a window.
13275      */
isAttachedToWindow()13276     public boolean isAttachedToWindow() {
13277         return mAttachInfo != null;
13278     }
13279 
13280     /**
13281      * Returns true if this view has been through at least one layout since it
13282      * was last attached to or detached from a window.
13283      */
isLaidOut()13284     public boolean isLaidOut() {
13285         return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
13286     }
13287 
13288     /**
13289      * @return {@code true} if laid-out and not about to do another layout.
13290      */
isLayoutValid()13291     boolean isLayoutValid() {
13292         return isLaidOut() && ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == 0);
13293     }
13294 
13295     /**
13296      * If this view doesn't do any drawing on its own, set this flag to
13297      * allow further optimizations. By default, this flag is not set on
13298      * View, but could be set on some View subclasses such as ViewGroup.
13299      *
13300      * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
13301      * you should clear this flag.
13302      *
13303      * @param willNotDraw whether or not this View draw on its own
13304      */
setWillNotDraw(boolean willNotDraw)13305     public void setWillNotDraw(boolean willNotDraw) {
13306         setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
13307     }
13308 
13309     /**
13310      * Returns whether or not this View draws on its own.
13311      *
13312      * @return true if this view has nothing to draw, false otherwise
13313      */
13314     @ViewDebug.ExportedProperty(category = "drawing")
willNotDraw()13315     public boolean willNotDraw() {
13316         return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
13317     }
13318 
13319     /**
13320      * When a View's drawing cache is enabled, drawing is redirected to an
13321      * offscreen bitmap. Some views, like an ImageView, must be able to
13322      * bypass this mechanism if they already draw a single bitmap, to avoid
13323      * unnecessary usage of the memory.
13324      *
13325      * @param willNotCacheDrawing true if this view does not cache its
13326      *        drawing, false otherwise
13327      *
13328      * @deprecated The view drawing cache was largely made obsolete with the introduction of
13329      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
13330      * layers are largely unnecessary and can easily result in a net loss in performance due to the
13331      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
13332      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
13333      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
13334      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
13335      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
13336      * software-rendered usages are discouraged and have compatibility issues with hardware-only
13337      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
13338      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
13339      * reports or unit testing the {@link PixelCopy} API is recommended.
13340      */
13341     @Deprecated
setWillNotCacheDrawing(boolean willNotCacheDrawing)13342     public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
13343         setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
13344     }
13345 
13346     /**
13347      * Returns whether or not this View can cache its drawing or not.
13348      *
13349      * @return true if this view does not cache its drawing, false otherwise
13350      *
13351      * @deprecated The view drawing cache was largely made obsolete with the introduction of
13352      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
13353      * layers are largely unnecessary and can easily result in a net loss in performance due to the
13354      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
13355      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
13356      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
13357      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
13358      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
13359      * software-rendered usages are discouraged and have compatibility issues with hardware-only
13360      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
13361      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
13362      * reports or unit testing the {@link PixelCopy} API is recommended.
13363      */
13364     @ViewDebug.ExportedProperty(category = "drawing")
13365     @Deprecated
willNotCacheDrawing()13366     public boolean willNotCacheDrawing() {
13367         return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
13368     }
13369 
13370     /**
13371      * Indicates whether this view reacts to click events or not.
13372      *
13373      * @return true if the view is clickable, false otherwise
13374      *
13375      * @see #setClickable(boolean)
13376      * @attr ref android.R.styleable#View_clickable
13377      */
13378     @ViewDebug.ExportedProperty
13379     @InspectableProperty
isClickable()13380     public boolean isClickable() {
13381         return (mViewFlags & CLICKABLE) == CLICKABLE;
13382     }
13383 
13384     /**
13385      * Enables or disables click events for this view. When a view
13386      * is clickable it will change its state to "pressed" on every click.
13387      * Subclasses should set the view clickable to visually react to
13388      * user's clicks.
13389      *
13390      * @param clickable true to make the view clickable, false otherwise
13391      *
13392      * @see #isClickable()
13393      * @attr ref android.R.styleable#View_clickable
13394      */
setClickable(boolean clickable)13395     public void setClickable(boolean clickable) {
13396         setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
13397     }
13398 
13399     /**
13400      * Enables or disables click events for this view when disabled.
13401      *
13402      * @param clickableWhenDisabled true to make the view clickable, false otherwise
13403      *
13404      * @attr ref android.R.styleable#View_allowClickWhenDisabled
13405      */
setAllowClickWhenDisabled(boolean clickableWhenDisabled)13406     public void setAllowClickWhenDisabled(boolean clickableWhenDisabled) {
13407         if (clickableWhenDisabled) {
13408             mPrivateFlags4 |= PFLAG4_ALLOW_CLICK_WHEN_DISABLED;
13409         } else {
13410             mPrivateFlags4 &= ~PFLAG4_ALLOW_CLICK_WHEN_DISABLED;
13411         }
13412     }
13413 
13414     /**
13415      * Indicates whether this view reacts to long click events or not.
13416      *
13417      * @return true if the view is long clickable, false otherwise
13418      *
13419      * @see #setLongClickable(boolean)
13420      * @attr ref android.R.styleable#View_longClickable
13421      */
13422     @InspectableProperty
isLongClickable()13423     public boolean isLongClickable() {
13424         return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
13425     }
13426 
13427     /**
13428      * Enables or disables long click events for this view. When a view is long
13429      * clickable it reacts to the user holding down the button for a longer
13430      * duration than a tap. This event can either launch the listener or a
13431      * context menu.
13432      *
13433      * @param longClickable true to make the view long clickable, false otherwise
13434      * @see #isLongClickable()
13435      * @attr ref android.R.styleable#View_longClickable
13436      */
setLongClickable(boolean longClickable)13437     public void setLongClickable(boolean longClickable) {
13438         setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
13439     }
13440 
13441     /**
13442      * Indicates whether this view reacts to context clicks or not.
13443      *
13444      * @return true if the view is context clickable, false otherwise
13445      * @see #setContextClickable(boolean)
13446      * @attr ref android.R.styleable#View_contextClickable
13447      */
13448     @InspectableProperty
isContextClickable()13449     public boolean isContextClickable() {
13450         return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
13451     }
13452 
13453     /**
13454      * Enables or disables context clicking for this view. This event can launch the listener.
13455      *
13456      * @param contextClickable true to make the view react to a context click, false otherwise
13457      * @see #isContextClickable()
13458      * @attr ref android.R.styleable#View_contextClickable
13459      */
setContextClickable(boolean contextClickable)13460     public void setContextClickable(boolean contextClickable) {
13461         setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
13462     }
13463 
13464     /**
13465      * Sets the pressed state for this view and provides a touch coordinate for
13466      * animation hinting.
13467      *
13468      * @param pressed Pass true to set the View's internal state to "pressed",
13469      *            or false to reverts the View's internal state from a
13470      *            previously set "pressed" state.
13471      * @param x The x coordinate of the touch that caused the press
13472      * @param y The y coordinate of the touch that caused the press
13473      */
setPressed(boolean pressed, float x, float y)13474     private void setPressed(boolean pressed, float x, float y) {
13475         if (pressed) {
13476             drawableHotspotChanged(x, y);
13477         }
13478 
13479         setPressed(pressed);
13480     }
13481 
13482     /**
13483      * Sets the pressed state for this view.
13484      *
13485      * @see #isClickable()
13486      * @see #setClickable(boolean)
13487      *
13488      * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
13489      *        the View's internal state from a previously set "pressed" state.
13490      */
setPressed(boolean pressed)13491     public void setPressed(boolean pressed) {
13492         final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
13493 
13494         if (pressed) {
13495             mPrivateFlags |= PFLAG_PRESSED;
13496         } else {
13497             mPrivateFlags &= ~PFLAG_PRESSED;
13498         }
13499 
13500         if (needsRefresh) {
13501             refreshDrawableState();
13502         }
13503         dispatchSetPressed(pressed);
13504     }
13505 
13506     /**
13507      * Dispatch setPressed to all of this View's children.
13508      *
13509      * @see #setPressed(boolean)
13510      *
13511      * @param pressed The new pressed state
13512      */
dispatchSetPressed(boolean pressed)13513     protected void dispatchSetPressed(boolean pressed) {
13514     }
13515 
13516     /**
13517      * Indicates whether the view is currently in pressed state. Unless
13518      * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
13519      * the pressed state.
13520      *
13521      * @see #setPressed(boolean)
13522      * @see #isClickable()
13523      * @see #setClickable(boolean)
13524      *
13525      * @return true if the view is currently pressed, false otherwise
13526      */
13527     @ViewDebug.ExportedProperty
13528     @InspectableProperty(hasAttributeId = false)
isPressed()13529     public boolean isPressed() {
13530         return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
13531     }
13532 
13533     /**
13534      * @hide
13535      * Indicates whether this view will participate in data collection through
13536      * {@link ViewStructure}.  If true, it will not provide any data
13537      * for itself or its children.  If false, the normal data collection will be allowed.
13538      *
13539      * @return Returns false if assist data collection is not blocked, else true.
13540      *
13541      * @see #setAssistBlocked(boolean)
13542      * @attr ref android.R.styleable#View_assistBlocked
13543      */
isAssistBlocked()13544     public boolean isAssistBlocked() {
13545         return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
13546     }
13547 
13548     /**
13549      * @hide
13550      * Controls whether assist data collection from this view and its children is enabled
13551      * (that is, whether {@link #onProvideStructure} and
13552      * {@link #onProvideVirtualStructure} will be called).  The default value is false,
13553      * allowing normal assist collection.  Setting this to false will disable assist collection.
13554      *
13555      * @param enabled Set to true to <em>disable</em> assist data collection, or false
13556      * (the default) to allow it.
13557      *
13558      * @see #isAssistBlocked()
13559      * @see #onProvideStructure
13560      * @see #onProvideVirtualStructure
13561      * @attr ref android.R.styleable#View_assistBlocked
13562      */
13563     @UnsupportedAppUsage
setAssistBlocked(boolean enabled)13564     public void setAssistBlocked(boolean enabled) {
13565         if (enabled) {
13566             mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
13567         } else {
13568             mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
13569         }
13570     }
13571 
13572     /**
13573      * Indicates whether this view will save its state (that is,
13574      * whether its {@link #onSaveInstanceState} method will be called).
13575      *
13576      * @return Returns true if the view state saving is enabled, else false.
13577      *
13578      * @see #setSaveEnabled(boolean)
13579      * @attr ref android.R.styleable#View_saveEnabled
13580      */
13581     @InspectableProperty
isSaveEnabled()13582     public boolean isSaveEnabled() {
13583         return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
13584     }
13585 
13586     /**
13587      * Controls whether the saving of this view's state is
13588      * enabled (that is, whether its {@link #onSaveInstanceState} method
13589      * will be called).  Note that even if freezing is enabled, the
13590      * view still must have an id assigned to it (via {@link #setId(int)})
13591      * for its state to be saved.  This flag can only disable the
13592      * saving of this view; any child views may still have their state saved.
13593      *
13594      * @param enabled Set to false to <em>disable</em> state saving, or true
13595      * (the default) to allow it.
13596      *
13597      * @see #isSaveEnabled()
13598      * @see #setId(int)
13599      * @see #onSaveInstanceState()
13600      * @attr ref android.R.styleable#View_saveEnabled
13601      */
setSaveEnabled(boolean enabled)13602     public void setSaveEnabled(boolean enabled) {
13603         setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
13604     }
13605 
13606     /**
13607      * Gets whether the framework should discard touches when the view's
13608      * window is obscured by another visible window at the touched location.
13609      * Refer to the {@link View} security documentation for more details.
13610      *
13611      * @return True if touch filtering is enabled.
13612      *
13613      * @see #setFilterTouchesWhenObscured(boolean)
13614      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
13615      */
13616     @ViewDebug.ExportedProperty
13617     @InspectableProperty
getFilterTouchesWhenObscured()13618     public boolean getFilterTouchesWhenObscured() {
13619         return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
13620     }
13621 
13622     /**
13623      * Sets whether the framework should discard touches when the view's
13624      * window is obscured by another visible window at the touched location.
13625      * Refer to the {@link View} security documentation for more details.
13626      *
13627      * @param enabled True if touch filtering should be enabled.
13628      *
13629      * @see #getFilterTouchesWhenObscured
13630      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
13631      */
setFilterTouchesWhenObscured(boolean enabled)13632     public void setFilterTouchesWhenObscured(boolean enabled) {
13633         setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
13634                 FILTER_TOUCHES_WHEN_OBSCURED);
13635         calculateAccessibilityDataSensitive();
13636     }
13637 
13638     /**
13639      * Indicates whether the entire hierarchy under this view will save its
13640      * state when a state saving traversal occurs from its parent.  The default
13641      * is true; if false, these views will not be saved unless
13642      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
13643      *
13644      * @return Returns true if the view state saving from parent is enabled, else false.
13645      *
13646      * @see #setSaveFromParentEnabled(boolean)
13647      */
isSaveFromParentEnabled()13648     public boolean isSaveFromParentEnabled() {
13649         return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
13650     }
13651 
13652     /**
13653      * Controls whether the entire hierarchy under this view will save its
13654      * state when a state saving traversal occurs from its parent.  The default
13655      * is true; if false, these views will not be saved unless
13656      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
13657      *
13658      * @param enabled Set to false to <em>disable</em> state saving, or true
13659      * (the default) to allow it.
13660      *
13661      * @see #isSaveFromParentEnabled()
13662      * @see #setId(int)
13663      * @see #onSaveInstanceState()
13664      */
setSaveFromParentEnabled(boolean enabled)13665     public void setSaveFromParentEnabled(boolean enabled) {
13666         setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
13667     }
13668 
13669 
13670     /**
13671      * Returns whether this View is currently able to take focus.
13672      *
13673      * @return True if this view can take focus, or false otherwise.
13674      */
13675     @ViewDebug.ExportedProperty(category = "focus")
isFocusable()13676     public final boolean isFocusable() {
13677         return FOCUSABLE == (mViewFlags & FOCUSABLE);
13678     }
13679 
13680     /**
13681      * Returns the focusable setting for this view.
13682      *
13683      * @return One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE}, or {@link #FOCUSABLE_AUTO}.
13684      * @attr ref android.R.styleable#View_focusable
13685      */
13686     @ViewDebug.ExportedProperty(mapping = {
13687             @ViewDebug.IntToString(from = NOT_FOCUSABLE, to = "NOT_FOCUSABLE"),
13688             @ViewDebug.IntToString(from = FOCUSABLE, to = "FOCUSABLE"),
13689             @ViewDebug.IntToString(from = FOCUSABLE_AUTO, to = "FOCUSABLE_AUTO")
13690             }, category = "focus")
13691     @InspectableProperty(enumMapping = {
13692             @EnumEntry(value = NOT_FOCUSABLE, name = "false"),
13693             @EnumEntry(value = FOCUSABLE, name = "true"),
13694             @EnumEntry(value = FOCUSABLE_AUTO, name = "auto")
13695     })
13696     @Focusable
getFocusable()13697     public int getFocusable() {
13698         return (mViewFlags & FOCUSABLE_AUTO) > 0 ? FOCUSABLE_AUTO : mViewFlags & FOCUSABLE;
13699     }
13700 
13701     /**
13702      * When a view is focusable, it may not want to take focus when in touch mode.
13703      * For example, a button would like focus when the user is navigating via a D-pad
13704      * so that the user can click on it, but once the user starts touching the screen,
13705      * the button shouldn't take focus
13706      * @return Whether the view is focusable in touch mode.
13707      * @attr ref android.R.styleable#View_focusableInTouchMode
13708      */
13709     @ViewDebug.ExportedProperty(category = "focus")
13710     @InspectableProperty
isFocusableInTouchMode()13711     public final boolean isFocusableInTouchMode() {
13712         return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
13713     }
13714 
13715     /**
13716      * Returns whether the view should be treated as a focusable unit by screen reader
13717      * accessibility tools.
13718      * @see #setScreenReaderFocusable(boolean)
13719      *
13720      * @return Whether the view should be treated as a focusable unit by screen reader.
13721      *
13722      * @attr ref android.R.styleable#View_screenReaderFocusable
13723      */
13724     @InspectableProperty
isScreenReaderFocusable()13725     public boolean isScreenReaderFocusable() {
13726         return (mPrivateFlags3 & PFLAG3_SCREEN_READER_FOCUSABLE) != 0;
13727     }
13728 
13729     /**
13730      * Sets whether this View should be a focusable element for screen readers
13731      * and include non-focusable Views from its subtree when providing feedback.
13732      * <p>
13733      * Note: this is similar to using <a href="#attr_android:focusable">{@code android:focusable},
13734      * but does not impact input focus behavior.
13735      *
13736      * @param screenReaderFocusable Whether the view should be treated as a unit by screen reader
13737      *                              accessibility tools.
13738      *
13739      * @attr ref android.R.styleable#View_screenReaderFocusable
13740      */
setScreenReaderFocusable(boolean screenReaderFocusable)13741     public void setScreenReaderFocusable(boolean screenReaderFocusable) {
13742         updatePflags3AndNotifyA11yIfChanged(PFLAG3_SCREEN_READER_FOCUSABLE, screenReaderFocusable);
13743     }
13744 
13745     /**
13746      * Gets whether this view is a heading for accessibility purposes.
13747      *
13748      * @return {@code true} if the view is a heading, {@code false} otherwise.
13749      *
13750      * @attr ref android.R.styleable#View_accessibilityHeading
13751      */
13752     @InspectableProperty
isAccessibilityHeading()13753     public boolean isAccessibilityHeading() {
13754         return (mPrivateFlags3 & PFLAG3_ACCESSIBILITY_HEADING) != 0;
13755     }
13756 
13757     /**
13758      * Set if view is a heading for a section of content for accessibility purposes.
13759      * <p>
13760      * Users of some accessibility services can choose to navigate between headings
13761      * instead of between paragraphs, words, etc. Apps that provide headings on
13762      * sections of text can help the text navigation experience.
13763      *
13764      * @param isHeading {@code true} if the view is a heading, {@code false} otherwise.
13765      *
13766      * @attr ref android.R.styleable#View_accessibilityHeading
13767      */
setAccessibilityHeading(boolean isHeading)13768     public void setAccessibilityHeading(boolean isHeading) {
13769         updatePflags3AndNotifyA11yIfChanged(PFLAG3_ACCESSIBILITY_HEADING, isHeading);
13770     }
13771 
updatePflags3AndNotifyA11yIfChanged(int mask, boolean newValue)13772     private void updatePflags3AndNotifyA11yIfChanged(int mask, boolean newValue) {
13773         int pflags3 = mPrivateFlags3;
13774         if (newValue) {
13775             pflags3 |= mask;
13776         } else {
13777             pflags3 &= ~mask;
13778         }
13779 
13780         if (pflags3 != mPrivateFlags3) {
13781             mPrivateFlags3 = pflags3;
13782             notifyViewAccessibilityStateChangedIfNeeded(
13783                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
13784         }
13785     }
13786 
13787     /**
13788      * Find the nearest view in the specified direction that can take focus.
13789      * This does not actually give focus to that view.
13790      *
13791      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
13792      *
13793      * @return The nearest focusable in the specified direction, or null if none
13794      *         can be found.
13795      */
focusSearch(@ocusRealDirection int direction)13796     public View focusSearch(@FocusRealDirection int direction) {
13797         if (mParent != null) {
13798             return mParent.focusSearch(this, direction);
13799         } else {
13800             return null;
13801         }
13802     }
13803 
13804     /**
13805      * Returns whether this View is a root of a keyboard navigation cluster.
13806      *
13807      * @return True if this view is a root of a cluster, or false otherwise.
13808      * @attr ref android.R.styleable#View_keyboardNavigationCluster
13809      */
13810     @ViewDebug.ExportedProperty(category = "focus")
13811     @InspectableProperty
isKeyboardNavigationCluster()13812     public final boolean isKeyboardNavigationCluster() {
13813         return (mPrivateFlags3 & PFLAG3_CLUSTER) != 0;
13814     }
13815 
13816     /**
13817      * Searches up the view hierarchy to find the top-most cluster. All deeper/nested clusters
13818      * will be ignored.
13819      *
13820      * @return the keyboard navigation cluster that this view is in (can be this view)
13821      *         or {@code null} if not in one
13822      */
findKeyboardNavigationCluster()13823     View findKeyboardNavigationCluster() {
13824         if (mParent instanceof View) {
13825             View cluster = ((View) mParent).findKeyboardNavigationCluster();
13826             if (cluster != null) {
13827                 return cluster;
13828             } else if (isKeyboardNavigationCluster()) {
13829                 return this;
13830             }
13831         }
13832         return null;
13833     }
13834 
13835     /**
13836      * Set whether this view is a root of a keyboard navigation cluster.
13837      *
13838      * @param isCluster If true, this view is a root of a cluster.
13839      *
13840      * @attr ref android.R.styleable#View_keyboardNavigationCluster
13841      */
setKeyboardNavigationCluster(boolean isCluster)13842     public void setKeyboardNavigationCluster(boolean isCluster) {
13843         if (isCluster) {
13844             mPrivateFlags3 |= PFLAG3_CLUSTER;
13845         } else {
13846             mPrivateFlags3 &= ~PFLAG3_CLUSTER;
13847         }
13848     }
13849 
13850     /**
13851      * Sets this View as the one which receives focus the next time cluster navigation jumps
13852      * to the cluster containing this View. This does NOT change focus even if the cluster
13853      * containing this view is current.
13854      *
13855      * @hide
13856      */
13857     @TestApi
setFocusedInCluster()13858     public final void setFocusedInCluster() {
13859         setFocusedInCluster(findKeyboardNavigationCluster());
13860     }
13861 
setFocusedInCluster(View cluster)13862     private void setFocusedInCluster(View cluster) {
13863         if (this instanceof ViewGroup) {
13864             ((ViewGroup) this).mFocusedInCluster = null;
13865         }
13866         if (cluster == this) {
13867             return;
13868         }
13869         ViewParent parent = mParent;
13870         View child = this;
13871         while (parent instanceof ViewGroup) {
13872             ((ViewGroup) parent).mFocusedInCluster = child;
13873             if (parent == cluster) {
13874                 break;
13875             }
13876             child = (View) parent;
13877             parent = parent.getParent();
13878         }
13879     }
13880 
updateFocusedInCluster(View oldFocus, @FocusDirection int direction)13881     private void updateFocusedInCluster(View oldFocus, @FocusDirection int direction) {
13882         if (oldFocus != null) {
13883             View oldCluster = oldFocus.findKeyboardNavigationCluster();
13884             View cluster = findKeyboardNavigationCluster();
13885             if (oldCluster != cluster) {
13886                 // Going from one cluster to another, so save last-focused.
13887                 // This covers cluster jumps because they are always FOCUS_DOWN
13888                 oldFocus.setFocusedInCluster(oldCluster);
13889                 if (!(oldFocus.mParent instanceof ViewGroup)) {
13890                     return;
13891                 }
13892                 if (direction == FOCUS_FORWARD || direction == FOCUS_BACKWARD) {
13893                     // This is a result of ordered navigation so consider navigation through
13894                     // the previous cluster "complete" and clear its last-focused memory.
13895                     ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
13896                 } else if (oldFocus instanceof ViewGroup
13897                         && ((ViewGroup) oldFocus).getDescendantFocusability()
13898                                 == ViewGroup.FOCUS_AFTER_DESCENDANTS
13899                         && ViewRootImpl.isViewDescendantOf(this, oldFocus)) {
13900                     // This means oldFocus is not focusable since it obviously has a focusable
13901                     // child (this). Don't restore focus to it in the future.
13902                     ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
13903                 }
13904             }
13905         }
13906     }
13907 
13908     /**
13909      * Returns whether this View should receive focus when the focus is restored for the view
13910      * hierarchy containing this view.
13911      * <p>
13912      * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
13913      * window or serves as a target of cluster navigation.
13914      *
13915      * @see #restoreDefaultFocus()
13916      *
13917      * @return {@code true} if this view is the default-focus view, {@code false} otherwise
13918      * @attr ref android.R.styleable#View_focusedByDefault
13919      */
13920     @ViewDebug.ExportedProperty(category = "focus")
13921     @InspectableProperty
isFocusedByDefault()13922     public final boolean isFocusedByDefault() {
13923         return (mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0;
13924     }
13925 
13926     /**
13927      * Sets whether this View should receive focus when the focus is restored for the view
13928      * hierarchy containing this view.
13929      * <p>
13930      * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
13931      * window or serves as a target of cluster navigation.
13932      *
13933      * @param isFocusedByDefault {@code true} to set this view as the default-focus view,
13934      *                           {@code false} otherwise.
13935      *
13936      * @see #restoreDefaultFocus()
13937      *
13938      * @attr ref android.R.styleable#View_focusedByDefault
13939      */
13940     @RemotableViewMethod
setFocusedByDefault(boolean isFocusedByDefault)13941     public void setFocusedByDefault(boolean isFocusedByDefault) {
13942         if (isFocusedByDefault == ((mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0)) {
13943             return;
13944         }
13945 
13946         if (isFocusedByDefault) {
13947             mPrivateFlags3 |= PFLAG3_FOCUSED_BY_DEFAULT;
13948         } else {
13949             mPrivateFlags3 &= ~PFLAG3_FOCUSED_BY_DEFAULT;
13950         }
13951 
13952         if (mParent instanceof ViewGroup) {
13953             if (isFocusedByDefault) {
13954                 ((ViewGroup) mParent).setDefaultFocus(this);
13955             } else {
13956                 ((ViewGroup) mParent).clearDefaultFocus(this);
13957             }
13958         }
13959     }
13960 
13961     /**
13962      * Returns whether the view hierarchy with this view as a root contain a default-focus view.
13963      *
13964      * @return {@code true} if this view has default focus, {@code false} otherwise
13965      */
hasDefaultFocus()13966     boolean hasDefaultFocus() {
13967         return isFocusedByDefault();
13968     }
13969 
13970     /**
13971      * Find the nearest keyboard navigation cluster in the specified direction.
13972      * This does not actually give focus to that cluster.
13973      *
13974      * @param currentCluster The starting point of the search. Null means the current cluster is not
13975      *                       found yet
13976      * @param direction Direction to look
13977      *
13978      * @return The nearest keyboard navigation cluster in the specified direction, or null if none
13979      *         can be found
13980      */
keyboardNavigationClusterSearch(View currentCluster, @FocusDirection int direction)13981     public View keyboardNavigationClusterSearch(View currentCluster,
13982             @FocusDirection int direction) {
13983         if (isKeyboardNavigationCluster()) {
13984             currentCluster = this;
13985         }
13986         if (isRootNamespace()) {
13987             // Root namespace means we should consider ourselves the top of the
13988             // tree for group searching; otherwise we could be group searching
13989             // into other tabs.  see LocalActivityManager and TabHost for more info.
13990             return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
13991                     this, currentCluster, direction);
13992         } else if (mParent != null) {
13993             return mParent.keyboardNavigationClusterSearch(currentCluster, direction);
13994         }
13995         return null;
13996     }
13997 
13998     /**
13999      * This method is the last chance for the focused view and its ancestors to
14000      * respond to an arrow key. This is called when the focused view did not
14001      * consume the key internally, nor could the view system find a new view in
14002      * the requested direction to give focus to.
14003      *
14004      * @param focused The currently focused view.
14005      * @param direction The direction focus wants to move. One of FOCUS_UP,
14006      *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
14007      * @return True if the this view consumed this unhandled move.
14008      */
dispatchUnhandledMove(View focused, @FocusRealDirection int direction)14009     public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
14010         return false;
14011     }
14012 
14013     /**
14014      * Sets whether this View should use a default focus highlight when it gets focused but doesn't
14015      * have {@link android.R.attr#state_focused} defined in its background.
14016      *
14017      * @param defaultFocusHighlightEnabled {@code true} to set this view to use a default focus
14018      *                                      highlight, {@code false} otherwise.
14019      *
14020      * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
14021      */
setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled)14022     public void setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled) {
14023         mDefaultFocusHighlightEnabled = defaultFocusHighlightEnabled;
14024     }
14025 
14026     /**
14027      * Returns whether this View should use a default focus highlight when it gets focused but
14028      * doesn't have {@link android.R.attr#state_focused} defined in its background.
14029      *
14030      * @return True if this View should use a default focus highlight.
14031      * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
14032      */
14033     @ViewDebug.ExportedProperty(category = "focus")
14034     @InspectableProperty
getDefaultFocusHighlightEnabled()14035     public final boolean getDefaultFocusHighlightEnabled() {
14036         return mDefaultFocusHighlightEnabled;
14037     }
14038 
14039     /**
14040      * If a user manually specified the next view id for a particular direction,
14041      * use the root to look up the view.
14042      * @param root The root view of the hierarchy containing this view.
14043      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
14044      * or FOCUS_BACKWARD.
14045      * @return The user specified next view, or null if there is none.
14046      */
findUserSetNextFocus(View root, @FocusDirection int direction)14047     View findUserSetNextFocus(View root, @FocusDirection int direction) {
14048         switch (direction) {
14049             case FOCUS_LEFT:
14050                 if (mNextFocusLeftId == View.NO_ID) return null;
14051                 return findViewInsideOutShouldExist(root, mNextFocusLeftId);
14052             case FOCUS_RIGHT:
14053                 if (mNextFocusRightId == View.NO_ID) return null;
14054                 return findViewInsideOutShouldExist(root, mNextFocusRightId);
14055             case FOCUS_UP:
14056                 if (mNextFocusUpId == View.NO_ID) return null;
14057                 return findViewInsideOutShouldExist(root, mNextFocusUpId);
14058             case FOCUS_DOWN:
14059                 if (mNextFocusDownId == View.NO_ID) return null;
14060                 return findViewInsideOutShouldExist(root, mNextFocusDownId);
14061             case FOCUS_FORWARD:
14062                 if (mNextFocusForwardId == View.NO_ID) return null;
14063                 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
14064             case FOCUS_BACKWARD: {
14065                 if (mID == View.NO_ID) return null;
14066                 final View rootView = root;
14067                 final View startView = this;
14068                 // Since we have forward links but no backward links, we need to find the view that
14069                 // forward links to this view. We can't just find the view with the specified ID
14070                 // because view IDs need not be unique throughout the tree.
14071                 return root.findViewByPredicateInsideOut(startView,
14072                     t -> findViewInsideOutShouldExist(rootView, t, t.mNextFocusForwardId)
14073                             == startView);
14074             }
14075         }
14076         return null;
14077     }
14078 
14079     /**
14080      * If a user manually specified the next keyboard-navigation cluster for a particular direction,
14081      * use the root to look up the view.
14082      *
14083      * @param root the root view of the hierarchy containing this view
14084      * @param direction {@link #FOCUS_FORWARD} or {@link #FOCUS_BACKWARD}
14085      * @return the user-specified next cluster, or {@code null} if there is none
14086      */
findUserSetNextKeyboardNavigationCluster(View root, @FocusDirection int direction)14087     View findUserSetNextKeyboardNavigationCluster(View root, @FocusDirection int direction) {
14088         switch (direction) {
14089             case FOCUS_FORWARD:
14090                 if (mNextClusterForwardId == View.NO_ID) return null;
14091                 return findViewInsideOutShouldExist(root, mNextClusterForwardId);
14092             case FOCUS_BACKWARD: {
14093                 if (mID == View.NO_ID) return null;
14094                 final int id = mID;
14095                 return root.findViewByPredicateInsideOut(this,
14096                         (Predicate<View>) t -> t.mNextClusterForwardId == id);
14097             }
14098         }
14099         return null;
14100     }
14101 
findViewInsideOutShouldExist(View root, int id)14102     private View findViewInsideOutShouldExist(View root, int id) {
14103         return findViewInsideOutShouldExist(root, this, id);
14104     }
14105 
findViewInsideOutShouldExist(View root, View start, int id)14106     private View findViewInsideOutShouldExist(View root, View start, int id) {
14107         if (mMatchIdPredicate == null) {
14108             mMatchIdPredicate = new MatchIdPredicate();
14109         }
14110         mMatchIdPredicate.mId = id;
14111         View result = root.findViewByPredicateInsideOut(start, mMatchIdPredicate);
14112         if (result == null) {
14113             Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
14114         }
14115         return result;
14116     }
14117 
14118     /**
14119      * Find and return all focusable views that are descendants of this view,
14120      * possibly including this view if it is focusable itself.
14121      *
14122      * @param direction The direction of the focus
14123      * @return A list of focusable views
14124      */
getFocusables(@ocusDirection int direction)14125     public ArrayList<View> getFocusables(@FocusDirection int direction) {
14126         ArrayList<View> result = new ArrayList<View>(24);
14127         addFocusables(result, direction);
14128         return result;
14129     }
14130 
14131     /**
14132      * Add any focusable views that are descendants of this view (possibly
14133      * including this view if it is focusable itself) to views.  If we are in touch mode,
14134      * only add views that are also focusable in touch mode.
14135      *
14136      * @param views Focusable views found so far
14137      * @param direction The direction of the focus
14138      */
addFocusables(ArrayList<View> views, @FocusDirection int direction)14139     public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
14140         addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
14141     }
14142 
14143     /**
14144      * Adds any focusable views that are descendants of this view (possibly
14145      * including this view if it is focusable itself) to views. This method
14146      * adds all focusable views regardless if we are in touch mode or
14147      * only views focusable in touch mode if we are in touch mode or
14148      * only views that can take accessibility focus if accessibility is enabled
14149      * depending on the focusable mode parameter.
14150      *
14151      * @param views Focusable views found so far or null if all we are interested is
14152      *        the number of focusables.
14153      * @param direction The direction of the focus.
14154      * @param focusableMode The type of focusables to be added.
14155      *
14156      * @see #FOCUSABLES_ALL
14157      * @see #FOCUSABLES_TOUCH_MODE
14158      */
addFocusables(ArrayList<View> views, @FocusDirection int direction, @FocusableMode int focusableMode)14159     public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
14160             @FocusableMode int focusableMode) {
14161         if (views == null) {
14162             return;
14163         }
14164         if (!canTakeFocus()) {
14165             return;
14166         }
14167         if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
14168                 && !isFocusableInTouchMode()) {
14169             return;
14170         }
14171         views.add(this);
14172     }
14173 
14174     /**
14175      * Adds any keyboard navigation cluster roots that are descendants of this view (possibly
14176      * including this view if it is a cluster root itself) to views.
14177      *
14178      * @param views Keyboard navigation cluster roots found so far
14179      * @param direction Direction to look
14180      */
addKeyboardNavigationClusters( @onNull Collection<View> views, int direction)14181     public void addKeyboardNavigationClusters(
14182             @NonNull Collection<View> views,
14183             int direction) {
14184         if (!isKeyboardNavigationCluster()) {
14185             return;
14186         }
14187         if (!hasFocusable()) {
14188             return;
14189         }
14190         views.add(this);
14191     }
14192 
14193     /**
14194      * Finds the Views that contain given text. The containment is case insensitive.
14195      * The search is performed by either the text that the View renders or the content
14196      * description that describes the view for accessibility purposes and the view does
14197      * not render or both. Clients can specify how the search is to be performed via
14198      * passing the {@link #FIND_VIEWS_WITH_TEXT} and
14199      * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
14200      *
14201      * @param outViews The output list of matching Views.
14202      * @param searched The text to match against.
14203      *
14204      * @see #FIND_VIEWS_WITH_TEXT
14205      * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
14206      * @see #setContentDescription(CharSequence)
14207      */
findViewsWithText(ArrayList<View> outViews, CharSequence searched, @FindViewFlags int flags)14208     public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
14209             @FindViewFlags int flags) {
14210         if (getAccessibilityNodeProvider() != null) {
14211             if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
14212                 outViews.add(this);
14213             }
14214         } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
14215                 && (searched != null && searched.length() > 0)
14216                 && (mContentDescription != null && mContentDescription.length() > 0)) {
14217             String searchedLowerCase = searched.toString().toLowerCase();
14218             String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
14219             if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
14220                 outViews.add(this);
14221             }
14222         }
14223     }
14224 
14225     /**
14226      * Find and return all touchable views that are descendants of this view,
14227      * possibly including this view if it is touchable itself.
14228      *
14229      * @return A list of touchable views
14230      */
getTouchables()14231     public ArrayList<View> getTouchables() {
14232         ArrayList<View> result = new ArrayList<View>();
14233         addTouchables(result);
14234         return result;
14235     }
14236 
14237     /**
14238      * Add any touchable views that are descendants of this view (possibly
14239      * including this view if it is touchable itself) to views.
14240      *
14241      * @param views Touchable views found so far
14242      */
addTouchables(ArrayList<View> views)14243     public void addTouchables(ArrayList<View> views) {
14244         final int viewFlags = mViewFlags;
14245 
14246         if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
14247                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
14248                 && (viewFlags & ENABLED_MASK) == ENABLED) {
14249             views.add(this);
14250         }
14251     }
14252 
14253     /**
14254      * Returns whether this View is accessibility focused.
14255      *
14256      * @return True if this View is accessibility focused.
14257      */
14258     @InspectableProperty(hasAttributeId = false)
isAccessibilityFocused()14259     public boolean isAccessibilityFocused() {
14260         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
14261     }
14262 
14263     /**
14264      * Call this to try to give accessibility focus to this view.
14265      *
14266      * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
14267      * returns false or the view is no visible or the view already has accessibility
14268      * focus.
14269      *
14270      * See also {@link #focusSearch(int)}, which is what you call to say that you
14271      * have focus, and you want your parent to look for the next one.
14272      *
14273      * <p>
14274      * <b>Note:</b> Avoid setting accessibility focus. This is intended to be controlled by screen
14275      * readers. Apps changing focus can confuse screen readers, so the resulting behavior can vary
14276      * by device and screen reader version.
14277      *
14278      * @return Whether this view actually took accessibility focus.
14279      *
14280      * @hide
14281      */
14282     @UnsupportedAppUsage
requestAccessibilityFocus()14283     public boolean requestAccessibilityFocus() {
14284         AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
14285         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
14286             return false;
14287         }
14288         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
14289             return false;
14290         }
14291         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
14292             mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
14293             ViewRootImpl viewRootImpl = getViewRootImpl();
14294             if (viewRootImpl != null) {
14295                 viewRootImpl.setAccessibilityFocus(this, null);
14296             }
14297             invalidate();
14298             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
14299             return true;
14300         }
14301         return false;
14302     }
14303 
14304     /**
14305      * Call this to try to clear accessibility focus of this view.
14306      *
14307      * See also {@link #focusSearch(int)}, which is what you call to say that you
14308      * have focus, and you want your parent to look for the next one.
14309      *
14310      * @hide
14311      */
14312     @UnsupportedAppUsage
clearAccessibilityFocus()14313     public void clearAccessibilityFocus() {
14314         clearAccessibilityFocusNoCallbacks(0);
14315 
14316         // Clear the global reference of accessibility focus if this view or
14317         // any of its descendants had accessibility focus. This will NOT send
14318         // an event or update internal state if focus is cleared from a
14319         // descendant view, which may leave views in inconsistent states.
14320         final ViewRootImpl viewRootImpl = getViewRootImpl();
14321         if (viewRootImpl != null) {
14322             final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
14323             if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
14324                 viewRootImpl.setAccessibilityFocus(null, null);
14325             }
14326         }
14327     }
14328 
sendAccessibilityHoverEvent(int eventType)14329     private void sendAccessibilityHoverEvent(int eventType) {
14330         // Since we are not delivering to a client accessibility events from not
14331         // important views (unless the clinet request that) we need to fire the
14332         // event from the deepest view exposed to the client. As a consequence if
14333         // the user crosses a not exposed view the client will see enter and exit
14334         // of the exposed predecessor followed by and enter and exit of that same
14335         // predecessor when entering and exiting the not exposed descendant. This
14336         // is fine since the client has a clear idea which view is hovered at the
14337         // price of a couple more events being sent. This is a simple and
14338         // working solution.
14339         View source = this;
14340         while (true) {
14341             if (source.includeForAccessibility(false)) {
14342                 source.sendAccessibilityEvent(eventType);
14343                 return;
14344             }
14345             ViewParent parent = source.getParent();
14346             if (parent instanceof View) {
14347                 source = (View) parent;
14348             } else {
14349                 return;
14350             }
14351         }
14352     }
14353 
14354     /**
14355      * Clears accessibility focus without calling any callback methods
14356      * normally invoked in {@link #clearAccessibilityFocus()}. This method
14357      * is used separately from that one for clearing accessibility focus when
14358      * giving this focus to another view.
14359      *
14360      * @param action The action, if any, that led to focus being cleared. Set to
14361      * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
14362      * the window.
14363      */
clearAccessibilityFocusNoCallbacks(int action)14364     void clearAccessibilityFocusNoCallbacks(int action) {
14365         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
14366             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
14367             invalidate();
14368             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
14369                 AccessibilityEvent event = AccessibilityEvent.obtain(
14370                         AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
14371                 event.setAction(action);
14372                 if (mAccessibilityDelegate != null) {
14373                     mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
14374                 } else {
14375                     sendAccessibilityEventUnchecked(event);
14376                 }
14377             }
14378 
14379             updatePreferKeepClearForFocus();
14380         }
14381     }
14382 
14383     /**
14384      * Call this to try to give focus to a specific view or to one of its
14385      * descendants.
14386      *
14387      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
14388      * false), or if it can't be focused due to other conditions (not focusable in touch mode
14389      * ({@link #isFocusableInTouchMode}) while the device is in touch mode, not visible, not
14390      * enabled, or has no size).
14391      *
14392      * See also {@link #focusSearch(int)}, which is what you call to say that you
14393      * have focus, and you want your parent to look for the next one.
14394      *
14395      * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
14396      * {@link #FOCUS_DOWN} and <code>null</code>.
14397      *
14398      * @return Whether this view or one of its descendants actually took focus.
14399      */
requestFocus()14400     public final boolean requestFocus() {
14401         return requestFocus(View.FOCUS_DOWN);
14402     }
14403 
14404     /**
14405      * This will request focus for whichever View was last focused within this
14406      * cluster before a focus-jump out of it.
14407      *
14408      * @hide
14409      */
14410     @TestApi
restoreFocusInCluster(@ocusRealDirection int direction)14411     public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
14412         // Prioritize focusableByDefault over algorithmic focus selection.
14413         if (restoreDefaultFocus()) {
14414             return true;
14415         }
14416         return requestFocus(direction);
14417     }
14418 
14419     /**
14420      * This will request focus for whichever View not in a cluster was last focused before a
14421      * focus-jump to a cluster. If no non-cluster View has previously had focus, this will focus
14422      * the "first" focusable view it finds.
14423      *
14424      * @hide
14425      */
14426     @TestApi
restoreFocusNotInCluster()14427     public boolean restoreFocusNotInCluster() {
14428         return requestFocus(View.FOCUS_DOWN);
14429     }
14430 
14431     /**
14432      * Gives focus to the default-focus view in the view hierarchy that has this view as a root.
14433      * If the default-focus view cannot be found, falls back to calling {@link #requestFocus(int)}.
14434      *
14435      * @return Whether this view or one of its descendants actually took focus
14436      */
restoreDefaultFocus()14437     public boolean restoreDefaultFocus() {
14438         return requestFocus(View.FOCUS_DOWN);
14439     }
14440 
14441     /**
14442      * Call this to try to give focus to a specific view or to one of its
14443      * descendants and give it a hint about what direction focus is heading.
14444      *
14445      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
14446      * false), or if it is focusable and it is not focusable in touch mode
14447      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
14448      *
14449      * See also {@link #focusSearch(int)}, which is what you call to say that you
14450      * have focus, and you want your parent to look for the next one.
14451      *
14452      * This is equivalent to calling {@link #requestFocus(int, Rect)} with
14453      * <code>null</code> set for the previously focused rectangle.
14454      *
14455      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
14456      * @return Whether this view or one of its descendants actually took focus.
14457      */
requestFocus(int direction)14458     public final boolean requestFocus(int direction) {
14459         return requestFocus(direction, null);
14460     }
14461 
14462     /**
14463      * Call this to try to give focus to a specific view or to one of its descendants
14464      * and give it hints about the direction and a specific rectangle that the focus
14465      * is coming from.  The rectangle can help give larger views a finer grained hint
14466      * about where focus is coming from, and therefore, where to show selection, or
14467      * forward focus change internally.
14468      *
14469      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
14470      * false), or if it is focusable and it is not focusable in touch mode
14471      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
14472      *
14473      * A View will not take focus if it is not visible.
14474      *
14475      * A View will not take focus if one of its parents has
14476      * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
14477      * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
14478      *
14479      * See also {@link #focusSearch(int)}, which is what you call to say that you
14480      * have focus, and you want your parent to look for the next one.
14481      *
14482      * You may wish to override this method if your custom {@link View} has an internal
14483      * {@link View} that it wishes to forward the request to.
14484      *
14485      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
14486      * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
14487      *        to give a finer grained hint about where focus is coming from.  May be null
14488      *        if there is no hint.
14489      * @return Whether this view or one of its descendants actually took focus.
14490      */
requestFocus(int direction, Rect previouslyFocusedRect)14491     public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
14492         return requestFocusNoSearch(direction, previouslyFocusedRect);
14493     }
14494 
requestFocusNoSearch(int direction, Rect previouslyFocusedRect)14495     private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
14496         // need to be focusable
14497         if (!canTakeFocus()) {
14498             return false;
14499         }
14500 
14501         // need to be focusable in touch mode if in touch mode
14502         if (isInTouchMode() &&
14503             (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
14504                return false;
14505         }
14506 
14507         // need to not have any parents blocking us
14508         if (hasAncestorThatBlocksDescendantFocus()) {
14509             return false;
14510         }
14511 
14512         if (!isLayoutValid()) {
14513             mPrivateFlags |= PFLAG_WANTS_FOCUS;
14514         } else {
14515             clearParentsWantFocus();
14516         }
14517 
14518         handleFocusGainInternal(direction, previouslyFocusedRect);
14519         return true;
14520     }
14521 
clearParentsWantFocus()14522     void clearParentsWantFocus() {
14523         if (mParent instanceof View) {
14524             ((View) mParent).mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
14525             ((View) mParent).clearParentsWantFocus();
14526         }
14527     }
14528 
14529     /**
14530      * Call this to try to give focus to a specific view or to one of its descendants. This is a
14531      * special variant of {@link #requestFocus() } that will allow views that are not focusable in
14532      * touch mode to request focus when they are touched.
14533      *
14534      * @return Whether this view or one of its descendants actually took focus.
14535      *
14536      * @see #isInTouchMode()
14537      *
14538      */
requestFocusFromTouch()14539     public final boolean requestFocusFromTouch() {
14540         // Leave touch mode if we need to
14541         if (isInTouchMode()) {
14542             ViewRootImpl viewRoot = getViewRootImpl();
14543             if (viewRoot != null) {
14544                 viewRoot.ensureTouchMode(false);
14545             }
14546         }
14547         return requestFocus(View.FOCUS_DOWN);
14548     }
14549 
14550     /**
14551      * @return Whether any ancestor of this view blocks descendant focus.
14552      */
hasAncestorThatBlocksDescendantFocus()14553     private boolean hasAncestorThatBlocksDescendantFocus() {
14554         final boolean focusableInTouchMode = isFocusableInTouchMode();
14555         ViewParent ancestor = mParent;
14556         while (ancestor instanceof ViewGroup) {
14557             final ViewGroup vgAncestor = (ViewGroup) ancestor;
14558             if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
14559                     || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
14560                 return true;
14561             } else {
14562                 ancestor = vgAncestor.getParent();
14563             }
14564         }
14565         return false;
14566     }
14567 
14568     /**
14569      * Gets the mode for determining whether this View is important for accessibility.
14570      * A view is important for accessibility if it fires accessibility events and if it
14571      * is reported to accessibility services that query the screen.
14572      *
14573      * @return The mode for determining whether a view is important for accessibility, one
14574      * of {@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, {@link #IMPORTANT_FOR_ACCESSIBILITY_YES},
14575      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO}, or
14576      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}.
14577      *
14578      * @attr ref android.R.styleable#View_importantForAccessibility
14579      *
14580      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
14581      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
14582      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
14583      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
14584      */
14585     @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
14586             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
14587             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
14588             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
14589             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
14590                     to = "noHideDescendants")
14591         })
14592     @InspectableProperty(enumMapping = {
14593             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_AUTO, name = "auto"),
14594             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_YES, name = "yes"),
14595             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_NO, name = "no"),
14596             @EnumEntry(value = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
14597                     name = "noHideDescendants"),
14598     })
getImportantForAccessibility()14599     public int getImportantForAccessibility() {
14600         return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
14601                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
14602     }
14603 
14604     /**
14605      * Sets the live region mode for this view. This indicates to accessibility
14606      * services whether they should automatically notify the user about changes
14607      * to the view's content description or text, or to the content descriptions
14608      * or text of the view's children (where applicable).
14609      * <p>
14610      * For example, in a login screen with a TextView that displays an "incorrect
14611      * password" notification, that view should be marked as a live region with
14612      * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
14613      * <p>
14614      * To disable change notifications for this view, use
14615      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
14616      * mode for most views.
14617      * <p>
14618      * To indicate that the user should be notified of changes, use
14619      * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
14620      * <p>
14621      * If the view's changes should interrupt ongoing speech and notify the user
14622      * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
14623      *
14624      * @param mode The live region mode for this view, one of:
14625      *        <ul>
14626      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
14627      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
14628      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
14629      *        </ul>
14630      * @attr ref android.R.styleable#View_accessibilityLiveRegion
14631      */
setAccessibilityLiveRegion(int mode)14632     public void setAccessibilityLiveRegion(int mode) {
14633         if (mode != getAccessibilityLiveRegion()) {
14634             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
14635             mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
14636                     & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
14637             notifyViewAccessibilityStateChangedIfNeeded(
14638                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
14639         }
14640     }
14641 
14642     /**
14643      * Gets the live region mode for this View.
14644      *
14645      * @return The live region mode for the view.
14646      *
14647      * @attr ref android.R.styleable#View_accessibilityLiveRegion
14648      *
14649      * @see #setAccessibilityLiveRegion(int)
14650      */
14651     @InspectableProperty(enumMapping = {
14652             @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_NONE, name = "none"),
14653             @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_POLITE, name = "polite"),
14654             @EnumEntry(value = ACCESSIBILITY_LIVE_REGION_ASSERTIVE, name = "assertive")
14655     })
getAccessibilityLiveRegion()14656     public int getAccessibilityLiveRegion() {
14657         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
14658                 >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
14659     }
14660 
14661     /**
14662      * Sets how to determine whether this view is important for accessibility
14663      * which is if it fires accessibility events and if it is reported to
14664      * accessibility services that query the screen.
14665      *
14666      * @param mode How to determine whether this view is important for accessibility.
14667      *
14668      * @attr ref android.R.styleable#View_importantForAccessibility
14669      *
14670      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
14671      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
14672      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
14673      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
14674      */
setImportantForAccessibility(int mode)14675     public void setImportantForAccessibility(int mode) {
14676         final int oldMode = getImportantForAccessibility();
14677         if (mode != oldMode) {
14678             final boolean hideDescendants =
14679                     mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
14680 
14681             // If this node or its descendants are no longer important, try to
14682             // clear accessibility focus.
14683             if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
14684                 final View focusHost = findAccessibilityFocusHost(hideDescendants);
14685                 if (focusHost != null) {
14686                     focusHost.clearAccessibilityFocus();
14687                 }
14688             }
14689 
14690             // If we're moving between AUTO and another state, we might not need
14691             // to send a subtree changed notification. We'll store the computed
14692             // importance, since we'll need to check it later to make sure.
14693             final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
14694                     || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
14695             final boolean oldIncludeForAccessibility =
14696                     maySkipNotify && includeForAccessibility(false);
14697             mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
14698             mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
14699                     & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
14700             if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility(false)) {
14701                 notifySubtreeAccessibilityStateChangedIfNeeded();
14702             } else {
14703                 notifyViewAccessibilityStateChangedIfNeeded(
14704                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
14705             }
14706         }
14707     }
14708 
14709     /**
14710      * Returns the view within this view's hierarchy that is hosting
14711      * accessibility focus.
14712      *
14713      * @param searchDescendants whether to search for focus in descendant views
14714      * @return the view hosting accessibility focus, or {@code null}
14715      */
findAccessibilityFocusHost(boolean searchDescendants)14716     private View findAccessibilityFocusHost(boolean searchDescendants) {
14717         if (isAccessibilityFocusedViewOrHost()) {
14718             return this;
14719         }
14720 
14721         if (searchDescendants) {
14722             final ViewRootImpl viewRoot = getViewRootImpl();
14723             if (viewRoot != null) {
14724                 final View focusHost = viewRoot.getAccessibilityFocusedHost();
14725                 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
14726                     return focusHost;
14727                 }
14728             }
14729         }
14730 
14731         return null;
14732     }
14733 
14734     /**
14735      * Computes whether this view should be exposed for accessibility. In
14736      * general, views that are interactive or provide information are exposed
14737      * while views that serve only as containers are hidden.
14738      * <p>
14739      * If an ancestor of this view has importance
14740      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
14741      * returns <code>false</code>.
14742      * <p>
14743      * Otherwise, the value is computed according to the view's
14744      * {@link #getImportantForAccessibility()} value:
14745      * <ol>
14746      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
14747      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
14748      * </code>
14749      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
14750      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
14751      * view satisfies any of the following:
14752      * <ul>
14753      * <li>Is actionable, e.g. {@link #isClickable()},
14754      * {@link #isLongClickable()}, or {@link #isFocusable()}
14755      * <li>Has an {@link AccessibilityDelegate}
14756      * <li>Has an interaction listener, e.g. {@link OnTouchListener},
14757      * {@link OnKeyListener}, etc.
14758      * <li>Is an accessibility live region, e.g.
14759      * {@link #getAccessibilityLiveRegion()} is not
14760      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
14761      * </ul>
14762      * <li>Has an accessibility pane title, see {@link #setAccessibilityPaneTitle}</li>
14763      * </ol>
14764      *
14765      * @return Whether the view is exposed for accessibility.
14766      * @see #setImportantForAccessibility(int)
14767      * @see #getImportantForAccessibility()
14768      */
isImportantForAccessibility()14769     public boolean isImportantForAccessibility() {
14770         final int mode = getImportantForAccessibility();
14771         if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
14772                 || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
14773             return false;
14774         }
14775 
14776         // Check parent mode to ensure we're not hidden.
14777         ViewParent parent = mParent;
14778         while (parent instanceof View) {
14779             if (((View) parent).getImportantForAccessibility()
14780                     == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
14781                 return false;
14782             }
14783             parent = parent.getParent();
14784         }
14785 
14786         return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
14787                 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
14788                 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE
14789                 || isAccessibilityPane();
14790     }
14791 
14792     /**
14793      * Gets the parent for accessibility purposes. Note that the parent for
14794      * accessibility is not necessary the immediate parent. It is the first
14795      * predecessor that is important for accessibility.
14796      *
14797      * @return The parent for accessibility purposes.
14798      */
getParentForAccessibility()14799     public ViewParent getParentForAccessibility() {
14800         if (mParent instanceof View) {
14801             View parentView = (View) mParent;
14802             if (parentView.includeForAccessibility()) {
14803                 return mParent;
14804             } else {
14805                 return mParent.getParentForAccessibility();
14806             }
14807         }
14808         return null;
14809     }
14810 
14811     /** @hide */
getSelfOrParentImportantForA11y()14812     View getSelfOrParentImportantForA11y() {
14813         if (isImportantForAccessibility()) return this;
14814         ViewParent parent = getParentForAccessibility();
14815         if (parent instanceof View) return (View) parent;
14816         return null;
14817     }
14818 
14819     /**
14820      * Adds the children of this View relevant for accessibility to the given list
14821      * as output. Since some Views are not important for accessibility the added
14822      * child views are not necessarily direct children of this view, rather they are
14823      * the first level of descendants important for accessibility.
14824      *
14825      * @param outChildren The output list that will receive children for accessibility.
14826      */
addChildrenForAccessibility(ArrayList<View> outChildren)14827     public void addChildrenForAccessibility(ArrayList<View> outChildren) {
14828 
14829     }
14830 
14831     /**
14832      * @see #includeForAccessibility(boolean)
14833      * @hide
14834      */
14835     @UnsupportedAppUsage
includeForAccessibility()14836     public boolean includeForAccessibility() {
14837         return includeForAccessibility(true);
14838     }
14839 
14840     /**
14841      * Whether to regard this view for accessibility.
14842      *
14843      * <p>
14844      * If this decision is used for generating the accessibility node tree then this returns false
14845      * for {@link #isAccessibilityDataPrivate()} views queried by non-accessibility tools.
14846      * </p>
14847      * <p>
14848      * Otherwise, a view is regarded for accessibility if:
14849      * <li>the view returns true for {@link #isImportantForAccessibility()}, or</li>
14850      * <li>the querying accessibility service has explicitly requested that views not important for
14851      * accessibility are regarded by setting
14852      * {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS}</li>
14853      * </p>
14854      *
14855      * @param forNodeTree True if the result of this function will be used for generating a node
14856      *                    tree, otherwise false (like when sending {@link AccessibilityEvent}s).
14857      * @return Whether to regard the view for accessibility.
14858      * @hide
14859      */
includeForAccessibility(boolean forNodeTree)14860     public boolean includeForAccessibility(boolean forNodeTree) {
14861         if (mAttachInfo == null) {
14862             return false;
14863         }
14864 
14865         if (forNodeTree) {
14866             // The AccessibilityDataPrivate property should not effect whether this View is
14867             // included for consideration when sending AccessibilityEvents. Events copy their
14868             // source View's AccessibilityDataPrivate value, and then filtering is done when
14869             // AccessibilityManagerService propagates events to each recipient AccessibilityService.
14870             if (!AccessibilityManager.getInstance(mContext).isRequestFromAccessibilityTool()
14871                     && isAccessibilityDataSensitive()) {
14872                 return false;
14873             }
14874         }
14875 
14876         return (mAttachInfo.mAccessibilityFetchFlags
14877                 & AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
14878                 || isImportantForAccessibility();
14879     }
14880 
14881     /**
14882      * Whether this view should restrict accessibility service access only to services that have the
14883      * {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property
14884      * set to true.
14885      *
14886      * <p>
14887      * See default behavior provided by {@link #ACCESSIBILITY_DATA_SENSITIVE_AUTO}. Otherwise,
14888      * returns true for {@link #ACCESSIBILITY_DATA_SENSITIVE_YES} or false for {@link
14889      * #ACCESSIBILITY_DATA_SENSITIVE_NO}.
14890      * </p>
14891      *
14892      * @return True if this view should restrict accessibility service access to services that have
14893      * the isAccessibilityTool property.
14894      */
14895     @ViewDebug.ExportedProperty(category = "accessibility")
isAccessibilityDataSensitive()14896     public boolean isAccessibilityDataSensitive() {
14897         if (mInferredAccessibilityDataSensitive == ACCESSIBILITY_DATA_SENSITIVE_AUTO) {
14898             calculateAccessibilityDataSensitive();
14899         }
14900         return mInferredAccessibilityDataSensitive == ACCESSIBILITY_DATA_SENSITIVE_YES;
14901     }
14902 
14903     /**
14904      * Calculate and cache the inferred value for {@link #isAccessibilityDataSensitive()}.
14905      *
14906      * <p>
14907      * <strong>Note:</strong> This method needs to be called any time one of the below conditions
14908      * changes, to recalculate the new value.
14909      * </p>
14910      */
calculateAccessibilityDataSensitive()14911     void calculateAccessibilityDataSensitive() {
14912         // Use the explicit value if set.
14913         if (mExplicitAccessibilityDataSensitive != ACCESSIBILITY_DATA_SENSITIVE_AUTO) {
14914             mInferredAccessibilityDataSensitive = mExplicitAccessibilityDataSensitive;
14915         } else if (getFilterTouchesWhenObscured()) {
14916             // Views that set filterTouchesWhenObscured default to accessibilityDataSensitive.
14917             mInferredAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_YES;
14918         } else if (mParent instanceof View && ((View) mParent).isAccessibilityDataSensitive()) {
14919             // Descendants of accessibilityDataSensitive Views are also accessibilityDataSensitive.
14920             mInferredAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_YES;
14921         } else {
14922             // Otherwise, default to not accessibilityDataSensitive.
14923             mInferredAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_NO;
14924         }
14925     }
14926 
14927     /**
14928      * Specifies whether this view should only allow interactions from
14929      * {@link android.accessibilityservice.AccessibilityService}s with the
14930      * {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property
14931      * set to true.
14932      */
setAccessibilityDataSensitive( @ccessibilityDataSensitive int accessibilityDataSensitive)14933     public void setAccessibilityDataSensitive(
14934             @AccessibilityDataSensitive int accessibilityDataSensitive) {
14935         mExplicitAccessibilityDataSensitive = accessibilityDataSensitive;
14936         calculateAccessibilityDataSensitive();
14937     }
14938 
14939     /**
14940      * Returns whether the View is considered actionable from
14941      * accessibility perspective. Such view are important for
14942      * accessibility.
14943      *
14944      * @return True if the view is actionable for accessibility.
14945      *
14946      * @hide
14947      */
isActionableForAccessibility()14948     public boolean isActionableForAccessibility() {
14949         return (isClickable() || isLongClickable() || isFocusable());
14950     }
14951 
14952     /**
14953      * Returns whether the View has registered callbacks which makes it
14954      * important for accessibility.
14955      *
14956      * @return True if the view is actionable for accessibility.
14957      */
hasListenersForAccessibility()14958     private boolean hasListenersForAccessibility() {
14959         ListenerInfo info = getListenerInfo();
14960         return mTouchDelegate != null || info.mOnKeyListener != null
14961                 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
14962                 || info.mOnHoverListener != null || info.mOnDragListener != null;
14963     }
14964 
14965     /**
14966      * Notifies that the accessibility state of this view changed. The change
14967      * is local to this view and does not represent structural changes such
14968      * as children and parent. For example, the view became focusable. The
14969      * notification is at at most once every
14970      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
14971      * to avoid unnecessary load to the system. Also once a view has a pending
14972      * notification this method is a NOP until the notification has been sent.
14973      *
14974      * @hide
14975      */
14976     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
notifyViewAccessibilityStateChangedIfNeeded(int changeType)14977     public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
14978         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
14979             return;
14980         }
14981 
14982         // Changes to views with a pane title count as window state changes, as the pane title
14983         // marks them as significant parts of the UI. A visible view with a nulled title may send
14984         // a disappeared event.
14985         if ((changeType != AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE)
14986                 && (isAccessibilityPane()
14987                 || (changeType == AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED)
14988                 && isAggregatedVisible())) {
14989             // If the pane isn't visible, content changed events are sufficient unless we're
14990             // reporting that the view just disappeared
14991             if ((isAggregatedVisible())
14992                     || (changeType == AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED)) {
14993                 final AccessibilityEvent event = AccessibilityEvent.obtain();
14994                 onInitializeAccessibilityEvent(event);
14995                 event.setEventType(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
14996                 event.setContentChangeTypes(changeType);
14997                 event.setSource(this);
14998                 onPopulateAccessibilityEvent(event);
14999                 if (mParent != null) {
15000                     try {
15001                         mParent.requestSendAccessibilityEvent(this, event);
15002                     } catch (AbstractMethodError e) {
15003                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName()
15004                                 + " does not fully implement ViewParent", e);
15005                     }
15006                 }
15007                 return;
15008             }
15009         }
15010 
15011         // If this is a live region, we should send a subtree change event
15012         // from this view immediately. Otherwise, we can let it propagate up.
15013         if (getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE) {
15014             final AccessibilityEvent event = AccessibilityEvent.obtain();
15015             event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
15016             event.setContentChangeTypes(changeType);
15017             sendAccessibilityEventUnchecked(event);
15018         } else if (mParent != null) {
15019             try {
15020                 mParent.notifySubtreeAccessibilityStateChanged(this, this, changeType);
15021             } catch (AbstractMethodError e) {
15022                 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
15023                         " does not fully implement ViewParent", e);
15024             }
15025         }
15026     }
15027 
15028     /**
15029      * Notifies that the accessibility state of this view changed. The change
15030      * is *not* local to this view and does represent structural changes such
15031      * as children and parent. For example, the view size changed. The
15032      * notification is at at most once every
15033      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
15034      * to avoid unnecessary load to the system. Also once a view has a pending
15035      * notification this method is a NOP until the notification has been sent.
15036      *
15037      * @hide
15038      */
15039     @UnsupportedAppUsage
notifySubtreeAccessibilityStateChangedIfNeeded()15040     public void notifySubtreeAccessibilityStateChangedIfNeeded() {
15041         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
15042             return;
15043         }
15044 
15045         if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
15046             mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
15047             if (mParent != null) {
15048                 try {
15049                     mParent.notifySubtreeAccessibilityStateChanged(
15050                             this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
15051                 } catch (AbstractMethodError e) {
15052                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
15053                             " does not fully implement ViewParent", e);
15054                 }
15055             }
15056         }
15057     }
15058 
notifySubtreeAccessibilityStateChangedByParentIfNeeded()15059     private void notifySubtreeAccessibilityStateChangedByParentIfNeeded() {
15060         if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
15061             return;
15062         }
15063 
15064         final View sendA11yEventView = (View) getParentForAccessibility();
15065         if (sendA11yEventView != null && sendA11yEventView.isShown()) {
15066             sendA11yEventView.notifySubtreeAccessibilityStateChangedIfNeeded();
15067         }
15068     }
15069 
15070     /**
15071      * Changes the visibility of this View without triggering any other changes. This should only
15072      * be used by animation frameworks, such as {@link android.transition.Transition}, where
15073      * visibility changes should not adjust focus or trigger a new layout. Application developers
15074      * should use {@link #setVisibility} instead to ensure that the hierarchy is correctly updated.
15075      *
15076      * <p>Only call this method when a temporary visibility must be applied during an
15077      * animation and the original visibility value is guaranteed to be reset after the
15078      * animation completes. Use {@link #setVisibility} in all other cases.</p>
15079      *
15080      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
15081      * @see #setVisibility(int)
15082      */
setTransitionVisibility(@isibility int visibility)15083     public void setTransitionVisibility(@Visibility int visibility) {
15084         mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
15085     }
15086 
15087     /**
15088      * Reset the flag indicating the accessibility state of the subtree rooted
15089      * at this view changed.
15090      */
resetSubtreeAccessibilityStateChanged()15091     void resetSubtreeAccessibilityStateChanged() {
15092         mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
15093     }
15094 
15095     /**
15096      * Report an accessibility action to this view's parents for delegated processing.
15097      *
15098      * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
15099      * call this method to delegate an accessibility action to a supporting parent. If the parent
15100      * returns true from its
15101      * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
15102      * method this method will return true to signify that the action was consumed.</p>
15103      *
15104      * <p>This method is useful for implementing nested scrolling child views. If
15105      * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
15106      * a custom view implementation may invoke this method to allow a parent to consume the
15107      * scroll first. If this method returns true the custom view should skip its own scrolling
15108      * behavior.</p>
15109      *
15110      * @param action Accessibility action to delegate
15111      * @param arguments Optional action arguments
15112      * @return true if the action was consumed by a parent
15113      */
dispatchNestedPrePerformAccessibilityAction(int action, @Nullable Bundle arguments)15114     public boolean dispatchNestedPrePerformAccessibilityAction(int action,
15115             @Nullable Bundle arguments) {
15116         for (ViewParent p = getParent(); p != null; p = p.getParent()) {
15117             if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
15118                 return true;
15119             }
15120         }
15121         return false;
15122     }
15123 
15124     /**
15125      * Performs the specified accessibility action on the view. For
15126      * possible accessibility actions look at {@link AccessibilityNodeInfo}.
15127      * <p>
15128      * If an {@link AccessibilityDelegate} has been specified via calling
15129      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
15130      * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
15131      * is responsible for handling this call.
15132      * </p>
15133      *
15134      * <p>The default implementation will delegate
15135      * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
15136      * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
15137      * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
15138      *
15139      * <p>
15140      * <b>Note:</b> Avoid setting accessibility focus with
15141      * {@link AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS}. This is intended to be controlled
15142      * by screen readers. Apps changing focus can confuse screen readers, so the resulting behavior
15143      * can vary by device and screen reader version.
15144      *
15145      * @param action The action to perform.
15146      * @param arguments Optional action arguments.
15147      * @return Whether the action was performed.
15148      */
performAccessibilityAction(int action, @Nullable Bundle arguments)15149     public boolean performAccessibilityAction(int action, @Nullable Bundle arguments) {
15150       if (mAccessibilityDelegate != null) {
15151           return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
15152       } else {
15153           return performAccessibilityActionInternal(action, arguments);
15154       }
15155     }
15156 
15157    /**
15158     * @see #performAccessibilityAction(int, Bundle)
15159     *
15160     * Note: Called from the default {@link AccessibilityDelegate}.
15161     *
15162     * @hide
15163     */
15164     @UnsupportedAppUsage
performAccessibilityActionInternal(int action, @Nullable Bundle arguments)15165     public boolean performAccessibilityActionInternal(int action, @Nullable Bundle arguments) {
15166         if (isNestedScrollingEnabled()
15167                 && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
15168                 || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
15169                 || action == R.id.accessibilityActionScrollUp
15170                 || action == R.id.accessibilityActionScrollLeft
15171                 || action == R.id.accessibilityActionScrollDown
15172                 || action == R.id.accessibilityActionScrollRight)) {
15173             if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
15174                 return true;
15175             }
15176         }
15177 
15178         switch (action) {
15179             case AccessibilityNodeInfo.ACTION_CLICK: {
15180                 if (isClickable()) {
15181                     performClickInternal();
15182                     return true;
15183                 }
15184             } break;
15185             case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
15186                 if (isLongClickable()) {
15187                     performLongClick();
15188                     return true;
15189                 }
15190             } break;
15191             case AccessibilityNodeInfo.ACTION_FOCUS: {
15192                 if (!hasFocus()) {
15193                     // Get out of touch mode since accessibility
15194                     // wants to move focus around.
15195                     getViewRootImpl().ensureTouchMode(false);
15196                     return requestFocus();
15197                 }
15198             } break;
15199             case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
15200                 if (hasFocus()) {
15201                     clearFocus();
15202                     return !isFocused();
15203                 }
15204             } break;
15205             case AccessibilityNodeInfo.ACTION_SELECT: {
15206                 if (!isSelected()) {
15207                     setSelected(true);
15208                     return isSelected();
15209                 }
15210             } break;
15211             case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
15212                 if (isSelected()) {
15213                     setSelected(false);
15214                     return !isSelected();
15215                 }
15216             } break;
15217             case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
15218                 if (!isAccessibilityFocused()) {
15219                     return requestAccessibilityFocus();
15220                 }
15221             } break;
15222             case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
15223                 if (isAccessibilityFocused()) {
15224                     clearAccessibilityFocus();
15225                     return true;
15226                 }
15227             } break;
15228             case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
15229                 if (arguments != null) {
15230                     final int granularity = arguments.getInt(
15231                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
15232                     final boolean extendSelection = arguments.getBoolean(
15233                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
15234                     return traverseAtGranularity(granularity, true, extendSelection);
15235                 }
15236             } break;
15237             case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
15238                 if (arguments != null) {
15239                     final int granularity = arguments.getInt(
15240                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
15241                     final boolean extendSelection = arguments.getBoolean(
15242                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
15243                     return traverseAtGranularity(granularity, false, extendSelection);
15244                 }
15245             } break;
15246             case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
15247                 CharSequence text = getIterableTextForAccessibility();
15248                 if (text == null) {
15249                     return false;
15250                 }
15251                 final int start = (arguments != null) ? arguments.getInt(
15252                         AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
15253                 final int end = (arguments != null) ? arguments.getInt(
15254                 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
15255                 // Only cursor position can be specified (selection length == 0)
15256                 if ((getAccessibilitySelectionStart() != start
15257                         || getAccessibilitySelectionEnd() != end)
15258                         && (start == end)) {
15259                     setAccessibilitySelection(start, end);
15260                     notifyViewAccessibilityStateChangedIfNeeded(
15261                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
15262                     return true;
15263                 }
15264             } break;
15265             case R.id.accessibilityActionShowOnScreen: {
15266                 if (mAttachInfo != null) {
15267                     final Rect r = mAttachInfo.mTmpInvalRect;
15268                     getDrawingRect(r);
15269                     return requestRectangleOnScreen(r, true);
15270                 }
15271             } break;
15272             case R.id.accessibilityActionContextClick: {
15273                 if (isContextClickable()) {
15274                     performContextClick();
15275                     return true;
15276                 }
15277             } break;
15278             case R.id.accessibilityActionShowTooltip: {
15279                 if ((mTooltipInfo != null) && (mTooltipInfo.mTooltipPopup != null)) {
15280                     // Tooltip already showing
15281                     return false;
15282                 }
15283                 return showLongClickTooltip(0, 0);
15284             }
15285             case R.id.accessibilityActionHideTooltip: {
15286                 if ((mTooltipInfo == null) || (mTooltipInfo.mTooltipPopup == null)) {
15287                     // No tooltip showing
15288                     return false;
15289                 }
15290                 hideTooltip();
15291                 return true;
15292             }
15293             case R.id.accessibilityActionDragDrop: {
15294                 if (!canAcceptAccessibilityDrop()) {
15295                     return false;
15296                 }
15297                 try {
15298                     if (mAttachInfo != null && mAttachInfo.mSession != null) {
15299                         final int[] location = new int[2];
15300                         getLocationInWindow(location);
15301                         final int centerX = location[0] + getWidth() / 2;
15302                         final int centerY = location[1] + getHeight() / 2;
15303                         return mAttachInfo.mSession.dropForAccessibility(mAttachInfo.mWindow,
15304                                 centerX, centerY);
15305                     }
15306                 } catch (RemoteException e) {
15307                     Log.e(VIEW_LOG_TAG, "Unable to drop for accessibility", e);
15308                 }
15309                 return false;
15310             }
15311             case R.id.accessibilityActionDragCancel: {
15312                 if (!startedSystemDragForAccessibility()) {
15313                     return false;
15314                 }
15315                 if (mAttachInfo != null && mAttachInfo.mDragToken != null) {
15316                     cancelDragAndDrop();
15317                     return true;
15318                 }
15319                 return false;
15320             }
15321         }
15322         return false;
15323     }
15324 
canAcceptAccessibilityDrop()15325     private boolean canAcceptAccessibilityDrop() {
15326         if (!canAcceptDrag()) {
15327             return false;
15328         }
15329         ListenerInfo li = mListenerInfo;
15330         return (li != null) && (li.mOnDragListener != null || li.mOnReceiveContentListener != null);
15331     }
15332 
traverseAtGranularity(int granularity, boolean forward, boolean extendSelection)15333     private boolean traverseAtGranularity(int granularity, boolean forward,
15334             boolean extendSelection) {
15335         CharSequence text = getIterableTextForAccessibility();
15336         if (text == null || text.length() == 0) {
15337             return false;
15338         }
15339         TextSegmentIterator iterator = getIteratorForGranularity(granularity);
15340         if (iterator == null) {
15341             return false;
15342         }
15343         int current = getAccessibilitySelectionEnd();
15344         if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
15345             current = forward ? 0 : text.length();
15346         }
15347         final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
15348         if (range == null) {
15349             return false;
15350         }
15351         final int segmentStart = range[0];
15352         final int segmentEnd = range[1];
15353         int selectionStart;
15354         int selectionEnd;
15355         if (extendSelection && isAccessibilitySelectionExtendable()) {
15356             prepareForExtendedAccessibilitySelection();
15357             selectionStart = getAccessibilitySelectionStart();
15358             if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
15359                 selectionStart = forward ? segmentStart : segmentEnd;
15360             }
15361             selectionEnd = forward ? segmentEnd : segmentStart;
15362         } else {
15363             selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
15364         }
15365         setAccessibilitySelection(selectionStart, selectionEnd);
15366         final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
15367                 : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
15368         sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
15369         return true;
15370     }
15371 
15372     /**
15373      * Gets the text reported for accessibility purposes.
15374      *
15375      * @return The accessibility text.
15376      *
15377      * @hide
15378      */
15379     @UnsupportedAppUsage
getIterableTextForAccessibility()15380     public CharSequence getIterableTextForAccessibility() {
15381         return getContentDescription();
15382     }
15383 
15384     /**
15385      * Gets whether accessibility selection can be extended.
15386      *
15387      * @return If selection is extensible.
15388      *
15389      * @hide
15390      */
isAccessibilitySelectionExtendable()15391     public boolean isAccessibilitySelectionExtendable() {
15392         return false;
15393     }
15394 
15395     /**
15396      * Prepare for extended selection.
15397      * @hide
15398      */
prepareForExtendedAccessibilitySelection()15399     public void prepareForExtendedAccessibilitySelection() {
15400         return;
15401     }
15402 
15403     /**
15404      * @hide
15405      */
getAccessibilitySelectionStart()15406     public int getAccessibilitySelectionStart() {
15407         return mAccessibilityCursorPosition;
15408     }
15409 
15410     /**
15411      * @hide
15412      */
getAccessibilitySelectionEnd()15413     public int getAccessibilitySelectionEnd() {
15414         return getAccessibilitySelectionStart();
15415     }
15416 
15417     /**
15418      * @hide
15419      */
setAccessibilitySelection(int start, int end)15420     public void setAccessibilitySelection(int start, int end) {
15421         if (start ==  end && end == mAccessibilityCursorPosition) {
15422             return;
15423         }
15424         if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
15425             mAccessibilityCursorPosition = start;
15426         } else {
15427             mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
15428         }
15429         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
15430     }
15431 
sendViewTextTraversedAtGranularityEvent(int action, int granularity, int fromIndex, int toIndex)15432     private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
15433             int fromIndex, int toIndex) {
15434         if (mParent == null) {
15435             return;
15436         }
15437         AccessibilityEvent event = AccessibilityEvent.obtain(
15438                 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
15439         onInitializeAccessibilityEvent(event);
15440         onPopulateAccessibilityEvent(event);
15441         event.setFromIndex(fromIndex);
15442         event.setToIndex(toIndex);
15443         event.setAction(action);
15444         event.setMovementGranularity(granularity);
15445         mParent.requestSendAccessibilityEvent(this, event);
15446     }
15447 
15448     /**
15449      * @hide
15450      */
15451     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getIteratorForGranularity(int granularity)15452     public TextSegmentIterator getIteratorForGranularity(int granularity) {
15453         switch (granularity) {
15454             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
15455                 CharSequence text = getIterableTextForAccessibility();
15456                 if (text != null && text.length() > 0) {
15457                     CharacterTextSegmentIterator iterator =
15458                         CharacterTextSegmentIterator.getInstance(
15459                                 mContext.getResources().getConfiguration().locale);
15460                     iterator.initialize(text.toString());
15461                     return iterator;
15462                 }
15463             } break;
15464             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
15465                 CharSequence text = getIterableTextForAccessibility();
15466                 if (text != null && text.length() > 0) {
15467                     WordTextSegmentIterator iterator =
15468                         WordTextSegmentIterator.getInstance(
15469                                 mContext.getResources().getConfiguration().locale);
15470                     iterator.initialize(text.toString());
15471                     return iterator;
15472                 }
15473             } break;
15474             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
15475                 CharSequence text = getIterableTextForAccessibility();
15476                 if (text != null && text.length() > 0) {
15477                     ParagraphTextSegmentIterator iterator =
15478                         ParagraphTextSegmentIterator.getInstance();
15479                     iterator.initialize(text.toString());
15480                     return iterator;
15481                 }
15482             } break;
15483         }
15484         return null;
15485     }
15486 
15487     /**
15488      * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
15489      * and {@link #onFinishTemporaryDetach()}.
15490      *
15491      * <p>This method always returns {@code true} when called directly or indirectly from
15492      * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
15493      * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
15494      * <ul>
15495      *     <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
15496      *     <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
15497      * </ul>
15498      * </p>
15499      *
15500      * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
15501      * and {@link #onFinishTemporaryDetach()}.
15502      */
isTemporarilyDetached()15503     public final boolean isTemporarilyDetached() {
15504         return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
15505     }
15506 
15507     /**
15508      * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
15509      * a container View.
15510      */
15511     @CallSuper
dispatchStartTemporaryDetach()15512     public void dispatchStartTemporaryDetach() {
15513         mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
15514         notifyEnterOrExitForAutoFillIfNeeded(false);
15515         notifyAppearedOrDisappearedForContentCaptureIfNeeded(false);
15516         onStartTemporaryDetach();
15517     }
15518 
15519     /**
15520      * This is called when a container is going to temporarily detach a child, with
15521      * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
15522      * It will either be followed by {@link #onFinishTemporaryDetach()} or
15523      * {@link #onDetachedFromWindow()} when the container is done.
15524      */
onStartTemporaryDetach()15525     public void onStartTemporaryDetach() {
15526         removeUnsetPressCallback();
15527         mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
15528     }
15529 
15530     /**
15531      * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
15532      * a container View.
15533      */
15534     @CallSuper
dispatchFinishTemporaryDetach()15535     public void dispatchFinishTemporaryDetach() {
15536         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
15537         onFinishTemporaryDetach();
15538         if (hasWindowFocus() && hasFocus()) {
15539             notifyFocusChangeToImeFocusController(true /* hasFocus */);
15540         }
15541         notifyEnterOrExitForAutoFillIfNeeded(true);
15542         notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
15543     }
15544 
15545     /**
15546      * Called after {@link #onStartTemporaryDetach} when the container is done
15547      * changing the view.
15548      */
onFinishTemporaryDetach()15549     public void onFinishTemporaryDetach() {
15550     }
15551 
15552     /**
15553      * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
15554      * for this view's window.  Returns null if the view is not currently attached
15555      * to the window.  Normally you will not need to use this directly, but
15556      * just use the standard high-level event callbacks like
15557      * {@link #onKeyDown(int, KeyEvent)}.
15558      */
getKeyDispatcherState()15559     public KeyEvent.DispatcherState getKeyDispatcherState() {
15560         return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
15561     }
15562 
15563     /**
15564      * Dispatch a key event before it is processed by any input method
15565      * associated with the view hierarchy.  This can be used to intercept
15566      * key events in special situations before the IME consumes them; a
15567      * typical example would be handling the BACK key to update the application's
15568      * UI instead of allowing the IME to see it and close itself.
15569      *
15570      * @param event The key event to be dispatched.
15571      * @return True if the event was handled, false otherwise.
15572      */
dispatchKeyEventPreIme(KeyEvent event)15573     public boolean dispatchKeyEventPreIme(KeyEvent event) {
15574         return onKeyPreIme(event.getKeyCode(), event);
15575     }
15576 
15577     /**
15578      * Dispatch a key event to the next view on the focus path. This path runs
15579      * from the top of the view tree down to the currently focused view. If this
15580      * view has focus, it will dispatch to itself. Otherwise it will dispatch
15581      * the next node down the focus path. This method also fires any key
15582      * listeners.
15583      *
15584      * @param event The key event to be dispatched.
15585      * @return True if the event was handled, false otherwise.
15586      */
dispatchKeyEvent(KeyEvent event)15587     public boolean dispatchKeyEvent(KeyEvent event) {
15588         if (mInputEventConsistencyVerifier != null) {
15589             mInputEventConsistencyVerifier.onKeyEvent(event, 0);
15590         }
15591 
15592         // Give any attached key listener a first crack at the event.
15593         //noinspection SimplifiableIfStatement
15594         ListenerInfo li = mListenerInfo;
15595         if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
15596                 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
15597             return true;
15598         }
15599 
15600         if (event.dispatch(this, mAttachInfo != null
15601                 ? mAttachInfo.mKeyDispatchState : null, this)) {
15602             return true;
15603         }
15604 
15605         if (mInputEventConsistencyVerifier != null) {
15606             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
15607         }
15608         return false;
15609     }
15610 
15611     /**
15612      * Dispatches a key shortcut event.
15613      *
15614      * @param event The key event to be dispatched.
15615      * @return True if the event was handled by the view, false otherwise.
15616      */
dispatchKeyShortcutEvent(KeyEvent event)15617     public boolean dispatchKeyShortcutEvent(KeyEvent event) {
15618         return onKeyShortcut(event.getKeyCode(), event);
15619     }
15620 
15621     /**
15622      * Pass the touch screen motion event down to the target view, or this
15623      * view if it is the target.
15624      *
15625      * @param event The motion event to be dispatched.
15626      * @return True if the event was handled by the view, false otherwise.
15627      *
15628      * @see #onTouchEvent(MotionEvent)
15629      */
dispatchTouchEvent(MotionEvent event)15630     public boolean dispatchTouchEvent(MotionEvent event) {
15631         // If the event should be handled by accessibility focus first.
15632         if (event.isTargetAccessibilityFocus()) {
15633             // We don't have focus or no virtual descendant has it, do not handle the event.
15634             if (!isAccessibilityFocusedViewOrHost()) {
15635                 return false;
15636             }
15637             // We have focus and got the event, then use normal event dispatch.
15638             event.setTargetAccessibilityFocus(false);
15639         }
15640         boolean result = false;
15641 
15642         if (mInputEventConsistencyVerifier != null) {
15643             mInputEventConsistencyVerifier.onTouchEvent(event, 0);
15644         }
15645 
15646         final int actionMasked = event.getActionMasked();
15647         if (actionMasked == MotionEvent.ACTION_DOWN) {
15648             // Defensive cleanup for new gesture
15649             stopNestedScroll();
15650         }
15651 
15652         if (onFilterTouchEventForSecurity(event)) {
15653             if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
15654                 result = true;
15655             }
15656             //noinspection SimplifiableIfStatement
15657             ListenerInfo li = mListenerInfo;
15658             if (li != null && li.mOnTouchListener != null
15659                     && (mViewFlags & ENABLED_MASK) == ENABLED
15660                     && li.mOnTouchListener.onTouch(this, event)) {
15661                 result = true;
15662             }
15663 
15664             if (!result && onTouchEvent(event)) {
15665                 result = true;
15666             }
15667         }
15668 
15669         if (!result && mInputEventConsistencyVerifier != null) {
15670             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
15671         }
15672 
15673         // Clean up after nested scrolls if this is the end of a gesture;
15674         // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
15675         // of the gesture.
15676         if (actionMasked == MotionEvent.ACTION_UP ||
15677                 actionMasked == MotionEvent.ACTION_CANCEL ||
15678                 (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
15679             stopNestedScroll();
15680         }
15681 
15682         return result;
15683     }
15684 
isAccessibilityFocusedViewOrHost()15685     boolean isAccessibilityFocusedViewOrHost() {
15686         return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
15687                 .getAccessibilityFocusedHost() == this);
15688     }
15689 
15690     /**
15691      * Returns whether this view can receive pointer events.
15692      *
15693      * @return {@code true} if this view can receive pointer events.
15694      * @hide
15695      */
canReceivePointerEvents()15696     protected boolean canReceivePointerEvents() {
15697         return (mViewFlags & VISIBILITY_MASK) == VISIBLE || getAnimation() != null;
15698     }
15699 
15700     /**
15701      * Filter the touch event to apply security policies.
15702      *
15703      * @param event The motion event to be filtered.
15704      * @return True if the event should be dispatched, false if the event should be dropped.
15705      *
15706      * @see #getFilterTouchesWhenObscured
15707      */
onFilterTouchEventForSecurity(MotionEvent event)15708     public boolean onFilterTouchEventForSecurity(MotionEvent event) {
15709         //noinspection RedundantIfStatement
15710         if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
15711                 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
15712             // Window is obscured, drop this touch.
15713             return false;
15714         }
15715         return true;
15716     }
15717 
15718     /**
15719      * Pass a trackball motion event down to the focused view.
15720      *
15721      * @param event The motion event to be dispatched.
15722      * @return True if the event was handled by the view, false otherwise.
15723      *
15724      * @see #onTrackballEvent(MotionEvent)
15725      */
dispatchTrackballEvent(MotionEvent event)15726     public boolean dispatchTrackballEvent(MotionEvent event) {
15727         if (mInputEventConsistencyVerifier != null) {
15728             mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
15729         }
15730 
15731         return onTrackballEvent(event);
15732     }
15733 
15734     /**
15735      * Pass a captured pointer event down to the focused view.
15736      *
15737      * @param event The motion event to be dispatched.
15738      * @return True if the event was handled by the view, false otherwise.
15739      */
dispatchCapturedPointerEvent(MotionEvent event)15740     public boolean dispatchCapturedPointerEvent(MotionEvent event) {
15741         if (!hasPointerCapture()) {
15742             return false;
15743         }
15744         //noinspection SimplifiableIfStatement
15745         ListenerInfo li = mListenerInfo;
15746         if (li != null && li.mOnCapturedPointerListener != null
15747                 && li.mOnCapturedPointerListener.onCapturedPointer(this, event)) {
15748             return true;
15749         }
15750         return onCapturedPointerEvent(event);
15751     }
15752 
15753     /**
15754      * Dispatch a generic motion event.
15755      * <p>
15756      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
15757      * are delivered to the view under the pointer.  All other generic motion events are
15758      * delivered to the focused view.  Hover events are handled specially and are delivered
15759      * to {@link #onHoverEvent(MotionEvent)} first.
15760      * </p>
15761      *
15762      * @param event The motion event to be dispatched.
15763      * @return True if the event was handled by the view, false otherwise.
15764      *
15765      * @see #onHoverEvent(MotionEvent)
15766      * @see #onGenericMotionEvent(MotionEvent)
15767      */
dispatchGenericMotionEvent(MotionEvent event)15768     public boolean dispatchGenericMotionEvent(MotionEvent event) {
15769         if (mInputEventConsistencyVerifier != null) {
15770             mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
15771         }
15772 
15773         final int source = event.getSource();
15774         if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
15775             final int action = event.getAction();
15776             if (action == MotionEvent.ACTION_HOVER_ENTER
15777                     || action == MotionEvent.ACTION_HOVER_MOVE
15778                     || action == MotionEvent.ACTION_HOVER_EXIT) {
15779                 if (dispatchHoverEvent(event)) {
15780                     return true;
15781                 }
15782             } else if (dispatchGenericPointerEvent(event)) {
15783                 return true;
15784             }
15785         } else if (dispatchGenericFocusedEvent(event)) {
15786             return true;
15787         }
15788 
15789         if (dispatchGenericMotionEventInternal(event)) {
15790             return true;
15791         }
15792 
15793         if (mInputEventConsistencyVerifier != null) {
15794             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
15795         }
15796         return false;
15797     }
15798 
dispatchGenericMotionEventInternal(MotionEvent event)15799     private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
15800         //noinspection SimplifiableIfStatement
15801         ListenerInfo li = mListenerInfo;
15802         if (li != null && li.mOnGenericMotionListener != null
15803                 && (mViewFlags & ENABLED_MASK) == ENABLED
15804                 && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
15805             return true;
15806         }
15807 
15808         if (onGenericMotionEvent(event)) {
15809             return true;
15810         }
15811 
15812         final int actionButton = event.getActionButton();
15813         switch (event.getActionMasked()) {
15814             case MotionEvent.ACTION_BUTTON_PRESS:
15815                 if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
15816                         && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
15817                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
15818                     if (performContextClick(event.getX(), event.getY())) {
15819                         mInContextButtonPress = true;
15820                         setPressed(true, event.getX(), event.getY());
15821                         removeTapCallback();
15822                         removeLongPressCallback();
15823                         return true;
15824                     }
15825                 }
15826                 break;
15827 
15828             case MotionEvent.ACTION_BUTTON_RELEASE:
15829                 if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
15830                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
15831                     mInContextButtonPress = false;
15832                     mIgnoreNextUpEvent = true;
15833                 }
15834                 break;
15835         }
15836 
15837         if (mInputEventConsistencyVerifier != null) {
15838             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
15839         }
15840         return false;
15841     }
15842 
15843     /**
15844      * Dispatch a hover event.
15845      * <p>
15846      * Do not call this method directly.
15847      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
15848      * </p>
15849      *
15850      * @param event The motion event to be dispatched.
15851      * @return True if the event was handled by the view, false otherwise.
15852      */
dispatchHoverEvent(MotionEvent event)15853     protected boolean dispatchHoverEvent(MotionEvent event) {
15854         ListenerInfo li = mListenerInfo;
15855         //noinspection SimplifiableIfStatement
15856         if (li != null && li.mOnHoverListener != null
15857                 && (mViewFlags & ENABLED_MASK) == ENABLED
15858                 && li.mOnHoverListener.onHover(this, event)) {
15859             return true;
15860         }
15861 
15862         return onHoverEvent(event);
15863     }
15864 
15865     /**
15866      * Returns true if the view has a child to which it has recently sent
15867      * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
15868      * it does not have a hovered child, then it must be the innermost hovered view.
15869      * @hide
15870      */
hasHoveredChild()15871     protected boolean hasHoveredChild() {
15872         return false;
15873     }
15874 
15875     /**
15876      * Returns true if the given point, in local coordinates, is inside the hovered child.
15877      *
15878      * @hide
15879      */
pointInHoveredChild(MotionEvent event)15880     protected boolean pointInHoveredChild(MotionEvent event) {
15881         return false;
15882     }
15883 
15884     /**
15885      * Dispatch a generic motion event to the view under the first pointer.
15886      * <p>
15887      * Do not call this method directly.
15888      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
15889      * </p>
15890      *
15891      * @param event The motion event to be dispatched.
15892      * @return True if the event was handled by the view, false otherwise.
15893      */
dispatchGenericPointerEvent(MotionEvent event)15894     protected boolean dispatchGenericPointerEvent(MotionEvent event) {
15895         return false;
15896     }
15897 
15898     /**
15899      * Dispatch a generic motion event to the currently focused view.
15900      * <p>
15901      * Do not call this method directly.
15902      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
15903      * </p>
15904      *
15905      * @param event The motion event to be dispatched.
15906      * @return True if the event was handled by the view, false otherwise.
15907      */
dispatchGenericFocusedEvent(MotionEvent event)15908     protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
15909         return false;
15910     }
15911 
15912     /**
15913      * Dispatch a pointer event.
15914      * <p>
15915      * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
15916      * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
15917      * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
15918      * and should not be expected to handle other pointing device features.
15919      * </p>
15920      *
15921      * @param event The motion event to be dispatched.
15922      * @return True if the event was handled by the view, false otherwise.
15923      * @hide
15924      */
15925     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
dispatchPointerEvent(MotionEvent event)15926     public final boolean dispatchPointerEvent(MotionEvent event) {
15927         if (event.isTouchEvent()) {
15928             return dispatchTouchEvent(event);
15929         } else {
15930             return dispatchGenericMotionEvent(event);
15931         }
15932     }
15933 
15934     /**
15935      * Called when the window containing this view gains or loses window focus.
15936      * ViewGroups should override to route to their children.
15937      *
15938      * @param hasFocus True if the window containing this view now has focus,
15939      *        false otherwise.
15940      */
dispatchWindowFocusChanged(boolean hasFocus)15941     public void dispatchWindowFocusChanged(boolean hasFocus) {
15942         onWindowFocusChanged(hasFocus);
15943     }
15944 
15945     /**
15946      * Called when the window containing this view gains or loses focus.  Note
15947      * that this is separate from view focus: to receive key events, both
15948      * your view and its window must have focus.  If a window is displayed
15949      * on top of yours that takes input focus, then your own window will lose
15950      * focus but the view focus will remain unchanged.
15951      *
15952      * @param hasWindowFocus True if the window containing this view now has
15953      *        focus, false otherwise.
15954      */
onWindowFocusChanged(boolean hasWindowFocus)15955     public void onWindowFocusChanged(boolean hasWindowFocus) {
15956         if (!hasWindowFocus) {
15957             if (isPressed()) {
15958                 setPressed(false);
15959             }
15960             mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
15961             if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
15962                 notifyFocusChangeToImeFocusController(false /* hasFocus */);
15963             }
15964             removeLongPressCallback();
15965             removeTapCallback();
15966             onFocusLost();
15967         } else if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
15968             notifyFocusChangeToImeFocusController(true /* hasFocus */);
15969         }
15970 
15971         refreshDrawableState();
15972     }
15973 
15974     /**
15975      * Returns true if this view is in a window that currently has window focus.
15976      * Note that this is not the same as the view itself having focus.
15977      *
15978      * @return True if this view is in a window that currently has window focus.
15979      */
hasWindowFocus()15980     public boolean hasWindowFocus() {
15981         return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
15982     }
15983 
15984     /**
15985      * @return {@code true} if this view is in a window that currently has IME focusable state.
15986      * @hide
15987      */
hasImeFocus()15988     public boolean hasImeFocus() {
15989         return getViewRootImpl() != null && getViewRootImpl().getImeFocusController().hasImeFocus();
15990     }
15991 
15992     /**
15993      * Dispatch a view visibility change down the view hierarchy.
15994      * ViewGroups should override to route to their children.
15995      * @param changedView The view whose visibility changed. Could be 'this' or
15996      * an ancestor view.
15997      * @param visibility The new visibility of changedView: {@link #VISIBLE},
15998      * {@link #INVISIBLE} or {@link #GONE}.
15999      */
dispatchVisibilityChanged(@onNull View changedView, @Visibility int visibility)16000     protected void dispatchVisibilityChanged(@NonNull View changedView,
16001             @Visibility int visibility) {
16002         onVisibilityChanged(changedView, visibility);
16003     }
16004 
16005     /**
16006      * Called when the visibility of the view or an ancestor of the view has
16007      * changed.
16008      *
16009      * @param changedView The view whose visibility changed. May be
16010      *                    {@code this} or an ancestor view.
16011      * @param visibility The new visibility, one of {@link #VISIBLE},
16012      *                   {@link #INVISIBLE} or {@link #GONE}.
16013      */
onVisibilityChanged(@onNull View changedView, @Visibility int visibility)16014     protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
16015     }
16016 
16017     /**
16018      * Dispatch a hint about whether this view is displayed. For instance, when
16019      * a View moves out of the screen, it might receives a display hint indicating
16020      * the view is not displayed. Applications should not <em>rely</em> on this hint
16021      * as there is no guarantee that they will receive one.
16022      *
16023      * @param hint A hint about whether or not this view is displayed:
16024      * {@link #VISIBLE} or {@link #INVISIBLE}.
16025      */
dispatchDisplayHint(@isibility int hint)16026     public void dispatchDisplayHint(@Visibility int hint) {
16027         onDisplayHint(hint);
16028     }
16029 
16030     /**
16031      * Gives this view a hint about whether is displayed or not. For instance, when
16032      * a View moves out of the screen, it might receives a display hint indicating
16033      * the view is not displayed. Applications should not <em>rely</em> on this hint
16034      * as there is no guarantee that they will receive one.
16035      *
16036      * @param hint A hint about whether or not this view is displayed:
16037      * {@link #VISIBLE} or {@link #INVISIBLE}.
16038      */
onDisplayHint(@isibility int hint)16039     protected void onDisplayHint(@Visibility int hint) {
16040     }
16041 
16042     /**
16043      * Dispatch a window visibility change down the view hierarchy.
16044      * ViewGroups should override to route to their children.
16045      *
16046      * @param visibility The new visibility of the window.
16047      *
16048      * @see #onWindowVisibilityChanged(int)
16049      */
dispatchWindowVisibilityChanged(@isibility int visibility)16050     public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
16051         onWindowVisibilityChanged(visibility);
16052     }
16053 
16054     /**
16055      * Called when the window containing has change its visibility
16056      * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
16057      * that this tells you whether or not your window is being made visible
16058      * to the window manager; this does <em>not</em> tell you whether or not
16059      * your window is obscured by other windows on the screen, even if it
16060      * is itself visible.
16061      *
16062      * @param visibility The new visibility of the window.
16063      */
onWindowVisibilityChanged(@isibility int visibility)16064     protected void onWindowVisibilityChanged(@Visibility int visibility) {
16065         if (visibility == VISIBLE) {
16066             initialAwakenScrollBars();
16067         }
16068     }
16069 
16070     /**
16071      * @return true if this view and all ancestors are visible as of the last
16072      * {@link #onVisibilityAggregated(boolean)} call.
16073      *
16074      * @hide
16075      */
isAggregatedVisible()16076     public boolean isAggregatedVisible() {
16077         return (mPrivateFlags3 & PFLAG3_AGGREGATED_VISIBLE) != 0;
16078     }
16079 
16080     /**
16081      * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
16082      * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
16083      * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
16084      *
16085      * @param isVisible true if this view's visibility to the user is uninterrupted by its
16086      *                  ancestors or by window visibility
16087      * @return true if this view is visible to the user, not counting clipping or overlapping
16088      */
dispatchVisibilityAggregated(boolean isVisible)16089     boolean dispatchVisibilityAggregated(boolean isVisible) {
16090         final boolean thisVisible = getVisibility() == VISIBLE;
16091         // If we're not visible but something is telling us we are, ignore it.
16092         if (thisVisible || !isVisible) {
16093             onVisibilityAggregated(isVisible);
16094         }
16095         return thisVisible && isVisible;
16096     }
16097 
16098     /**
16099      * Called when the user-visibility of this View is potentially affected by a change
16100      * to this view itself, an ancestor view or the window this view is attached to.
16101      *
16102      * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
16103      *                  and this view's window is also visible
16104      */
16105     @CallSuper
onVisibilityAggregated(boolean isVisible)16106     public void onVisibilityAggregated(boolean isVisible) {
16107         // Update our internal visibility tracking so we can detect changes
16108         boolean oldVisible = isAggregatedVisible();
16109         mPrivateFlags3 = isVisible ? (mPrivateFlags3 | PFLAG3_AGGREGATED_VISIBLE)
16110                 : (mPrivateFlags3 & ~PFLAG3_AGGREGATED_VISIBLE);
16111         if (isVisible && mAttachInfo != null) {
16112             initialAwakenScrollBars();
16113         }
16114 
16115         final Drawable dr = mBackground;
16116         if (dr != null && isVisible != dr.isVisible()) {
16117             dr.setVisible(isVisible, false);
16118         }
16119         final Drawable hl = mDefaultFocusHighlight;
16120         if (hl != null && isVisible != hl.isVisible()) {
16121             hl.setVisible(isVisible, false);
16122         }
16123         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
16124         if (fg != null && isVisible != fg.isVisible()) {
16125             fg.setVisible(isVisible, false);
16126         }
16127 
16128         if (isAutofillable()) {
16129             AutofillManager afm = getAutofillManager();
16130 
16131             if (afm != null && getAutofillViewId() > LAST_APP_AUTOFILL_ID) {
16132                 if (mVisibilityChangeForAutofillHandler != null) {
16133                     mVisibilityChangeForAutofillHandler.removeMessages(0);
16134                 }
16135 
16136                 // If the view is in the background but still part of the hierarchy this is called
16137                 // with isVisible=false. Hence visibility==false requires further checks
16138                 if (isVisible) {
16139                     afm.notifyViewVisibilityChanged(this, true);
16140                 } else {
16141                     if (mVisibilityChangeForAutofillHandler == null) {
16142                         mVisibilityChangeForAutofillHandler =
16143                                 new VisibilityChangeForAutofillHandler(afm, this);
16144                     }
16145                     // Let current operation (e.g. removal of the view from the hierarchy)
16146                     // finish before checking state
16147                     mVisibilityChangeForAutofillHandler.obtainMessage(0, this).sendToTarget();
16148                 }
16149             }
16150         }
16151 
16152         if (isVisible != oldVisible) {
16153             if (isAccessibilityPane()) {
16154                 notifyViewAccessibilityStateChangedIfNeeded(isVisible
16155                         ? AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_APPEARED
16156                         : AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED);
16157             }
16158 
16159             notifyAppearedOrDisappearedForContentCaptureIfNeeded(isVisible);
16160 
16161             if (!getSystemGestureExclusionRects().isEmpty()) {
16162                 postUpdate(this::updateSystemGestureExclusionRects);
16163             }
16164 
16165             if (!collectPreferKeepClearRects().isEmpty()) {
16166                 postUpdate(this::updateKeepClearRects);
16167             }
16168         }
16169     }
16170 
16171     /**
16172      * Returns the current visibility of the window this view is attached to
16173      * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
16174      *
16175      * @return Returns the current visibility of the view's window.
16176      */
16177     @Visibility
getWindowVisibility()16178     public int getWindowVisibility() {
16179         return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
16180     }
16181 
16182     /**
16183      * Retrieve the overall visible display size in which the window this view is
16184      * attached to has been positioned in.  This takes into account screen
16185      * decorations above the window, for both cases where the window itself
16186      * is being position inside of them or the window is being placed under
16187      * then and covered insets are used for the window to position its content
16188      * inside.  In effect, this tells you the available area where content can
16189      * be placed and remain visible to users.
16190      *
16191      * @param outRect Filled in with the visible display frame.  If the view
16192      * is not attached to a window, this is simply the raw display size.
16193      */
getWindowVisibleDisplayFrame(Rect outRect)16194     public void getWindowVisibleDisplayFrame(Rect outRect) {
16195         if (mAttachInfo != null) {
16196             mAttachInfo.mViewRootImpl.getWindowVisibleDisplayFrame(outRect);
16197             return;
16198         }
16199         // The view is not attached to a display so we don't have a context.
16200         // Make a best guess about the display size.
16201         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
16202         d.getRectSize(outRect);
16203     }
16204 
16205     /**
16206      * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
16207      * is currently in without any insets.
16208      *
16209      * @hide
16210      */
16211     @UnsupportedAppUsage
16212     @TestApi
getWindowDisplayFrame(@onNull Rect outRect)16213     public void getWindowDisplayFrame(@NonNull Rect outRect) {
16214         if (mAttachInfo != null) {
16215             mAttachInfo.mViewRootImpl.getDisplayFrame(outRect);
16216             return;
16217         }
16218         // The view is not attached to a display so we don't have a context.
16219         // Make a best guess about the display size.
16220         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
16221         d.getRectSize(outRect);
16222     }
16223 
16224     /**
16225      * Dispatch a notification about a resource configuration change down
16226      * the view hierarchy.
16227      * ViewGroups should override to route to their children.
16228      *
16229      * @param newConfig The new resource configuration.
16230      *
16231      * @see #onConfigurationChanged(android.content.res.Configuration)
16232      */
dispatchConfigurationChanged(Configuration newConfig)16233     public void dispatchConfigurationChanged(Configuration newConfig) {
16234         onConfigurationChanged(newConfig);
16235     }
16236 
16237     /**
16238      * Called when the current configuration of the resources being used
16239      * by the application have changed.  You can use this to decide when
16240      * to reload resources that can changed based on orientation and other
16241      * configuration characteristics.  You only need to use this if you are
16242      * not relying on the normal {@link android.app.Activity} mechanism of
16243      * recreating the activity instance upon a configuration change.
16244      *
16245      * @param newConfig The new resource configuration.
16246      */
onConfigurationChanged(Configuration newConfig)16247     protected void onConfigurationChanged(Configuration newConfig) {
16248     }
16249 
16250     /**
16251      * Private function to aggregate all per-view attributes in to the view
16252      * root.
16253      */
dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility)16254     void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
16255         performCollectViewAttributes(attachInfo, visibility);
16256     }
16257 
performCollectViewAttributes(AttachInfo attachInfo, int visibility)16258     void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
16259         if ((visibility & VISIBILITY_MASK) == VISIBLE) {
16260             if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
16261                 attachInfo.mKeepScreenOn = true;
16262             }
16263             attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
16264             ListenerInfo li = mListenerInfo;
16265             if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
16266                 attachInfo.mHasSystemUiListeners = true;
16267             }
16268         }
16269     }
16270 
needGlobalAttributesUpdate(boolean force)16271     void needGlobalAttributesUpdate(boolean force) {
16272         final AttachInfo ai = mAttachInfo;
16273         if (ai != null && !ai.mRecomputeGlobalAttributes) {
16274             if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
16275                     || ai.mHasSystemUiListeners) {
16276                 ai.mRecomputeGlobalAttributes = true;
16277             }
16278         }
16279     }
16280 
16281     /**
16282      * Returns the touch mode state associated with this view.
16283      *
16284      * Attached views return the touch mode state from the associated window's display.
16285      * Detached views just return the default touch mode value defined in
16286      * {@code com.android.internal.R.bool.config_defaultInTouchMode}.
16287      *
16288      * Touch mode is entered once the user begins interacting with the device by touch, and
16289      * affects various things like whether focus highlight is always visible to the user.
16290      *
16291      * @return the touch mode state associated with this view
16292      */
16293     @ViewDebug.ExportedProperty
isInTouchMode()16294     public boolean isInTouchMode() {
16295         if (mAttachInfo != null) {
16296             return mAttachInfo.mInTouchMode;
16297         }
16298         return mResources.getBoolean(com.android.internal.R.bool.config_defaultInTouchMode);
16299     }
16300 
16301     /**
16302      * Returns the context the view is running in, through which it can
16303      * access the current theme, resources, etc.
16304      *
16305      * @return The view's Context.
16306      */
16307     @ViewDebug.CapturedViewProperty
16308     @UiContext
getContext()16309     public final Context getContext() {
16310         return mContext;
16311     }
16312 
16313     /**
16314      * Handle a key event before it is processed by any input method
16315      * associated with the view hierarchy.  This can be used to intercept
16316      * key events in special situations before the IME consumes them; a
16317      * typical example would be handling the BACK key to update the application's
16318      * UI instead of allowing the IME to see it and close itself.
16319      *
16320      * @param keyCode The value in event.getKeyCode().
16321      * @param event Description of the key event.
16322      * @return If you handled the event, return true. If you want to allow the
16323      *         event to be handled by the next receiver, return false.
16324      */
onKeyPreIme(int keyCode, KeyEvent event)16325     public boolean onKeyPreIme(int keyCode, KeyEvent event) {
16326         return false;
16327     }
16328 
16329     /**
16330      * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
16331      * KeyEvent.Callback.onKeyDown()}: perform press of the view
16332      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
16333      * is released, if the view is enabled and clickable.
16334      * <p>
16335      * Key presses in software keyboards will generally NOT trigger this
16336      * listener, although some may elect to do so in some situations. Do not
16337      * rely on this to catch software key presses.
16338      *
16339      * @param keyCode a key code that represents the button pressed, from
16340      *                {@link android.view.KeyEvent}
16341      * @param event the KeyEvent object that defines the button action
16342      */
onKeyDown(int keyCode, KeyEvent event)16343     public boolean onKeyDown(int keyCode, KeyEvent event) {
16344         if (KeyEvent.isConfirmKey(keyCode) && event.hasNoModifiers()) {
16345             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
16346                 return true;
16347             }
16348 
16349             if (event.getRepeatCount() == 0) {
16350                 // Long clickable items don't necessarily have to be clickable.
16351                 final boolean clickable = (mViewFlags & CLICKABLE) == CLICKABLE
16352                         || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
16353                 if (clickable || (mViewFlags & TOOLTIP) == TOOLTIP) {
16354                     // For the purposes of menu anchoring and drawable hotspots,
16355                     // key events are considered to be at the center of the view.
16356                     final float x = getWidth() / 2f;
16357                     final float y = getHeight() / 2f;
16358                     if (clickable) {
16359                         setPressed(true, x, y);
16360                     }
16361                     checkForLongClick(
16362                             ViewConfiguration.getLongPressTimeout(),
16363                             x,
16364                             y,
16365                             // This is not a touch gesture -- do not classify it as one.
16366                             TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION);
16367                     return true;
16368                 }
16369             }
16370         }
16371 
16372         return false;
16373     }
16374 
16375     /**
16376      * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
16377      * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
16378      * the event).
16379      * <p>Key presses in software keyboards will generally NOT trigger this listener,
16380      * although some may elect to do so in some situations. Do not rely on this to
16381      * catch software key presses.
16382      */
onKeyLongPress(int keyCode, KeyEvent event)16383     public boolean onKeyLongPress(int keyCode, KeyEvent event) {
16384         return false;
16385     }
16386 
16387     /**
16388      * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
16389      * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
16390      * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
16391      * or {@link KeyEvent#KEYCODE_SPACE} is released.
16392      * <p>Key presses in software keyboards will generally NOT trigger this listener,
16393      * although some may elect to do so in some situations. Do not rely on this to
16394      * catch software key presses.
16395      *
16396      * @param keyCode A key code that represents the button pressed, from
16397      *                {@link android.view.KeyEvent}.
16398      * @param event   The KeyEvent object that defines the button action.
16399      */
onKeyUp(int keyCode, KeyEvent event)16400     public boolean onKeyUp(int keyCode, KeyEvent event) {
16401         if (KeyEvent.isConfirmKey(keyCode) && event.hasNoModifiers()) {
16402             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
16403                 return true;
16404             }
16405             if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
16406                 setPressed(false);
16407 
16408                 if (!mHasPerformedLongPress) {
16409                     // This is a tap, so remove the longpress check
16410                     removeLongPressCallback();
16411                     if (!event.isCanceled()) {
16412                         return performClickInternal();
16413                     }
16414                 }
16415             }
16416         }
16417         return false;
16418     }
16419 
16420     /**
16421      * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
16422      * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
16423      * the event).
16424      * <p>Key presses in software keyboards will generally NOT trigger this listener,
16425      * although some may elect to do so in some situations. Do not rely on this to
16426      * catch software key presses.
16427      *
16428      * @param keyCode     A key code that represents the button pressed, from
16429      *                    {@link android.view.KeyEvent}.
16430      * @param repeatCount The number of times the action was made.
16431      * @param event       The KeyEvent object that defines the button action.
16432      */
onKeyMultiple(int keyCode, int repeatCount, KeyEvent event)16433     public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
16434         return false;
16435     }
16436 
16437     /**
16438      * Called on the focused view when a key shortcut event is not handled.
16439      * Override this method to implement local key shortcuts for the View.
16440      * Key shortcuts can also be implemented by setting the
16441      * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
16442      *
16443      * @param keyCode The value in event.getKeyCode().
16444      * @param event Description of the key event.
16445      * @return If you handled the event, return true. If you want to allow the
16446      *         event to be handled by the next receiver, return false.
16447      */
onKeyShortcut(int keyCode, KeyEvent event)16448     public boolean onKeyShortcut(int keyCode, KeyEvent event) {
16449         return false;
16450     }
16451 
16452     /**
16453      * Check whether the called view is a text editor, in which case it
16454      * would make sense to automatically display a soft input window for
16455      * it.  Subclasses should override this if they implement
16456      * {@link #onCreateInputConnection(EditorInfo)} to return true if
16457      * a call on that method would return a non-null InputConnection, and
16458      * they are really a first-class editor that the user would normally
16459      * start typing on when the go into a window containing your view.
16460      *
16461      * <p>The default implementation always returns false.  This does
16462      * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
16463      * will not be called or the user can not otherwise perform edits on your
16464      * view; it is just a hint to the system that this is not the primary
16465      * purpose of this view.
16466      *
16467      * @return Returns true if this view is a text editor, else false.
16468      */
onCheckIsTextEditor()16469     public boolean onCheckIsTextEditor() {
16470         return false;
16471     }
16472 
16473     /**
16474      * Create a new InputConnection for an InputMethod to interact
16475      * with the view.  The default implementation returns null, since it doesn't
16476      * support input methods.  You can override this to implement such support.
16477      * This is only needed for views that take focus and text input.
16478      *
16479      * <p>When implementing this, you probably also want to implement
16480      * {@link #onCheckIsTextEditor()} to indicate you will return a
16481      * non-null InputConnection.</p>
16482      *
16483      * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
16484      * object correctly and in its entirety, so that the connected IME can rely
16485      * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
16486      * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
16487      * must be filled in with the correct cursor position for IMEs to work correctly
16488      * with your application.</p>
16489      *
16490      * @param outAttrs Fill in with attribute information about the connection.
16491      */
onCreateInputConnection(EditorInfo outAttrs)16492     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
16493         return null;
16494     }
16495 
16496     /**
16497      * Called by the {@link android.view.inputmethod.InputMethodManager} to notify the application
16498      * that the system has successfully initialized an {@link InputConnection} and it is ready for
16499      * use.
16500      *
16501      * <p>The default implementation does nothing, since a view doesn't support input methods by
16502      * default (see {@link #onCreateInputConnection}).
16503      *
16504      * @param inputConnection The {@link InputConnection} from {@link #onCreateInputConnection},
16505      * after it's been fully initialized by the system.
16506      * @param editorInfo The {@link EditorInfo} that was used to create the {@link InputConnection}.
16507      * @param handler The dedicated {@link Handler} on which IPC method calls from input methods
16508      * will be dispatched. This is the handler returned by {@link InputConnection#getHandler()}. If
16509      * that method returns null, this parameter will be null also.
16510      *
16511      * @hide
16512      */
onInputConnectionOpenedInternal(@onNull InputConnection inputConnection, @NonNull EditorInfo editorInfo, @Nullable Handler handler)16513     public void onInputConnectionOpenedInternal(@NonNull InputConnection inputConnection,
16514             @NonNull EditorInfo editorInfo, @Nullable Handler handler) {}
16515 
16516     /**
16517      * Called by the {@link android.view.inputmethod.InputMethodManager} to notify the application
16518      * that the {@link InputConnection} has been closed.
16519      *
16520      * <p>The default implementation does nothing, since a view doesn't support input methods by
16521      * default (see {@link #onCreateInputConnection}).
16522      *
16523      * <p><strong>Note:</strong> This callback is not invoked if the view is already detached when
16524      * the {@link InputConnection} is closed or the connection is not valid and managed by
16525      * {@link com.android.server.inputmethod.InputMethodManagerService}.
16526      * TODO(b/170645312): Before un-hiding this API, handle the detached view scenario.
16527      *
16528      * @hide
16529      */
onInputConnectionClosedInternal()16530     public void onInputConnectionClosedInternal() {}
16531 
16532     /**
16533      * Called by the {@link android.view.inputmethod.InputMethodManager}
16534      * when a view who is not the current
16535      * input connection target is trying to make a call on the manager.  The
16536      * default implementation returns false; you can override this to return
16537      * true for certain views if you are performing InputConnection proxying
16538      * to them.
16539      * @param view The View that is making the InputMethodManager call.
16540      * @return Return true to allow the call, false to reject.
16541      */
checkInputConnectionProxy(View view)16542     public boolean checkInputConnectionProxy(View view) {
16543         return false;
16544     }
16545 
16546     /**
16547      * Show the context menu for this view. It is not safe to hold on to the
16548      * menu after returning from this method.
16549      *
16550      * You should normally not overload this method. Overload
16551      * {@link #onCreateContextMenu(ContextMenu)} or define an
16552      * {@link OnCreateContextMenuListener} to add items to the context menu.
16553      *
16554      * @param menu The context menu to populate
16555      */
createContextMenu(ContextMenu menu)16556     public void createContextMenu(ContextMenu menu) {
16557         ContextMenuInfo menuInfo = getContextMenuInfo();
16558 
16559         // Sets the current menu info so all items added to menu will have
16560         // my extra info set.
16561         ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
16562 
16563         onCreateContextMenu(menu);
16564         ListenerInfo li = mListenerInfo;
16565         if (li != null && li.mOnCreateContextMenuListener != null) {
16566             li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
16567         }
16568 
16569         // Clear the extra information so subsequent items that aren't mine don't
16570         // have my extra info.
16571         ((MenuBuilder)menu).setCurrentMenuInfo(null);
16572 
16573         if (mParent != null) {
16574             mParent.createContextMenu(menu);
16575         }
16576     }
16577 
16578     /**
16579      * Views should implement this if they have extra information to associate
16580      * with the context menu. The return result is supplied as a parameter to
16581      * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
16582      * callback.
16583      *
16584      * @return Extra information about the item for which the context menu
16585      *         should be shown. This information will vary across different
16586      *         subclasses of View.
16587      */
getContextMenuInfo()16588     protected ContextMenuInfo getContextMenuInfo() {
16589         return null;
16590     }
16591 
16592     /**
16593      * Views should implement this if the view itself is going to add items to
16594      * the context menu.
16595      *
16596      * @param menu the context menu to populate
16597      */
onCreateContextMenu(ContextMenu menu)16598     protected void onCreateContextMenu(ContextMenu menu) {
16599     }
16600 
16601     /**
16602      * Implement this method to handle trackball motion events.
16603      * <p>
16604      * The <em>relative</em> movement of the trackball since the last event
16605      * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
16606      * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
16607      * that a movement of 1 corresponds to the user pressing one DPAD key (so
16608      * they will often be fractional values, representing the more fine-grained
16609      * movement information available from a trackball).
16610      * </p>
16611      *
16612      * @param event The motion event.
16613      * @return True if the event was handled, false otherwise.
16614      */
onTrackballEvent(MotionEvent event)16615     public boolean onTrackballEvent(MotionEvent event) {
16616         return false;
16617     }
16618 
16619     /**
16620      * Implement this method to handle generic motion events.
16621      * <p>
16622      * Generic motion events describe joystick movements, hover events from mouse or stylus
16623      * devices, trackpad touches, scroll wheel movements and other motion events not handled
16624      * by {@link #onTouchEvent(MotionEvent)} or {@link #onTrackballEvent(MotionEvent)}.
16625      * The {@link MotionEvent#getSource() source} of the motion event specifies
16626      * the class of input that was received.  Implementations of this method
16627      * must examine the bits in the source before processing the event.
16628      * The following code example shows how this is done.
16629      * </p><p>
16630      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
16631      * are delivered to the view under the pointer.  All other generic motion events are
16632      * delivered to the focused view.
16633      * </p>
16634      * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
16635      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
16636      *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
16637      *             // process the joystick movement...
16638      *             return true;
16639      *         }
16640      *     }
16641      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
16642      *         switch (event.getAction()) {
16643      *             case MotionEvent.ACTION_HOVER_MOVE:
16644      *                 // process the hover movement...
16645      *                 return true;
16646      *             case MotionEvent.ACTION_SCROLL:
16647      *                 // process the scroll wheel movement...
16648      *                 return true;
16649      *         }
16650      *     }
16651      *     return super.onGenericMotionEvent(event);
16652      * }</pre>
16653      *
16654      * @param event The generic motion event being processed.
16655      * @return True if the event was handled, false otherwise.
16656      */
onGenericMotionEvent(MotionEvent event)16657     public boolean onGenericMotionEvent(MotionEvent event) {
16658         return false;
16659     }
16660 
16661     /**
16662      * Dispatching hover events to {@link TouchDelegate} to improve accessibility.
16663      * <p>
16664      * This method is dispatching hover events to the delegate target to support explore by touch.
16665      * Similar to {@link ViewGroup#dispatchTouchEvent}, this method send proper hover events to
16666      * the delegate target according to the pointer and the touch area of the delegate while touch
16667      * exploration enabled.
16668      * </p>
16669      *
16670      * @param event The motion event dispatch to the delegate target.
16671      * @return True if the event was handled, false otherwise.
16672      *
16673      * @see #onHoverEvent
16674      */
dispatchTouchExplorationHoverEvent(MotionEvent event)16675     private boolean dispatchTouchExplorationHoverEvent(MotionEvent event) {
16676         final AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
16677         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
16678             return false;
16679         }
16680 
16681         final boolean oldHoveringTouchDelegate = mHoveringTouchDelegate;
16682         final int action = event.getActionMasked();
16683         boolean pointInDelegateRegion = false;
16684         boolean handled = false;
16685 
16686         final AccessibilityNodeInfo.TouchDelegateInfo info = mTouchDelegate.getTouchDelegateInfo();
16687         for (int i = 0; i < info.getRegionCount(); i++) {
16688             Region r = info.getRegionAt(i);
16689             if (r.contains((int) event.getX(), (int) event.getY())) {
16690                 pointInDelegateRegion = true;
16691             }
16692         }
16693 
16694         // Explore by touch should dispatch events to children under the pointer first if any
16695         // before dispatching to TouchDelegate. For non-hoverable views that do not consume
16696         // hover events but receive accessibility focus, it should also not delegate to these
16697         // views when hovered.
16698         if (!oldHoveringTouchDelegate) {
16699             if ((action == MotionEvent.ACTION_HOVER_ENTER
16700                     || action == MotionEvent.ACTION_HOVER_MOVE)
16701                     && !pointInHoveredChild(event)
16702                     && pointInDelegateRegion) {
16703                 mHoveringTouchDelegate = true;
16704             }
16705         } else {
16706             if (action == MotionEvent.ACTION_HOVER_EXIT
16707                     || (action == MotionEvent.ACTION_HOVER_MOVE
16708                         && (pointInHoveredChild(event) || !pointInDelegateRegion))) {
16709                 mHoveringTouchDelegate = false;
16710             }
16711         }
16712         switch (action) {
16713             case MotionEvent.ACTION_HOVER_MOVE:
16714                 if (oldHoveringTouchDelegate && mHoveringTouchDelegate) {
16715                     // Inside bounds, dispatch as is.
16716                     handled = mTouchDelegate.onTouchExplorationHoverEvent(event);
16717                 } else if (!oldHoveringTouchDelegate && mHoveringTouchDelegate) {
16718                     // Moving inbound, synthesize hover enter.
16719                     MotionEvent eventNoHistory = (event.getHistorySize() == 0)
16720                             ? event : MotionEvent.obtainNoHistory(event);
16721                     eventNoHistory.setAction(MotionEvent.ACTION_HOVER_ENTER);
16722                     handled = mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
16723                     eventNoHistory.setAction(action);
16724                     handled |= mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
16725                 } else if (oldHoveringTouchDelegate && !mHoveringTouchDelegate) {
16726                     // Moving outbound, synthesize hover exit.
16727                     final boolean hoverExitPending = event.isHoverExitPending();
16728                     event.setHoverExitPending(true);
16729                     mTouchDelegate.onTouchExplorationHoverEvent(event);
16730                     MotionEvent eventNoHistory = (event.getHistorySize() == 0)
16731                             ? event : MotionEvent.obtainNoHistory(event);
16732                     eventNoHistory.setHoverExitPending(hoverExitPending);
16733                     eventNoHistory.setAction(MotionEvent.ACTION_HOVER_EXIT);
16734                     mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
16735                 }  // else: outside bounds, do nothing.
16736                 break;
16737             case MotionEvent.ACTION_HOVER_ENTER:
16738                 if (!oldHoveringTouchDelegate && mHoveringTouchDelegate) {
16739                     handled = mTouchDelegate.onTouchExplorationHoverEvent(event);
16740                 }
16741                 break;
16742             case MotionEvent.ACTION_HOVER_EXIT:
16743                 if (oldHoveringTouchDelegate) {
16744                     mTouchDelegate.onTouchExplorationHoverEvent(event);
16745                 }
16746                 break;
16747         }
16748         return handled;
16749     }
16750 
16751     /**
16752      * Implement this method to handle hover events.
16753      * <p>
16754      * This method is called whenever a pointer is hovering into, over, or out of the
16755      * bounds of a view and the view is not currently being touched.
16756      * Hover events are represented as pointer events with action
16757      * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
16758      * or {@link MotionEvent#ACTION_HOVER_EXIT}.
16759      * </p>
16760      * <ul>
16761      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
16762      * when the pointer enters the bounds of the view.</li>
16763      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
16764      * when the pointer has already entered the bounds of the view and has moved.</li>
16765      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
16766      * when the pointer has exited the bounds of the view or when the pointer is
16767      * about to go down due to a button click, tap, or similar user action that
16768      * causes the view to be touched.</li>
16769      * </ul>
16770      * <p>
16771      * The view should implement this method to return true to indicate that it is
16772      * handling the hover event, such as by changing its drawable state.
16773      * </p><p>
16774      * The default implementation calls {@link #setHovered} to update the hovered state
16775      * of the view when a hover enter or hover exit event is received, if the view
16776      * is enabled and is clickable.  The default implementation also sends hover
16777      * accessibility events.
16778      * </p>
16779      *
16780      * @param event The motion event that describes the hover.
16781      * @return True if the view handled the hover event.
16782      *
16783      * @see #isHovered
16784      * @see #setHovered
16785      * @see #onHoverChanged
16786      */
onHoverEvent(MotionEvent event)16787     public boolean onHoverEvent(MotionEvent event) {
16788         if (mTouchDelegate != null && dispatchTouchExplorationHoverEvent(event)) {
16789             return true;
16790         }
16791 
16792         // The root view may receive hover (or touch) events that are outside the bounds of
16793         // the window.  This code ensures that we only send accessibility events for
16794         // hovers that are actually within the bounds of the root view.
16795         final int action = event.getActionMasked();
16796         if (!mSendingHoverAccessibilityEvents) {
16797             if ((action == MotionEvent.ACTION_HOVER_ENTER
16798                     || action == MotionEvent.ACTION_HOVER_MOVE)
16799                     && !hasHoveredChild()
16800                     && pointInView(event.getX(), event.getY())) {
16801                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
16802                 mSendingHoverAccessibilityEvents = true;
16803             }
16804         } else {
16805             if (action == MotionEvent.ACTION_HOVER_EXIT
16806                     || (action == MotionEvent.ACTION_HOVER_MOVE
16807                             && !pointInView(event.getX(), event.getY()))) {
16808                 mSendingHoverAccessibilityEvents = false;
16809                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
16810             }
16811         }
16812 
16813         if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
16814                 && event.isFromSource(InputDevice.SOURCE_MOUSE)
16815                 && isOnScrollbar(event.getX(), event.getY())) {
16816             awakenScrollBars();
16817         }
16818 
16819         // If we consider ourself hoverable, or if we we're already hovered,
16820         // handle changing state in response to ENTER and EXIT events.
16821         if (isHoverable() || isHovered()) {
16822             switch (action) {
16823                 case MotionEvent.ACTION_HOVER_ENTER:
16824                     setHovered(true);
16825                     break;
16826                 case MotionEvent.ACTION_HOVER_EXIT:
16827                     setHovered(false);
16828                     break;
16829             }
16830 
16831             // Dispatch the event to onGenericMotionEvent before returning true.
16832             // This is to provide compatibility with existing applications that
16833             // handled HOVER_MOVE events in onGenericMotionEvent and that would
16834             // break because of the new default handling for hoverable views
16835             // in onHoverEvent.
16836             // Note that onGenericMotionEvent will be called by default when
16837             // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
16838             dispatchGenericMotionEventInternal(event);
16839             // The event was already handled by calling setHovered(), so always
16840             // return true.
16841             return true;
16842         }
16843 
16844         return false;
16845     }
16846 
16847     /**
16848      * Returns true if the view should handle {@link #onHoverEvent}
16849      * by calling {@link #setHovered} to change its hovered state.
16850      *
16851      * @return True if the view is hoverable.
16852      */
isHoverable()16853     private boolean isHoverable() {
16854         final int viewFlags = mViewFlags;
16855         if ((viewFlags & ENABLED_MASK) == DISABLED) {
16856             return false;
16857         }
16858 
16859         return (viewFlags & CLICKABLE) == CLICKABLE
16860                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
16861                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
16862     }
16863 
16864     /**
16865      * Returns true if the view is currently hovered.
16866      *
16867      * @return True if the view is currently hovered.
16868      *
16869      * @see #setHovered
16870      * @see #onHoverChanged
16871      */
16872     @ViewDebug.ExportedProperty
isHovered()16873     public boolean isHovered() {
16874         return (mPrivateFlags & PFLAG_HOVERED) != 0;
16875     }
16876 
16877     /**
16878      * Sets whether the view is currently hovered.
16879      * <p>
16880      * Calling this method also changes the drawable state of the view.  This
16881      * enables the view to react to hover by using different drawable resources
16882      * to change its appearance.
16883      * </p><p>
16884      * The {@link #onHoverChanged} method is called when the hovered state changes.
16885      * </p>
16886      *
16887      * @param hovered True if the view is hovered.
16888      *
16889      * @see #isHovered
16890      * @see #onHoverChanged
16891      */
setHovered(boolean hovered)16892     public void setHovered(boolean hovered) {
16893         if (hovered) {
16894             if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
16895                 mPrivateFlags |= PFLAG_HOVERED;
16896                 refreshDrawableState();
16897                 onHoverChanged(true);
16898             }
16899         } else {
16900             if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
16901                 mPrivateFlags &= ~PFLAG_HOVERED;
16902                 refreshDrawableState();
16903                 onHoverChanged(false);
16904             }
16905         }
16906     }
16907 
16908     /**
16909      * Implement this method to handle hover state changes.
16910      * <p>
16911      * This method is called whenever the hover state changes as a result of a
16912      * call to {@link #setHovered}.
16913      * </p>
16914      *
16915      * @param hovered The current hover state, as returned by {@link #isHovered}.
16916      *
16917      * @see #isHovered
16918      * @see #setHovered
16919      */
onHoverChanged(boolean hovered)16920     public void onHoverChanged(boolean hovered) {
16921     }
16922 
16923     /**
16924      * Handles scroll bar dragging by mouse input.
16925      *
16926      * @hide
16927      * @param event The motion event.
16928      *
16929      * @return true if the event was handled as a scroll bar dragging, false otherwise.
16930      */
handleScrollBarDragging(MotionEvent event)16931     protected boolean handleScrollBarDragging(MotionEvent event) {
16932         if (mScrollCache == null) {
16933             return false;
16934         }
16935         final float x = event.getX();
16936         final float y = event.getY();
16937         final int action = event.getAction();
16938         if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
16939                 && action != MotionEvent.ACTION_DOWN)
16940                     || !event.isFromSource(InputDevice.SOURCE_MOUSE)
16941                     || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
16942             mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
16943             return false;
16944         }
16945 
16946         switch (action) {
16947             case MotionEvent.ACTION_MOVE:
16948                 if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
16949                     return false;
16950                 }
16951                 if (mScrollCache.mScrollBarDraggingState
16952                         == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
16953                     final Rect bounds = mScrollCache.mScrollBarBounds;
16954                     getVerticalScrollBarBounds(bounds, null);
16955                     final int range = computeVerticalScrollRange();
16956                     final int offset = computeVerticalScrollOffset();
16957                     final int extent = computeVerticalScrollExtent();
16958 
16959                     final int thumbLength = ScrollBarUtils.getThumbLength(
16960                             bounds.height(), bounds.width(), extent, range);
16961                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
16962                             bounds.height(), thumbLength, extent, range, offset);
16963 
16964                     final float diff = y - mScrollCache.mScrollBarDraggingPos;
16965                     final float maxThumbOffset = bounds.height() - thumbLength;
16966                     final float newThumbOffset =
16967                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
16968                     final int height = getHeight();
16969                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
16970                             && height > 0 && extent > 0) {
16971                         final int newY = Math.round((range - extent)
16972                                 / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
16973                         if (newY != getScrollY()) {
16974                             mScrollCache.mScrollBarDraggingPos = y;
16975                             setScrollY(newY);
16976                         }
16977                     }
16978                     return true;
16979                 }
16980                 if (mScrollCache.mScrollBarDraggingState
16981                         == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
16982                     final Rect bounds = mScrollCache.mScrollBarBounds;
16983                     getHorizontalScrollBarBounds(bounds, null);
16984                     final int range = computeHorizontalScrollRange();
16985                     final int offset = computeHorizontalScrollOffset();
16986                     final int extent = computeHorizontalScrollExtent();
16987 
16988                     final int thumbLength = ScrollBarUtils.getThumbLength(
16989                             bounds.width(), bounds.height(), extent, range);
16990                     final int thumbOffset = ScrollBarUtils.getThumbOffset(
16991                             bounds.width(), thumbLength, extent, range, offset);
16992 
16993                     final float diff = x - mScrollCache.mScrollBarDraggingPos;
16994                     final float maxThumbOffset = bounds.width() - thumbLength;
16995                     final float newThumbOffset =
16996                             Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
16997                     final int width = getWidth();
16998                     if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
16999                             && width > 0 && extent > 0) {
17000                         final int newX = Math.round((range - extent)
17001                                 / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
17002                         if (newX != getScrollX()) {
17003                             mScrollCache.mScrollBarDraggingPos = x;
17004                             setScrollX(newX);
17005                         }
17006                     }
17007                     return true;
17008                 }
17009             case MotionEvent.ACTION_DOWN:
17010                 if (mScrollCache.state == ScrollabilityCache.OFF) {
17011                     return false;
17012                 }
17013                 if (isOnVerticalScrollbarThumb(x, y)) {
17014                     mScrollCache.mScrollBarDraggingState =
17015                             ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
17016                     mScrollCache.mScrollBarDraggingPos = y;
17017                     return true;
17018                 }
17019                 if (isOnHorizontalScrollbarThumb(x, y)) {
17020                     mScrollCache.mScrollBarDraggingState =
17021                             ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
17022                     mScrollCache.mScrollBarDraggingPos = x;
17023                     return true;
17024                 }
17025         }
17026         mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
17027         return false;
17028     }
17029 
17030     /**
17031      * Implement this method to handle touch screen motion events.
17032      * <p>
17033      * If this method is used to detect click actions, it is recommended that
17034      * the actions be performed by implementing and calling
17035      * {@link #performClick()}. This will ensure consistent system behavior,
17036      * including:
17037      * <ul>
17038      * <li>obeying click sound preferences
17039      * <li>dispatching OnClickListener calls
17040      * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
17041      * accessibility features are enabled
17042      * </ul>
17043      *
17044      * @param event The motion event.
17045      * @return True if the event was handled, false otherwise.
17046      */
onTouchEvent(MotionEvent event)17047     public boolean onTouchEvent(MotionEvent event) {
17048         final float x = event.getX();
17049         final float y = event.getY();
17050         final int viewFlags = mViewFlags;
17051         final int action = event.getAction();
17052 
17053         final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE
17054                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
17055                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
17056 
17057         if ((viewFlags & ENABLED_MASK) == DISABLED
17058                 && (mPrivateFlags4 & PFLAG4_ALLOW_CLICK_WHEN_DISABLED) == 0) {
17059             if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
17060                 setPressed(false);
17061             }
17062             mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
17063             // A disabled view that is clickable still consumes the touch
17064             // events, it just doesn't respond to them.
17065             return clickable;
17066         }
17067         if (mTouchDelegate != null) {
17068             if (mTouchDelegate.onTouchEvent(event)) {
17069                 return true;
17070             }
17071         }
17072 
17073         if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
17074             switch (action) {
17075                 case MotionEvent.ACTION_UP:
17076                     mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
17077                     if ((viewFlags & TOOLTIP) == TOOLTIP) {
17078                         handleTooltipUp();
17079                     }
17080                     if (!clickable) {
17081                         removeTapCallback();
17082                         removeLongPressCallback();
17083                         mInContextButtonPress = false;
17084                         mHasPerformedLongPress = false;
17085                         mIgnoreNextUpEvent = false;
17086                         break;
17087                     }
17088                     boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
17089                     if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
17090                         // take focus if we don't have it already and we should in
17091                         // touch mode.
17092                         boolean focusTaken = false;
17093                         if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
17094                             focusTaken = requestFocus();
17095                         }
17096 
17097                         if (prepressed) {
17098                             // The button is being released before we actually
17099                             // showed it as pressed.  Make it show the pressed
17100                             // state now (before scheduling the click) to ensure
17101                             // the user sees it.
17102                             setPressed(true, x, y);
17103                         }
17104 
17105                         if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
17106                             // This is a tap, so remove the longpress check
17107                             removeLongPressCallback();
17108 
17109                             // Only perform take click actions if we were in the pressed state
17110                             if (!focusTaken) {
17111                                 // Use a Runnable and post this rather than calling
17112                                 // performClick directly. This lets other visual state
17113                                 // of the view update before click actions start.
17114                                 if (mPerformClick == null) {
17115                                     mPerformClick = new PerformClick();
17116                                 }
17117                                 if (!post(mPerformClick)) {
17118                                     performClickInternal();
17119                                 }
17120                             }
17121                         }
17122 
17123                         if (mUnsetPressedState == null) {
17124                             mUnsetPressedState = new UnsetPressedState();
17125                         }
17126 
17127                         if (prepressed) {
17128                             postDelayed(mUnsetPressedState,
17129                                     ViewConfiguration.getPressedStateDuration());
17130                         } else if (!post(mUnsetPressedState)) {
17131                             // If the post failed, unpress right now
17132                             mUnsetPressedState.run();
17133                         }
17134 
17135                         removeTapCallback();
17136                     }
17137                     mIgnoreNextUpEvent = false;
17138                     break;
17139 
17140                 case MotionEvent.ACTION_DOWN:
17141                     if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
17142                         mPrivateFlags3 |= PFLAG3_FINGER_DOWN;
17143                     }
17144                     mHasPerformedLongPress = false;
17145 
17146                     if (!clickable) {
17147                         checkForLongClick(
17148                                 ViewConfiguration.getLongPressTimeout(),
17149                                 x,
17150                                 y,
17151                                 TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
17152                         break;
17153                     }
17154 
17155                     if (performButtonActionOnTouchDown(event)) {
17156                         break;
17157                     }
17158 
17159                     // Walk up the hierarchy to determine if we're inside a scrolling container.
17160                     boolean isInScrollingContainer = isInScrollingContainer();
17161 
17162                     // For views inside a scrolling container, delay the pressed feedback for
17163                     // a short period in case this is a scroll.
17164                     if (isInScrollingContainer) {
17165                         mPrivateFlags |= PFLAG_PREPRESSED;
17166                         if (mPendingCheckForTap == null) {
17167                             mPendingCheckForTap = new CheckForTap();
17168                         }
17169                         mPendingCheckForTap.x = event.getX();
17170                         mPendingCheckForTap.y = event.getY();
17171                         postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
17172                     } else {
17173                         // Not inside a scrolling container, so show the feedback right away
17174                         setPressed(true, x, y);
17175                         checkForLongClick(
17176                                 ViewConfiguration.getLongPressTimeout(),
17177                                 x,
17178                                 y,
17179                                 TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
17180                     }
17181                     break;
17182 
17183                 case MotionEvent.ACTION_CANCEL:
17184                     if (clickable) {
17185                         setPressed(false);
17186                     }
17187                     removeTapCallback();
17188                     removeLongPressCallback();
17189                     mInContextButtonPress = false;
17190                     mHasPerformedLongPress = false;
17191                     mIgnoreNextUpEvent = false;
17192                     mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
17193                     break;
17194 
17195                 case MotionEvent.ACTION_MOVE:
17196                     if (clickable) {
17197                         drawableHotspotChanged(x, y);
17198                     }
17199 
17200                     final int motionClassification = event.getClassification();
17201                     final boolean ambiguousGesture =
17202                             motionClassification == MotionEvent.CLASSIFICATION_AMBIGUOUS_GESTURE;
17203                     int touchSlop = mTouchSlop;
17204                     if (ambiguousGesture && hasPendingLongPressCallback()) {
17205                         if (!pointInView(x, y, touchSlop)) {
17206                             // The default action here is to cancel long press. But instead, we
17207                             // just extend the timeout here, in case the classification
17208                             // stays ambiguous.
17209                             removeLongPressCallback();
17210                             long delay = (long) (ViewConfiguration.getLongPressTimeout()
17211                                     * mAmbiguousGestureMultiplier);
17212                             // Subtract the time already spent
17213                             delay -= event.getEventTime() - event.getDownTime();
17214                             checkForLongClick(
17215                                     delay,
17216                                     x,
17217                                     y,
17218                                     TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
17219                         }
17220                         touchSlop *= mAmbiguousGestureMultiplier;
17221                     }
17222 
17223                     // Be lenient about moving outside of buttons
17224                     if (!pointInView(x, y, touchSlop)) {
17225                         // Outside button
17226                         // Remove any future long press/tap checks
17227                         removeTapCallback();
17228                         removeLongPressCallback();
17229                         if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
17230                             setPressed(false);
17231                         }
17232                         mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
17233                     }
17234 
17235                     final boolean deepPress =
17236                             motionClassification == MotionEvent.CLASSIFICATION_DEEP_PRESS;
17237                     if (deepPress && hasPendingLongPressCallback()) {
17238                         // process the long click action immediately
17239                         removeLongPressCallback();
17240                         checkForLongClick(
17241                                 0 /* send immediately */,
17242                                 x,
17243                                 y,
17244                                 TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS);
17245                     }
17246 
17247                     break;
17248             }
17249 
17250             return true;
17251         }
17252 
17253         return false;
17254     }
17255 
17256     /**
17257      * @hide
17258      */
17259     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
isInScrollingContainer()17260     public boolean isInScrollingContainer() {
17261         ViewParent p = getParent();
17262         while (p != null && p instanceof ViewGroup) {
17263             if (((ViewGroup) p).shouldDelayChildPressedState()) {
17264                 return true;
17265             }
17266             p = p.getParent();
17267         }
17268         return false;
17269     }
17270 
17271     /**
17272      * Remove the longpress detection timer.
17273      */
removeLongPressCallback()17274     private void removeLongPressCallback() {
17275         if (mPendingCheckForLongPress != null) {
17276             removeCallbacks(mPendingCheckForLongPress);
17277         }
17278     }
17279 
17280     /**
17281      * Return true if the long press callback is scheduled to run sometime in the future.
17282      * Return false if there is no scheduled long press callback at the moment.
17283      */
hasPendingLongPressCallback()17284     private boolean hasPendingLongPressCallback() {
17285         if (mPendingCheckForLongPress == null) {
17286             return false;
17287         }
17288         final AttachInfo attachInfo = mAttachInfo;
17289         if (attachInfo == null) {
17290             return false;
17291         }
17292         return attachInfo.mHandler.hasCallbacks(mPendingCheckForLongPress);
17293     }
17294 
17295    /**
17296      * Remove the pending click action
17297      */
17298     @UnsupportedAppUsage
removePerformClickCallback()17299     private void removePerformClickCallback() {
17300         if (mPerformClick != null) {
17301             removeCallbacks(mPerformClick);
17302         }
17303     }
17304 
17305     /**
17306      * Remove the prepress detection timer.
17307      */
removeUnsetPressCallback()17308     private void removeUnsetPressCallback() {
17309         if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
17310             setPressed(false);
17311             removeCallbacks(mUnsetPressedState);
17312         }
17313     }
17314 
17315     /**
17316      * Remove the tap detection timer.
17317      */
removeTapCallback()17318     private void removeTapCallback() {
17319         if (mPendingCheckForTap != null) {
17320             mPrivateFlags &= ~PFLAG_PREPRESSED;
17321             removeCallbacks(mPendingCheckForTap);
17322         }
17323     }
17324 
17325     /**
17326      * Cancels a pending long press.  Your subclass can use this if you
17327      * want the context menu to come up if the user presses and holds
17328      * at the same place, but you don't want it to come up if they press
17329      * and then move around enough to cause scrolling.
17330      */
cancelLongPress()17331     public void cancelLongPress() {
17332         removeLongPressCallback();
17333 
17334         /*
17335          * The prepressed state handled by the tap callback is a display
17336          * construct, but the tap callback will post a long press callback
17337          * less its own timeout. Remove it here.
17338          */
17339         removeTapCallback();
17340     }
17341 
17342     /**
17343      * Sets the TouchDelegate for this View.
17344      */
setTouchDelegate(TouchDelegate delegate)17345     public void setTouchDelegate(TouchDelegate delegate) {
17346         mTouchDelegate = delegate;
17347     }
17348 
17349     /**
17350      * Gets the TouchDelegate for this View.
17351      */
getTouchDelegate()17352     public TouchDelegate getTouchDelegate() {
17353         return mTouchDelegate;
17354     }
17355 
17356     /**
17357      * Request unbuffered dispatch of the given stream of MotionEvents to this View.
17358      *
17359      * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
17360      * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
17361      * available. This method should only be called for touch events.
17362      *
17363      * <p class="note">This API is not intended for most applications. Buffered dispatch
17364      * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
17365      * streams will not improve your input latency. Side effects include: increased latency,
17366      * jittery scrolls and inability to take advantage of system resampling. Talk to your input
17367      * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
17368      * you.</p>
17369      *
17370      * To receive unbuffered events for arbitrary input device source classes, use
17371      * {@link #requestUnbufferedDispatch(int)},
17372      *
17373      * @see View#requestUnbufferedDispatch(int)
17374      */
requestUnbufferedDispatch(MotionEvent event)17375     public final void requestUnbufferedDispatch(MotionEvent event) {
17376         final int action = event.getAction();
17377         if (mAttachInfo == null
17378                 || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
17379                 || !event.isTouchEvent()) {
17380             return;
17381         }
17382         mAttachInfo.mUnbufferedDispatchRequested = true;
17383     }
17384 
17385     /**
17386      * Request unbuffered dispatch of the given event source class to this view.
17387      * This is similar to {@link View#requestUnbufferedDispatch(MotionEvent)}, but does not
17388      * automatically terminate, and allows the specification of arbitrary input source classes.
17389      *
17390      * <p>Prior to {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, calling this method
17391      * will not result in any behavioral changes when this View is not attached to a window.
17392      *
17393      * @param source The combined input source class to request unbuffered dispatch for. All
17394      *               events coming from these source classes will not be buffered. Set to
17395      *               {@link InputDevice#SOURCE_CLASS_NONE} in order to return to default behaviour.
17396      *
17397      * @see View#requestUnbufferedDispatch(MotionEvent)
17398      */
requestUnbufferedDispatch(@nputSourceClass int source)17399     public final void requestUnbufferedDispatch(@InputSourceClass int source) {
17400         if (mUnbufferedInputSource == source) {
17401             return;
17402         }
17403         mUnbufferedInputSource = source;
17404         if (mParent != null) {
17405             mParent.onDescendantUnbufferedRequested();
17406         }
17407     }
17408 
hasSize()17409     private boolean hasSize() {
17410         return (mBottom > mTop) && (mRight > mLeft);
17411     }
17412 
canTakeFocus()17413     private boolean canTakeFocus() {
17414         return ((mViewFlags & VISIBILITY_MASK) == VISIBLE)
17415                 && ((mViewFlags & FOCUSABLE) == FOCUSABLE)
17416                 && ((mViewFlags & ENABLED_MASK) == ENABLED)
17417                 && (sCanFocusZeroSized || !isLayoutValid() || hasSize());
17418     }
17419 
17420     /**
17421      * Set flags controlling behavior of this view.
17422      *
17423      * @param flags Constant indicating the value which should be set
17424      * @param mask Constant indicating the bit range that should be changed
17425      */
17426     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
setFlags(int flags, int mask)17427     void setFlags(int flags, int mask) {
17428         final boolean accessibilityEnabled =
17429                 AccessibilityManager.getInstance(mContext).isEnabled();
17430         final boolean oldIncludeForAccessibility =
17431                 accessibilityEnabled && includeForAccessibility(false);
17432 
17433         int old = mViewFlags;
17434         mViewFlags = (mViewFlags & ~mask) | (flags & mask);
17435 
17436         int changed = mViewFlags ^ old;
17437         if (changed == 0) {
17438             return;
17439         }
17440         int privateFlags = mPrivateFlags;
17441         boolean shouldNotifyFocusableAvailable = false;
17442 
17443         // If focusable is auto, update the FOCUSABLE bit.
17444         int focusableChangedByAuto = 0;
17445         if (((mViewFlags & FOCUSABLE_AUTO) != 0)
17446                 && (changed & (FOCUSABLE_MASK | CLICKABLE)) != 0) {
17447             // Heuristic only takes into account whether view is clickable.
17448             final int newFocus;
17449             if ((mViewFlags & CLICKABLE) != 0) {
17450                 newFocus = FOCUSABLE;
17451             } else {
17452                 newFocus = NOT_FOCUSABLE;
17453             }
17454             mViewFlags = (mViewFlags & ~FOCUSABLE) | newFocus;
17455             focusableChangedByAuto = (old & FOCUSABLE) ^ (newFocus & FOCUSABLE);
17456             changed = (changed & ~FOCUSABLE) | focusableChangedByAuto;
17457         }
17458 
17459         /* Check if the FOCUSABLE bit has changed */
17460         if (((changed & FOCUSABLE) != 0) && ((privateFlags & PFLAG_HAS_BOUNDS) != 0)) {
17461             if (((old & FOCUSABLE) == FOCUSABLE)
17462                     && ((privateFlags & PFLAG_FOCUSED) != 0)) {
17463                 /* Give up focus if we are no longer focusable */
17464                 clearFocus();
17465                 if (mParent instanceof ViewGroup) {
17466                     ((ViewGroup) mParent).clearFocusedInCluster();
17467                 }
17468             } else if (((old & FOCUSABLE) == NOT_FOCUSABLE)
17469                     && ((privateFlags & PFLAG_FOCUSED) == 0)) {
17470                 /*
17471                  * Tell the view system that we are now available to take focus
17472                  * if no one else already has it.
17473                  */
17474                 if (mParent != null) {
17475                     ViewRootImpl viewRootImpl = getViewRootImpl();
17476                     if (!sAutoFocusableOffUIThreadWontNotifyParents
17477                             || focusableChangedByAuto == 0
17478                             || viewRootImpl == null
17479                             || viewRootImpl.mThread == Thread.currentThread()) {
17480                         shouldNotifyFocusableAvailable = canTakeFocus();
17481                     }
17482                 }
17483             }
17484         }
17485 
17486         final int newVisibility = flags & VISIBILITY_MASK;
17487         if (newVisibility == VISIBLE) {
17488             if ((changed & VISIBILITY_MASK) != 0) {
17489                 /*
17490                  * If this view is becoming visible, invalidate it in case it changed while
17491                  * it was not visible. Marking it drawn ensures that the invalidation will
17492                  * go through.
17493                  */
17494                 mPrivateFlags |= PFLAG_DRAWN;
17495                 invalidate(true);
17496 
17497                 needGlobalAttributesUpdate(true);
17498 
17499                 // a view becoming visible is worth notifying the parent about in case nothing has
17500                 // focus. Even if this specific view isn't focusable, it may contain something that
17501                 // is, so let the root view try to give this focus if nothing else does.
17502                 shouldNotifyFocusableAvailable = hasSize();
17503             }
17504         }
17505 
17506         if ((changed & ENABLED_MASK) != 0) {
17507             if ((mViewFlags & ENABLED_MASK) == ENABLED) {
17508                 // a view becoming enabled should notify the parent as long as the view is also
17509                 // visible and the parent wasn't already notified by becoming visible during this
17510                 // setFlags invocation.
17511                 shouldNotifyFocusableAvailable = canTakeFocus();
17512             } else {
17513                 if (isFocused()) clearFocus();
17514             }
17515         }
17516 
17517         if (shouldNotifyFocusableAvailable && mParent != null) {
17518             mParent.focusableViewAvailable(this);
17519         }
17520 
17521         /* Check if the GONE bit has changed */
17522         if ((changed & GONE) != 0) {
17523             needGlobalAttributesUpdate(false);
17524             requestLayout();
17525 
17526             if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
17527                 if (hasFocus()) {
17528                     clearFocus();
17529                     if (mParent instanceof ViewGroup) {
17530                         ((ViewGroup) mParent).clearFocusedInCluster();
17531                     }
17532                 }
17533                 clearAccessibilityFocus();
17534                 destroyDrawingCache();
17535                 if (mParent instanceof View) {
17536                     // GONE views noop invalidation, so invalidate the parent
17537                     ((View) mParent).invalidate(true);
17538                 }
17539                 // Mark the view drawn to ensure that it gets invalidated properly the next
17540                 // time it is visible and gets invalidated
17541                 mPrivateFlags |= PFLAG_DRAWN;
17542             }
17543             if (mAttachInfo != null) {
17544                 mAttachInfo.mViewVisibilityChanged = true;
17545             }
17546         }
17547 
17548         /* Check if the VISIBLE bit has changed */
17549         if ((changed & INVISIBLE) != 0) {
17550             needGlobalAttributesUpdate(false);
17551             /*
17552              * If this view is becoming invisible, set the DRAWN flag so that
17553              * the next invalidate() will not be skipped.
17554              */
17555             mPrivateFlags |= PFLAG_DRAWN;
17556 
17557             if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
17558                 // root view becoming invisible shouldn't clear focus and accessibility focus
17559                 if (getRootView() != this) {
17560                     if (hasFocus()) {
17561                         clearFocus();
17562                         if (mParent instanceof ViewGroup) {
17563                             ((ViewGroup) mParent).clearFocusedInCluster();
17564                         }
17565                     }
17566                     clearAccessibilityFocus();
17567                 }
17568             }
17569             if (mAttachInfo != null) {
17570                 mAttachInfo.mViewVisibilityChanged = true;
17571             }
17572         }
17573 
17574         if ((changed & VISIBILITY_MASK) != 0) {
17575             // If the view is invisible, cleanup its display list to free up resources
17576             if (newVisibility != VISIBLE && mAttachInfo != null) {
17577                 cleanupDraw();
17578             }
17579 
17580             if (mParent instanceof ViewGroup) {
17581                 ViewGroup parent = (ViewGroup) mParent;
17582                 parent.onChildVisibilityChanged(this, (changed & VISIBILITY_MASK),
17583                         newVisibility);
17584                 parent.invalidate(true);
17585             } else if (mParent != null) {
17586                 mParent.invalidateChild(this, null);
17587             }
17588 
17589             if (mAttachInfo != null) {
17590                 dispatchVisibilityChanged(this, newVisibility);
17591 
17592                 // Aggregated visibility changes are dispatched to attached views
17593                 // in visible windows where the parent is currently shown/drawn
17594                 // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
17595                 // discounting clipping or overlapping. This makes it a good place
17596                 // to change animation states.
17597                 if (mParent != null && getWindowVisibility() == VISIBLE &&
17598                         ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
17599                     dispatchVisibilityAggregated(newVisibility == VISIBLE);
17600                 }
17601                 // If this view is invisible from visible, then sending the A11y event by its
17602                 // parent which is shown and has the accessibility important.
17603                 if ((old & VISIBILITY_MASK) == VISIBLE) {
17604                     notifySubtreeAccessibilityStateChangedByParentIfNeeded();
17605                 } else {
17606                     notifySubtreeAccessibilityStateChangedIfNeeded();
17607                 }
17608             }
17609         }
17610 
17611         if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
17612             destroyDrawingCache();
17613         }
17614 
17615         if ((changed & DRAWING_CACHE_ENABLED) != 0) {
17616             destroyDrawingCache();
17617             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
17618             invalidateParentCaches();
17619         }
17620 
17621         if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
17622             destroyDrawingCache();
17623             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
17624         }
17625 
17626         if ((changed & DRAW_MASK) != 0) {
17627             if ((mViewFlags & WILL_NOT_DRAW) != 0) {
17628                 if (mBackground != null
17629                         || mDefaultFocusHighlight != null
17630                         || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
17631                     mPrivateFlags &= ~PFLAG_SKIP_DRAW;
17632                 } else {
17633                     mPrivateFlags |= PFLAG_SKIP_DRAW;
17634                 }
17635             } else {
17636                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
17637             }
17638             requestLayout();
17639             invalidate(true);
17640         }
17641 
17642         if ((changed & KEEP_SCREEN_ON) != 0) {
17643             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
17644                 mParent.recomputeViewAttributes(this);
17645             }
17646         }
17647 
17648         if (accessibilityEnabled) {
17649             // If we're an accessibility pane and the visibility changed, we already have sent
17650             // a state change, so we really don't need to report other changes.
17651             if (isAccessibilityPane()) {
17652                 changed &= ~VISIBILITY_MASK;
17653             }
17654             if ((changed & FOCUSABLE) != 0 || (changed & VISIBILITY_MASK) != 0
17655                     || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
17656                     || (changed & CONTEXT_CLICKABLE) != 0) {
17657                 if (oldIncludeForAccessibility != includeForAccessibility(false)) {
17658                     notifySubtreeAccessibilityStateChangedIfNeeded();
17659                 } else {
17660                     notifyViewAccessibilityStateChangedIfNeeded(
17661                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
17662                 }
17663             } else if ((changed & ENABLED_MASK) != 0) {
17664                 notifyViewAccessibilityStateChangedIfNeeded(
17665                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
17666             }
17667         }
17668     }
17669 
17670     /**
17671      * Change the view's z order in the tree, so it's on top of other sibling
17672      * views. This ordering change may affect layout, if the parent container
17673      * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
17674      * to {@link android.os.Build.VERSION_CODES#KITKAT} this
17675      * method should be followed by calls to {@link #requestLayout()} and
17676      * {@link View#invalidate()} on the view's parent to force the parent to redraw
17677      * with the new child ordering.
17678      *
17679      * @see ViewGroup#bringChildToFront(View)
17680      */
bringToFront()17681     public void bringToFront() {
17682         if (mParent != null) {
17683             mParent.bringChildToFront(this);
17684         }
17685     }
17686 
17687     /**
17688      * This is called in response to an internal scroll in this view (i.e., the
17689      * view scrolled its own contents). This is typically as a result of
17690      * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
17691      * called.
17692      *
17693      * @param l Current horizontal scroll origin.
17694      * @param t Current vertical scroll origin.
17695      * @param oldl Previous horizontal scroll origin.
17696      * @param oldt Previous vertical scroll origin.
17697      */
onScrollChanged(int l, int t, int oldl, int oldt)17698     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
17699         notifySubtreeAccessibilityStateChangedIfNeeded();
17700         postSendViewScrolledAccessibilityEventCallback(l - oldl, t - oldt);
17701 
17702         mBackgroundSizeChanged = true;
17703         mDefaultFocusHighlightSizeChanged = true;
17704         if (mForegroundInfo != null) {
17705             mForegroundInfo.mBoundsChanged = true;
17706         }
17707 
17708         final AttachInfo ai = mAttachInfo;
17709         if (ai != null) {
17710             ai.mViewScrollChanged = true;
17711         }
17712 
17713         if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
17714             mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
17715         }
17716     }
17717 
17718     /**
17719      * Interface definition for a callback to be invoked when the scroll
17720      * X or Y positions of a view change.
17721      * <p>
17722      * <b>Note:</b> Some views handle scrolling independently from View and may
17723      * have their own separate listeners for scroll-type events. For example,
17724      * {@link android.widget.ListView ListView} allows clients to register an
17725      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
17726      * to listen for changes in list scroll position.
17727      *
17728      * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
17729      */
17730     public interface OnScrollChangeListener {
17731         /**
17732          * Called when the scroll position of a view changes.
17733          *
17734          * @param v The view whose scroll position has changed.
17735          * @param scrollX Current horizontal scroll origin.
17736          * @param scrollY Current vertical scroll origin.
17737          * @param oldScrollX Previous horizontal scroll origin.
17738          * @param oldScrollY Previous vertical scroll origin.
17739          */
onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY)17740         void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
17741     }
17742 
17743     /**
17744      * Interface definition for a callback to be invoked when the layout bounds of a view
17745      * changes due to layout processing.
17746      */
17747     public interface OnLayoutChangeListener {
17748         /**
17749          * Called when the layout bounds of a view changes due to layout processing.
17750          *
17751          * @param v The view whose bounds have changed.
17752          * @param left The new value of the view's left property.
17753          * @param top The new value of the view's top property.
17754          * @param right The new value of the view's right property.
17755          * @param bottom The new value of the view's bottom property.
17756          * @param oldLeft The previous value of the view's left property.
17757          * @param oldTop The previous value of the view's top property.
17758          * @param oldRight The previous value of the view's right property.
17759          * @param oldBottom The previous value of the view's bottom property.
17760          */
onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom)17761         void onLayoutChange(View v, int left, int top, int right, int bottom,
17762             int oldLeft, int oldTop, int oldRight, int oldBottom);
17763     }
17764 
17765     /**
17766      * This is called during layout when the size of this view has changed. If
17767      * you were just added to the view hierarchy, you're called with the old
17768      * values of 0.
17769      *
17770      * @param w Current width of this view.
17771      * @param h Current height of this view.
17772      * @param oldw Old width of this view.
17773      * @param oldh Old height of this view.
17774      */
onSizeChanged(int w, int h, int oldw, int oldh)17775     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
17776     }
17777 
17778     /**
17779      * Called by draw to draw the child views. This may be overridden
17780      * by derived classes to gain control just before its children are drawn
17781      * (but after its own view has been drawn).
17782      * @param canvas the canvas on which to draw the view
17783      */
dispatchDraw(@onNull Canvas canvas)17784     protected void dispatchDraw(@NonNull Canvas canvas) {
17785 
17786     }
17787 
17788     /**
17789      * Gets the parent of this view. Note that the parent is a
17790      * ViewParent and not necessarily a View.
17791      *
17792      * @return Parent of this view.
17793      */
getParent()17794     public final ViewParent getParent() {
17795         return mParent;
17796     }
17797 
17798     /**
17799      * Set the horizontal scrolled position of your view. This will cause a call to
17800      * {@link #onScrollChanged(int, int, int, int)} and the view will be
17801      * invalidated.
17802      * @param value the x position to scroll to
17803      */
setScrollX(int value)17804     public void setScrollX(int value) {
17805         scrollTo(value, mScrollY);
17806     }
17807 
17808     /**
17809      * Set the vertical scrolled position of your view. This will cause a call to
17810      * {@link #onScrollChanged(int, int, int, int)} and the view will be
17811      * invalidated.
17812      * @param value the y position to scroll to
17813      */
setScrollY(int value)17814     public void setScrollY(int value) {
17815         scrollTo(mScrollX, value);
17816     }
17817 
17818     /**
17819      * Return the scrolled left position of this view. This is the left edge of
17820      * the displayed part of your view. You do not need to draw any pixels
17821      * farther left, since those are outside of the frame of your view on
17822      * screen.
17823      *
17824      * @return The left edge of the displayed part of your view, in pixels.
17825      */
17826     @InspectableProperty
getScrollX()17827     public final int getScrollX() {
17828         return mScrollX;
17829     }
17830 
17831     /**
17832      * Return the scrolled top position of this view. This is the top edge of
17833      * the displayed part of your view. You do not need to draw any pixels above
17834      * it, since those are outside of the frame of your view on screen.
17835      *
17836      * @return The top edge of the displayed part of your view, in pixels.
17837      */
17838     @InspectableProperty
getScrollY()17839     public final int getScrollY() {
17840         return mScrollY;
17841     }
17842 
17843     /**
17844      * Return the width of your view.
17845      *
17846      * @return The width of your view, in pixels.
17847      */
17848     @ViewDebug.ExportedProperty(category = "layout")
getWidth()17849     public final int getWidth() {
17850         return mRight - mLeft;
17851     }
17852 
17853     /**
17854      * Return the height of your view.
17855      *
17856      * @return The height of your view, in pixels.
17857      */
17858     @ViewDebug.ExportedProperty(category = "layout")
getHeight()17859     public final int getHeight() {
17860         return mBottom - mTop;
17861     }
17862 
17863     /**
17864      * Return the visible drawing bounds of your view. Fills in the output
17865      * rectangle with the values from getScrollX(), getScrollY(),
17866      * getWidth(), and getHeight(). These bounds do not account for any
17867      * transformation properties currently set on the view, such as
17868      * {@link #setScaleX(float)} or {@link #setRotation(float)}.
17869      *
17870      * @param outRect The (scrolled) drawing bounds of the view.
17871      */
getDrawingRect(Rect outRect)17872     public void getDrawingRect(Rect outRect) {
17873         outRect.left = mScrollX;
17874         outRect.top = mScrollY;
17875         outRect.right = mScrollX + (mRight - mLeft);
17876         outRect.bottom = mScrollY + (mBottom - mTop);
17877     }
17878 
17879     /**
17880      * Like {@link #getMeasuredWidthAndState()}, but only returns the
17881      * raw width component (that is the result is masked by
17882      * {@link #MEASURED_SIZE_MASK}).
17883      *
17884      * @return The raw measured width of this view.
17885      */
getMeasuredWidth()17886     public final int getMeasuredWidth() {
17887         return mMeasuredWidth & MEASURED_SIZE_MASK;
17888     }
17889 
17890     /**
17891      * Return the full width measurement information for this view as computed
17892      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
17893      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
17894      * This should be used during measurement and layout calculations only. Use
17895      * {@link #getWidth()} to see how wide a view is after layout.
17896      *
17897      * @return The measured width of this view as a bit mask.
17898      */
17899     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
17900             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
17901                     name = "MEASURED_STATE_TOO_SMALL"),
17902     })
getMeasuredWidthAndState()17903     public final int getMeasuredWidthAndState() {
17904         return mMeasuredWidth;
17905     }
17906 
17907     /**
17908      * Like {@link #getMeasuredHeightAndState()}, but only returns the
17909      * raw height component (that is the result is masked by
17910      * {@link #MEASURED_SIZE_MASK}).
17911      *
17912      * @return The raw measured height of this view.
17913      */
getMeasuredHeight()17914     public final int getMeasuredHeight() {
17915         return mMeasuredHeight & MEASURED_SIZE_MASK;
17916     }
17917 
17918     /**
17919      * Return the full height measurement information for this view as computed
17920      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
17921      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
17922      * This should be used during measurement and layout calculations only. Use
17923      * {@link #getHeight()} to see how high a view is after layout.
17924      *
17925      * @return The measured height of this view as a bit mask.
17926      */
17927     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
17928             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
17929                     name = "MEASURED_STATE_TOO_SMALL"),
17930     })
getMeasuredHeightAndState()17931     public final int getMeasuredHeightAndState() {
17932         return mMeasuredHeight;
17933     }
17934 
17935     /**
17936      * Return only the state bits of {@link #getMeasuredWidthAndState()}
17937      * and {@link #getMeasuredHeightAndState()}, combined into one integer.
17938      * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
17939      * and the height component is at the shifted bits
17940      * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
17941      */
getMeasuredState()17942     public final int getMeasuredState() {
17943         return (mMeasuredWidth&MEASURED_STATE_MASK)
17944                 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
17945                         & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
17946     }
17947 
17948     /**
17949      * The transform matrix of this view, which is calculated based on the current
17950      * rotation, scale, and pivot properties.
17951      *
17952      * @see #getRotation()
17953      * @see #getScaleX()
17954      * @see #getScaleY()
17955      * @see #getPivotX()
17956      * @see #getPivotY()
17957      * @return The current transform matrix for the view
17958      */
getMatrix()17959     public Matrix getMatrix() {
17960         ensureTransformationInfo();
17961         final Matrix matrix = mTransformationInfo.mMatrix;
17962         mRenderNode.getMatrix(matrix);
17963         return matrix;
17964     }
17965 
17966     /**
17967      * Returns true if the transform matrix is the identity matrix.
17968      * Recomputes the matrix if necessary.
17969      *
17970      * @return True if the transform matrix is the identity matrix, false otherwise.
17971      * @hide
17972      */
17973     @UnsupportedAppUsage
hasIdentityMatrix()17974     public final boolean hasIdentityMatrix() {
17975         return mRenderNode.hasIdentityMatrix();
17976     }
17977 
17978     @UnsupportedAppUsage
ensureTransformationInfo()17979     void ensureTransformationInfo() {
17980         if (mTransformationInfo == null) {
17981             mTransformationInfo = new TransformationInfo();
17982         }
17983     }
17984 
17985     /**
17986      * Utility method to retrieve the inverse of the current mMatrix property.
17987      * We cache the matrix to avoid recalculating it when transform properties
17988      * have not changed.
17989      *
17990      * @return The inverse of the current matrix of this view.
17991      * @hide
17992      */
17993     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getInverseMatrix()17994     public final Matrix getInverseMatrix() {
17995         ensureTransformationInfo();
17996         if (mTransformationInfo.mInverseMatrix == null) {
17997             mTransformationInfo.mInverseMatrix = new Matrix();
17998         }
17999         final Matrix matrix = mTransformationInfo.mInverseMatrix;
18000         mRenderNode.getInverseMatrix(matrix);
18001         return matrix;
18002     }
18003 
18004     /**
18005      * Gets the distance along the Z axis from the camera to this view.
18006      *
18007      * @see #setCameraDistance(float)
18008      *
18009      * @return The distance along the Z axis.
18010      */
getCameraDistance()18011     public float getCameraDistance() {
18012         final float dpi = mResources.getDisplayMetrics().densityDpi;
18013         return mRenderNode.getCameraDistance() * dpi;
18014     }
18015 
18016     /**
18017      * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
18018      * views are drawn) from the camera to this view. The camera's distance
18019      * affects 3D transformations, for instance rotations around the X and Y
18020      * axis. If the rotationX or rotationY properties are changed and this view is
18021      * large (more than half the size of the screen), it is recommended to always
18022      * use a camera distance that's greater than the height (X axis rotation) or
18023      * the width (Y axis rotation) of this view.</p>
18024      *
18025      * <p>The distance of the camera from the view plane can have an affect on the
18026      * perspective distortion of the view when it is rotated around the x or y axis.
18027      * For example, a large distance will result in a large viewing angle, and there
18028      * will not be much perspective distortion of the view as it rotates. A short
18029      * distance may cause much more perspective distortion upon rotation, and can
18030      * also result in some drawing artifacts if the rotated view ends up partially
18031      * behind the camera (which is why the recommendation is to use a distance at
18032      * least as far as the size of the view, if the view is to be rotated.)</p>
18033      *
18034      * <p>The distance is expressed in "depth pixels." The default distance depends
18035      * on the screen density. For instance, on a medium density display, the
18036      * default distance is 1280. On a high density display, the default distance
18037      * is 1920.</p>
18038      *
18039      * <p>If you want to specify a distance that leads to visually consistent
18040      * results across various densities, use the following formula:</p>
18041      * <pre>
18042      * float scale = context.getResources().getDisplayMetrics().density;
18043      * view.setCameraDistance(distance * scale);
18044      * </pre>
18045      *
18046      * <p>The density scale factor of a high density display is 1.5,
18047      * and 1920 = 1280 * 1.5.</p>
18048      *
18049      * @param distance The distance in "depth pixels", if negative the opposite
18050      *        value is used
18051      *
18052      * @see #setRotationX(float)
18053      * @see #setRotationY(float)
18054      */
setCameraDistance(float distance)18055     public void setCameraDistance(float distance) {
18056         final float dpi = mResources.getDisplayMetrics().densityDpi;
18057 
18058         invalidateViewProperty(true, false);
18059         mRenderNode.setCameraDistance(Math.abs(distance) / dpi);
18060         invalidateViewProperty(false, false);
18061 
18062         invalidateParentIfNeededAndWasQuickRejected();
18063     }
18064 
18065     /**
18066      * The degrees that the view is rotated around the pivot point.
18067      *
18068      * @see #setRotation(float)
18069      * @see #getPivotX()
18070      * @see #getPivotY()
18071      *
18072      * @return The degrees of rotation.
18073      */
18074     @ViewDebug.ExportedProperty(category = "drawing")
18075     @InspectableProperty
getRotation()18076     public float getRotation() {
18077         return mRenderNode.getRotationZ();
18078     }
18079 
18080     /**
18081      * Sets the degrees that the view is rotated around the pivot point. Increasing values
18082      * result in clockwise rotation.
18083      *
18084      * @param rotation The degrees of rotation.
18085      *
18086      * @see #getRotation()
18087      * @see #getPivotX()
18088      * @see #getPivotY()
18089      * @see #setRotationX(float)
18090      * @see #setRotationY(float)
18091      *
18092      * @attr ref android.R.styleable#View_rotation
18093      */
18094     @RemotableViewMethod
setRotation(float rotation)18095     public void setRotation(float rotation) {
18096         if (rotation != getRotation()) {
18097             // Double-invalidation is necessary to capture view's old and new areas
18098             invalidateViewProperty(true, false);
18099             mRenderNode.setRotationZ(rotation);
18100             invalidateViewProperty(false, true);
18101 
18102             invalidateParentIfNeededAndWasQuickRejected();
18103             notifySubtreeAccessibilityStateChangedIfNeeded();
18104         }
18105     }
18106 
18107     /**
18108      * The degrees that the view is rotated around the vertical axis through the pivot point.
18109      *
18110      * @see #getPivotX()
18111      * @see #getPivotY()
18112      * @see #setRotationY(float)
18113      *
18114      * @return The degrees of Y rotation.
18115      */
18116     @ViewDebug.ExportedProperty(category = "drawing")
18117     @InspectableProperty
getRotationY()18118     public float getRotationY() {
18119         return mRenderNode.getRotationY();
18120     }
18121 
18122     /**
18123      * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
18124      * Increasing values result in counter-clockwise rotation from the viewpoint of looking
18125      * down the y axis.
18126      *
18127      * When rotating large views, it is recommended to adjust the camera distance
18128      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
18129      *
18130      * @param rotationY The degrees of Y rotation.
18131      *
18132      * @see #getRotationY()
18133      * @see #getPivotX()
18134      * @see #getPivotY()
18135      * @see #setRotation(float)
18136      * @see #setRotationX(float)
18137      * @see #setCameraDistance(float)
18138      *
18139      * @attr ref android.R.styleable#View_rotationY
18140      */
18141     @RemotableViewMethod
setRotationY(float rotationY)18142     public void setRotationY(float rotationY) {
18143         if (rotationY != getRotationY()) {
18144             invalidateViewProperty(true, false);
18145             mRenderNode.setRotationY(rotationY);
18146             invalidateViewProperty(false, true);
18147 
18148             invalidateParentIfNeededAndWasQuickRejected();
18149             notifySubtreeAccessibilityStateChangedIfNeeded();
18150         }
18151     }
18152 
18153     /**
18154      * The degrees that the view is rotated around the horizontal axis through the pivot point.
18155      *
18156      * @see #getPivotX()
18157      * @see #getPivotY()
18158      * @see #setRotationX(float)
18159      *
18160      * @return The degrees of X rotation.
18161      */
18162     @ViewDebug.ExportedProperty(category = "drawing")
18163     @InspectableProperty
getRotationX()18164     public float getRotationX() {
18165         return mRenderNode.getRotationX();
18166     }
18167 
18168     /**
18169      * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
18170      * Increasing values result in clockwise rotation from the viewpoint of looking down the
18171      * x axis.
18172      *
18173      * When rotating large views, it is recommended to adjust the camera distance
18174      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
18175      *
18176      * @param rotationX The degrees of X rotation.
18177      *
18178      * @see #getRotationX()
18179      * @see #getPivotX()
18180      * @see #getPivotY()
18181      * @see #setRotation(float)
18182      * @see #setRotationY(float)
18183      * @see #setCameraDistance(float)
18184      *
18185      * @attr ref android.R.styleable#View_rotationX
18186      */
18187     @RemotableViewMethod
setRotationX(float rotationX)18188     public void setRotationX(float rotationX) {
18189         if (rotationX != getRotationX()) {
18190             invalidateViewProperty(true, false);
18191             mRenderNode.setRotationX(rotationX);
18192             invalidateViewProperty(false, true);
18193 
18194             invalidateParentIfNeededAndWasQuickRejected();
18195             notifySubtreeAccessibilityStateChangedIfNeeded();
18196         }
18197     }
18198 
18199     /**
18200      * The amount that the view is scaled in x around the pivot point, as a proportion of
18201      * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
18202      *
18203      * <p>By default, this is 1.0f.
18204      *
18205      * @see #getPivotX()
18206      * @see #getPivotY()
18207      * @return The scaling factor.
18208      */
18209     @ViewDebug.ExportedProperty(category = "drawing")
18210     @InspectableProperty
getScaleX()18211     public float getScaleX() {
18212         return mRenderNode.getScaleX();
18213     }
18214 
18215     /**
18216      * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
18217      * the view's unscaled width. A value of 1 means that no scaling is applied.
18218      *
18219      * @param scaleX The scaling factor.
18220      * @see #getPivotX()
18221      * @see #getPivotY()
18222      *
18223      * @attr ref android.R.styleable#View_scaleX
18224      */
18225     @RemotableViewMethod
setScaleX(float scaleX)18226     public void setScaleX(float scaleX) {
18227         if (scaleX != getScaleX()) {
18228             scaleX = sanitizeFloatPropertyValue(scaleX, "scaleX");
18229             invalidateViewProperty(true, false);
18230             mRenderNode.setScaleX(scaleX);
18231             invalidateViewProperty(false, true);
18232 
18233             invalidateParentIfNeededAndWasQuickRejected();
18234             notifySubtreeAccessibilityStateChangedIfNeeded();
18235         }
18236     }
18237 
18238     /**
18239      * The amount that the view is scaled in y around the pivot point, as a proportion of
18240      * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
18241      *
18242      * <p>By default, this is 1.0f.
18243      *
18244      * @see #getPivotX()
18245      * @see #getPivotY()
18246      * @return The scaling factor.
18247      */
18248     @ViewDebug.ExportedProperty(category = "drawing")
18249     @InspectableProperty
getScaleY()18250     public float getScaleY() {
18251         return mRenderNode.getScaleY();
18252     }
18253 
18254     /**
18255      * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
18256      * the view's unscaled width. A value of 1 means that no scaling is applied.
18257      *
18258      * @param scaleY The scaling factor.
18259      * @see #getPivotX()
18260      * @see #getPivotY()
18261      *
18262      * @attr ref android.R.styleable#View_scaleY
18263      */
18264     @RemotableViewMethod
setScaleY(float scaleY)18265     public void setScaleY(float scaleY) {
18266         if (scaleY != getScaleY()) {
18267             scaleY = sanitizeFloatPropertyValue(scaleY, "scaleY");
18268             invalidateViewProperty(true, false);
18269             mRenderNode.setScaleY(scaleY);
18270             invalidateViewProperty(false, true);
18271 
18272             invalidateParentIfNeededAndWasQuickRejected();
18273             notifySubtreeAccessibilityStateChangedIfNeeded();
18274         }
18275     }
18276 
18277     /**
18278      * The x location of the point around which the view is {@link #setRotation(float) rotated}
18279      * and {@link #setScaleX(float) scaled}.
18280      *
18281      * @see #getRotation()
18282      * @see #getScaleX()
18283      * @see #getScaleY()
18284      * @see #getPivotY()
18285      * @return The x location of the pivot point.
18286      *
18287      * @attr ref android.R.styleable#View_transformPivotX
18288      */
18289     @ViewDebug.ExportedProperty(category = "drawing")
18290     @InspectableProperty(name = "transformPivotX")
getPivotX()18291     public float getPivotX() {
18292         return mRenderNode.getPivotX();
18293     }
18294 
18295     /**
18296      * Sets the x location of the point around which the view is
18297      * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
18298      * By default, the pivot point is centered on the object.
18299      * Setting this property disables this behavior and causes the view to use only the
18300      * explicitly set pivotX and pivotY values.
18301      *
18302      * @param pivotX The x location of the pivot point.
18303      * @see #getRotation()
18304      * @see #getScaleX()
18305      * @see #getScaleY()
18306      * @see #getPivotY()
18307      *
18308      * @attr ref android.R.styleable#View_transformPivotX
18309      */
18310     @RemotableViewMethod
setPivotX(float pivotX)18311     public void setPivotX(float pivotX) {
18312         if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
18313             invalidateViewProperty(true, false);
18314             mRenderNode.setPivotX(pivotX);
18315             invalidateViewProperty(false, true);
18316 
18317             invalidateParentIfNeededAndWasQuickRejected();
18318         }
18319     }
18320 
18321     /**
18322      * The y location of the point around which the view is {@link #setRotation(float) rotated}
18323      * and {@link #setScaleY(float) scaled}.
18324      *
18325      * @see #getRotation()
18326      * @see #getScaleX()
18327      * @see #getScaleY()
18328      * @see #getPivotY()
18329      * @return The y location of the pivot point.
18330      *
18331      * @attr ref android.R.styleable#View_transformPivotY
18332      */
18333     @ViewDebug.ExportedProperty(category = "drawing")
18334     @InspectableProperty(name = "transformPivotY")
getPivotY()18335     public float getPivotY() {
18336         return mRenderNode.getPivotY();
18337     }
18338 
18339     /**
18340      * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
18341      * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
18342      * Setting this property disables this behavior and causes the view to use only the
18343      * explicitly set pivotX and pivotY values.
18344      *
18345      * @param pivotY The y location of the pivot point.
18346      * @see #getRotation()
18347      * @see #getScaleX()
18348      * @see #getScaleY()
18349      * @see #getPivotY()
18350      *
18351      * @attr ref android.R.styleable#View_transformPivotY
18352      */
18353     @RemotableViewMethod
setPivotY(float pivotY)18354     public void setPivotY(float pivotY) {
18355         if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
18356             invalidateViewProperty(true, false);
18357             mRenderNode.setPivotY(pivotY);
18358             invalidateViewProperty(false, true);
18359 
18360             invalidateParentIfNeededAndWasQuickRejected();
18361         }
18362     }
18363 
18364     /**
18365      * Returns whether or not a pivot has been set by a call to {@link #setPivotX(float)} or
18366      * {@link #setPivotY(float)}. If no pivot has been set then the pivot will be the center
18367      * of the view.
18368      *
18369      * @return True if a pivot has been set, false if the default pivot is being used
18370      */
isPivotSet()18371     public boolean isPivotSet() {
18372         return mRenderNode.isPivotExplicitlySet();
18373     }
18374 
18375     /**
18376      * Clears any pivot previously set by a call to  {@link #setPivotX(float)} or
18377      * {@link #setPivotY(float)}. After calling this {@link #isPivotSet()} will be false
18378      * and the pivot used for rotation will return to default of being centered on the view.
18379      */
resetPivot()18380     public void resetPivot() {
18381         if (mRenderNode.resetPivot()) {
18382             invalidateViewProperty(false, false);
18383         }
18384     }
18385 
18386     /**
18387      * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
18388      * completely transparent and 1 means the view is completely opaque.
18389      *
18390      * <p>By default this is 1.0f.
18391      * @return The opacity of the view.
18392      */
18393     @ViewDebug.ExportedProperty(category = "drawing")
18394     @InspectableProperty
getAlpha()18395     public float getAlpha() {
18396         return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
18397     }
18398 
18399     /**
18400      * Sets the behavior for overlapping rendering for this view (see {@link
18401      * #hasOverlappingRendering()} for more details on this behavior). Calling this method
18402      * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
18403      * providing the value which is then used internally. That is, when {@link
18404      * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
18405      * #hasOverlappingRendering()} is ignored and the value passed into this method is used
18406      * instead.
18407      *
18408      * @param hasOverlappingRendering The value for overlapping rendering to be used internally
18409      * instead of that returned by {@link #hasOverlappingRendering()}.
18410      *
18411      * @attr ref android.R.styleable#View_forceHasOverlappingRendering
18412      */
forceHasOverlappingRendering(boolean hasOverlappingRendering)18413     public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
18414         mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
18415         if (hasOverlappingRendering) {
18416             mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
18417         } else {
18418             mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
18419         }
18420     }
18421 
18422     /**
18423      * Returns the value for overlapping rendering that is used internally. This is either
18424      * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
18425      * the return value of {@link #hasOverlappingRendering()}, otherwise.
18426      *
18427      * @return The value for overlapping rendering being used internally.
18428      */
getHasOverlappingRendering()18429     public final boolean getHasOverlappingRendering() {
18430         return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
18431                 (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
18432                 hasOverlappingRendering();
18433     }
18434 
18435     /**
18436      * Returns whether this View has content which overlaps.
18437      *
18438      * <p>This function, intended to be overridden by specific View types, is an optimization when
18439      * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
18440      * an offscreen buffer and then composited into place, which can be expensive. If the view has
18441      * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
18442      * directly. An example of overlapping rendering is a TextView with a background image, such as
18443      * a Button. An example of non-overlapping rendering is a TextView with no background, or an
18444      * ImageView with only the foreground image. The default implementation returns true; subclasses
18445      * should override if they have cases which can be optimized.</p>
18446      *
18447      * <p><strong>Note:</strong> The return value of this method is ignored if {@link
18448      * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
18449      *
18450      * @return true if the content in this view might overlap, false otherwise.
18451      */
18452     @ViewDebug.ExportedProperty(category = "drawing")
hasOverlappingRendering()18453     public boolean hasOverlappingRendering() {
18454         return true;
18455     }
18456 
18457     /**
18458      * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
18459      * completely transparent and 1 means the view is completely opaque.
18460      *
18461      * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
18462      * can have significant performance implications, especially for large views. It is best to use
18463      * the alpha property sparingly and transiently, as in the case of fading animations.</p>
18464      *
18465      * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
18466      * strongly recommended for performance reasons to either override
18467      * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
18468      * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
18469      * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
18470      * the default path for rendering an unlayered View with alpha could add multiple milliseconds
18471      * of rendering cost, even for simple or small views. Starting with
18472      * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
18473      * applied to the view at the rendering level.</p>
18474      *
18475      * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
18476      * responsible for applying the opacity itself.</p>
18477      *
18478      * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
18479      * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
18480      * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
18481      * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
18482      *
18483      * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
18484      * value will clip a View to its bounds, unless the View returns <code>false</code> from
18485      * {@link #hasOverlappingRendering}.</p>
18486      *
18487      * @param alpha The opacity of the view.
18488      *
18489      * @see #hasOverlappingRendering()
18490      * @see #setLayerType(int, android.graphics.Paint)
18491      *
18492      * @attr ref android.R.styleable#View_alpha
18493      */
18494     @RemotableViewMethod
setAlpha(@loatRangefrom=0.0, to=1.0) float alpha)18495     public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
18496         ensureTransformationInfo();
18497         if (mTransformationInfo.mAlpha != alpha) {
18498             setAlphaInternal(alpha);
18499             if (onSetAlpha((int) (alpha * 255))) {
18500                 mPrivateFlags |= PFLAG_ALPHA_SET;
18501                 // subclass is handling alpha - don't optimize rendering cache invalidation
18502                 invalidateParentCaches();
18503                 invalidate(true);
18504             } else {
18505                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
18506                 invalidateViewProperty(true, false);
18507                 mRenderNode.setAlpha(getFinalAlpha());
18508             }
18509         }
18510     }
18511 
18512     /**
18513      * Faster version of setAlpha() which performs the same steps except there are
18514      * no calls to invalidate(). The caller of this function should perform proper invalidation
18515      * on the parent and this object. The return value indicates whether the subclass handles
18516      * alpha (the return value for onSetAlpha()).
18517      *
18518      * @param alpha The new value for the alpha property
18519      * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
18520      *         the new value for the alpha property is different from the old value
18521      */
18522     @UnsupportedAppUsage(maxTargetSdk  = Build.VERSION_CODES.P, trackingBug = 123768435)
setAlphaNoInvalidation(float alpha)18523     boolean setAlphaNoInvalidation(float alpha) {
18524         ensureTransformationInfo();
18525         if (mTransformationInfo.mAlpha != alpha) {
18526             setAlphaInternal(alpha);
18527             boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
18528             if (subclassHandlesAlpha) {
18529                 mPrivateFlags |= PFLAG_ALPHA_SET;
18530                 return true;
18531             } else {
18532                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
18533                 mRenderNode.setAlpha(getFinalAlpha());
18534             }
18535         }
18536         return false;
18537     }
18538 
setAlphaInternal(float alpha)18539     void setAlphaInternal(float alpha) {
18540         float oldAlpha = mTransformationInfo.mAlpha;
18541         mTransformationInfo.mAlpha = alpha;
18542         // Report visibility changes, which can affect children, to accessibility
18543         if ((alpha == 0) ^ (oldAlpha == 0)) {
18544             notifySubtreeAccessibilityStateChangedIfNeeded();
18545         }
18546     }
18547 
18548     /**
18549      * This property is intended only for use by the Fade transition, which animates it
18550      * to produce a visual translucency that does not side-effect (or get affected by)
18551      * the real alpha property. This value is composited with the other alpha value
18552      * (and the AlphaAnimation value, when that is present) to produce a final visual
18553      * translucency result, which is what is passed into the DisplayList.
18554      */
setTransitionAlpha(float alpha)18555     public void setTransitionAlpha(float alpha) {
18556         ensureTransformationInfo();
18557         if (mTransformationInfo.mTransitionAlpha != alpha) {
18558             mTransformationInfo.mTransitionAlpha = alpha;
18559             mPrivateFlags &= ~PFLAG_ALPHA_SET;
18560             invalidateViewProperty(true, false);
18561             mRenderNode.setAlpha(getFinalAlpha());
18562         }
18563     }
18564 
18565     /**
18566      * Calculates the visual alpha of this view, which is a combination of the actual
18567      * alpha value and the transitionAlpha value (if set).
18568      */
getFinalAlpha()18569     private float getFinalAlpha() {
18570         if (mTransformationInfo != null) {
18571             return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
18572         }
18573         return 1;
18574     }
18575 
18576     /**
18577      * This property is intended only for use by the Fade transition, which animates
18578      * it to produce a visual translucency that does not side-effect (or get affected
18579      * by) the real alpha property. This value is composited with the other alpha
18580      * value (and the AlphaAnimation value, when that is present) to produce a final
18581      * visual translucency result, which is what is passed into the DisplayList.
18582      */
18583     @ViewDebug.ExportedProperty(category = "drawing")
getTransitionAlpha()18584     public float getTransitionAlpha() {
18585         return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
18586     }
18587 
18588     /**
18589      * Sets whether or not to allow force dark to apply to this view.
18590      *
18591      * Setting this to false will disable the auto-dark feature on everything this view
18592      * draws, including any descendants.
18593      *
18594      * Setting this to true will allow this view to be automatically made dark, however
18595      * a value of 'true' will not override any 'false' value in its parent chain nor will
18596      * it prevent any 'false' in any of its children.
18597      *
18598      * The default behavior of force dark is also influenced by the Theme's
18599      * {@link android.R.styleable#Theme_isLightTheme isLightTheme} attribute.
18600      * If a theme is isLightTheme="false", then force dark is globally disabled for that theme.
18601      *
18602      * @param allow Whether or not to allow force dark.
18603      */
setForceDarkAllowed(boolean allow)18604     public void setForceDarkAllowed(boolean allow) {
18605         if (mRenderNode.setForceDarkAllowed(allow)) {
18606             // Currently toggling force-dark requires a new display list push to apply
18607             // TODO: Make it not clobber the display list so this is just a damageSelf() instead
18608             invalidate();
18609         }
18610     }
18611 
18612     /**
18613      * See {@link #setForceDarkAllowed(boolean)}
18614      *
18615      * @return true if force dark is allowed (default), false if it is disabled
18616      */
18617     @ViewDebug.ExportedProperty(category = "drawing")
18618     @InspectableProperty
isForceDarkAllowed()18619     public boolean isForceDarkAllowed() {
18620         return mRenderNode.isForceDarkAllowed();
18621     }
18622 
18623     /**
18624      * Top position of this view relative to its parent.
18625      *
18626      * @return The top of this view, in pixels.
18627      */
18628     @ViewDebug.CapturedViewProperty
getTop()18629     public final int getTop() {
18630         return mTop;
18631     }
18632 
18633     /**
18634      * Sets the top position of this view relative to its parent. This method is meant to be called
18635      * by the layout system and should not generally be called otherwise, because the property
18636      * may be changed at any time by the layout.
18637      *
18638      * @param top The top of this view, in pixels.
18639      */
setTop(int top)18640     public final void setTop(int top) {
18641         if (top != mTop) {
18642             final boolean matrixIsIdentity = hasIdentityMatrix();
18643             if (matrixIsIdentity) {
18644                 if (mAttachInfo != null) {
18645                     int minTop;
18646                     int yLoc;
18647                     if (top < mTop) {
18648                         minTop = top;
18649                         yLoc = top - mTop;
18650                     } else {
18651                         minTop = mTop;
18652                         yLoc = 0;
18653                     }
18654                     invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
18655                 }
18656             } else {
18657                 // Double-invalidation is necessary to capture view's old and new areas
18658                 invalidate(true);
18659             }
18660 
18661             int width = mRight - mLeft;
18662             int oldHeight = mBottom - mTop;
18663 
18664             mTop = top;
18665             mRenderNode.setTop(mTop);
18666 
18667             sizeChange(width, mBottom - mTop, width, oldHeight);
18668 
18669             if (!matrixIsIdentity) {
18670                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
18671                 invalidate(true);
18672             }
18673             mBackgroundSizeChanged = true;
18674             mDefaultFocusHighlightSizeChanged = true;
18675             if (mForegroundInfo != null) {
18676                 mForegroundInfo.mBoundsChanged = true;
18677             }
18678             invalidateParentIfNeeded();
18679         }
18680     }
18681 
18682     /**
18683      * Bottom position of this view relative to its parent.
18684      *
18685      * @return The bottom of this view, in pixels.
18686      */
18687     @ViewDebug.CapturedViewProperty
getBottom()18688     public final int getBottom() {
18689         return mBottom;
18690     }
18691 
18692     /**
18693      * True if this view has changed since the last time being drawn.
18694      *
18695      * @return The dirty state of this view.
18696      */
isDirty()18697     public boolean isDirty() {
18698         return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
18699     }
18700 
18701     /**
18702      * Sets the bottom position of this view relative to its parent. This method is meant to be
18703      * called by the layout system and should not generally be called otherwise, because the
18704      * property may be changed at any time by the layout.
18705      *
18706      * @param bottom The bottom of this view, in pixels.
18707      */
setBottom(int bottom)18708     public final void setBottom(int bottom) {
18709         if (bottom != mBottom) {
18710             final boolean matrixIsIdentity = hasIdentityMatrix();
18711             if (matrixIsIdentity) {
18712                 if (mAttachInfo != null) {
18713                     int maxBottom;
18714                     if (bottom < mBottom) {
18715                         maxBottom = mBottom;
18716                     } else {
18717                         maxBottom = bottom;
18718                     }
18719                     invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
18720                 }
18721             } else {
18722                 // Double-invalidation is necessary to capture view's old and new areas
18723                 invalidate(true);
18724             }
18725 
18726             int width = mRight - mLeft;
18727             int oldHeight = mBottom - mTop;
18728 
18729             mBottom = bottom;
18730             mRenderNode.setBottom(mBottom);
18731 
18732             sizeChange(width, mBottom - mTop, width, oldHeight);
18733 
18734             if (!matrixIsIdentity) {
18735                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
18736                 invalidate(true);
18737             }
18738             mBackgroundSizeChanged = true;
18739             mDefaultFocusHighlightSizeChanged = true;
18740             if (mForegroundInfo != null) {
18741                 mForegroundInfo.mBoundsChanged = true;
18742             }
18743             invalidateParentIfNeeded();
18744         }
18745     }
18746 
18747     /**
18748      * Left position of this view relative to its parent.
18749      *
18750      * @return The left edge of this view, in pixels.
18751      */
18752     @ViewDebug.CapturedViewProperty
getLeft()18753     public final int getLeft() {
18754         return mLeft;
18755     }
18756 
18757     /**
18758      * Sets the left position of this view relative to its parent. This method is meant to be called
18759      * by the layout system and should not generally be called otherwise, because the property
18760      * may be changed at any time by the layout.
18761      *
18762      * @param left The left of this view, in pixels.
18763      */
setLeft(int left)18764     public final void setLeft(int left) {
18765         if (left != mLeft) {
18766             final boolean matrixIsIdentity = hasIdentityMatrix();
18767             if (matrixIsIdentity) {
18768                 if (mAttachInfo != null) {
18769                     int minLeft;
18770                     int xLoc;
18771                     if (left < mLeft) {
18772                         minLeft = left;
18773                         xLoc = left - mLeft;
18774                     } else {
18775                         minLeft = mLeft;
18776                         xLoc = 0;
18777                     }
18778                     invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
18779                 }
18780             } else {
18781                 // Double-invalidation is necessary to capture view's old and new areas
18782                 invalidate(true);
18783             }
18784 
18785             int oldWidth = mRight - mLeft;
18786             int height = mBottom - mTop;
18787 
18788             mLeft = left;
18789             mRenderNode.setLeft(left);
18790 
18791             sizeChange(mRight - mLeft, height, oldWidth, height);
18792 
18793             if (!matrixIsIdentity) {
18794                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
18795                 invalidate(true);
18796             }
18797             mBackgroundSizeChanged = true;
18798             mDefaultFocusHighlightSizeChanged = true;
18799             if (mForegroundInfo != null) {
18800                 mForegroundInfo.mBoundsChanged = true;
18801             }
18802             invalidateParentIfNeeded();
18803         }
18804     }
18805 
18806     /**
18807      * Right position of this view relative to its parent.
18808      *
18809      * @return The right edge of this view, in pixels.
18810      */
18811     @ViewDebug.CapturedViewProperty
getRight()18812     public final int getRight() {
18813         return mRight;
18814     }
18815 
18816     /**
18817      * Sets the right position of this view relative to its parent. This method is meant to be called
18818      * by the layout system and should not generally be called otherwise, because the property
18819      * may be changed at any time by the layout.
18820      *
18821      * @param right The right of this view, in pixels.
18822      */
setRight(int right)18823     public final void setRight(int right) {
18824         if (right != mRight) {
18825             final boolean matrixIsIdentity = hasIdentityMatrix();
18826             if (matrixIsIdentity) {
18827                 if (mAttachInfo != null) {
18828                     int maxRight;
18829                     if (right < mRight) {
18830                         maxRight = mRight;
18831                     } else {
18832                         maxRight = right;
18833                     }
18834                     invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
18835                 }
18836             } else {
18837                 // Double-invalidation is necessary to capture view's old and new areas
18838                 invalidate(true);
18839             }
18840 
18841             int oldWidth = mRight - mLeft;
18842             int height = mBottom - mTop;
18843 
18844             mRight = right;
18845             mRenderNode.setRight(mRight);
18846 
18847             sizeChange(mRight - mLeft, height, oldWidth, height);
18848 
18849             if (!matrixIsIdentity) {
18850                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
18851                 invalidate(true);
18852             }
18853             mBackgroundSizeChanged = true;
18854             mDefaultFocusHighlightSizeChanged = true;
18855             if (mForegroundInfo != null) {
18856                 mForegroundInfo.mBoundsChanged = true;
18857             }
18858             invalidateParentIfNeeded();
18859         }
18860     }
18861 
sanitizeFloatPropertyValue(float value, String propertyName)18862     private static float sanitizeFloatPropertyValue(float value, String propertyName) {
18863         return sanitizeFloatPropertyValue(value, propertyName, -Float.MAX_VALUE, Float.MAX_VALUE);
18864     }
18865 
sanitizeFloatPropertyValue(float value, String propertyName, float min, float max)18866     private static float sanitizeFloatPropertyValue(float value, String propertyName,
18867             float min, float max) {
18868         // The expected "nothing bad happened" path
18869         if (value >= min && value <= max) return value;
18870 
18871         if (value < min || value == Float.NEGATIVE_INFINITY) {
18872             if (sThrowOnInvalidFloatProperties) {
18873                 throw new IllegalArgumentException("Cannot set '" + propertyName + "' to "
18874                         + value + ", the value must be >= " + min);
18875             }
18876             return min;
18877         }
18878 
18879         if (value > max || value == Float.POSITIVE_INFINITY) {
18880             if (sThrowOnInvalidFloatProperties) {
18881                 throw new IllegalArgumentException("Cannot set '" + propertyName + "' to "
18882                         + value + ", the value must be <= " + max);
18883             }
18884             return max;
18885         }
18886 
18887         if (Float.isNaN(value)) {
18888             if (sThrowOnInvalidFloatProperties) {
18889                 throw new IllegalArgumentException(
18890                         "Cannot set '" + propertyName + "' to Float.NaN");
18891             }
18892             return 0; // Unclear which direction this NaN went so... 0?
18893         }
18894 
18895         // Shouldn't be possible to reach this.
18896         throw new IllegalStateException("How do you get here?? " + value);
18897     }
18898 
18899     /**
18900      * The visual x position of this view, in pixels. This is equivalent to the
18901      * {@link #setTranslationX(float) translationX} property plus the current
18902      * {@link #getLeft() left} property.
18903      *
18904      * @return The visual x position of this view, in pixels.
18905      */
18906     @ViewDebug.ExportedProperty(category = "drawing")
getX()18907     public float getX() {
18908         return mLeft + getTranslationX();
18909     }
18910 
18911     /**
18912      * Sets the visual x position of this view, in pixels. This is equivalent to setting the
18913      * {@link #setTranslationX(float) translationX} property to be the difference between
18914      * the x value passed in and the current {@link #getLeft() left} property.
18915      *
18916      * @param x The visual x position of this view, in pixels.
18917      */
setX(float x)18918     public void setX(float x) {
18919         setTranslationX(x - mLeft);
18920     }
18921 
18922     /**
18923      * The visual y position of this view, in pixels. This is equivalent to the
18924      * {@link #setTranslationY(float) translationY} property plus the current
18925      * {@link #getTop() top} property.
18926      *
18927      * @return The visual y position of this view, in pixels.
18928      */
18929     @ViewDebug.ExportedProperty(category = "drawing")
getY()18930     public float getY() {
18931         return mTop + getTranslationY();
18932     }
18933 
18934     /**
18935      * Sets the visual y position of this view, in pixels. This is equivalent to setting the
18936      * {@link #setTranslationY(float) translationY} property to be the difference between
18937      * the y value passed in and the current {@link #getTop() top} property.
18938      *
18939      * @param y The visual y position of this view, in pixels.
18940      */
setY(float y)18941     public void setY(float y) {
18942         setTranslationY(y - mTop);
18943     }
18944 
18945     /**
18946      * The visual z position of this view, in pixels. This is equivalent to the
18947      * {@link #setTranslationZ(float) translationZ} property plus the current
18948      * {@link #getElevation() elevation} property.
18949      *
18950      * @return The visual z position of this view, in pixels.
18951      */
18952     @ViewDebug.ExportedProperty(category = "drawing")
getZ()18953     public float getZ() {
18954         return getElevation() + getTranslationZ();
18955     }
18956 
18957     /**
18958      * Sets the visual z position of this view, in pixels. This is equivalent to setting the
18959      * {@link #setTranslationZ(float) translationZ} property to be the difference between
18960      * the z value passed in and the current {@link #getElevation() elevation} property.
18961      *
18962      * @param z The visual z position of this view, in pixels.
18963      */
setZ(float z)18964     public void setZ(float z) {
18965         setTranslationZ(z - getElevation());
18966     }
18967 
18968     /**
18969      * The base elevation of this view relative to its parent, in pixels.
18970      *
18971      * @return The base depth position of the view, in pixels.
18972      */
18973     @ViewDebug.ExportedProperty(category = "drawing")
18974     @InspectableProperty
getElevation()18975     public float getElevation() {
18976         return mRenderNode.getElevation();
18977     }
18978 
18979     /**
18980      * Sets the base elevation of this view, in pixels.
18981      *
18982      * @attr ref android.R.styleable#View_elevation
18983      */
18984     @RemotableViewMethod
setElevation(float elevation)18985     public void setElevation(float elevation) {
18986         if (elevation != getElevation()) {
18987             elevation = sanitizeFloatPropertyValue(elevation, "elevation");
18988             invalidateViewProperty(true, false);
18989             mRenderNode.setElevation(elevation);
18990             invalidateViewProperty(false, true);
18991 
18992             invalidateParentIfNeededAndWasQuickRejected();
18993         }
18994     }
18995 
18996     /**
18997      * The horizontal location of this view relative to its {@link #getLeft() left} position.
18998      * This position is post-layout, in addition to wherever the object's
18999      * layout placed it.
19000      *
19001      * @return The horizontal position of this view relative to its left position, in pixels.
19002      */
19003     @ViewDebug.ExportedProperty(category = "drawing")
19004     @InspectableProperty
getTranslationX()19005     public float getTranslationX() {
19006         return mRenderNode.getTranslationX();
19007     }
19008 
19009     /**
19010      * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
19011      * This effectively positions the object post-layout, in addition to wherever the object's
19012      * layout placed it.
19013      *
19014      * @param translationX The horizontal position of this view relative to its left position,
19015      * in pixels.
19016      *
19017      * @attr ref android.R.styleable#View_translationX
19018      */
19019     @RemotableViewMethod
setTranslationX(float translationX)19020     public void setTranslationX(float translationX) {
19021         if (translationX != getTranslationX()) {
19022             invalidateViewProperty(true, false);
19023             mRenderNode.setTranslationX(translationX);
19024             invalidateViewProperty(false, true);
19025 
19026             invalidateParentIfNeededAndWasQuickRejected();
19027             notifySubtreeAccessibilityStateChangedIfNeeded();
19028         }
19029     }
19030 
19031     /**
19032      * The vertical location of this view relative to its {@link #getTop() top} position.
19033      * This position is post-layout, in addition to wherever the object's
19034      * layout placed it.
19035      *
19036      * @return The vertical position of this view relative to its top position,
19037      * in pixels.
19038      */
19039     @ViewDebug.ExportedProperty(category = "drawing")
19040     @InspectableProperty
getTranslationY()19041     public float getTranslationY() {
19042         return mRenderNode.getTranslationY();
19043     }
19044 
19045     /**
19046      * Sets the vertical location of this view relative to its {@link #getTop() top} position.
19047      * This effectively positions the object post-layout, in addition to wherever the object's
19048      * layout placed it.
19049      *
19050      * @param translationY The vertical position of this view relative to its top position,
19051      * in pixels.
19052      *
19053      * @attr ref android.R.styleable#View_translationY
19054      */
19055     @RemotableViewMethod
setTranslationY(float translationY)19056     public void setTranslationY(float translationY) {
19057         if (translationY != getTranslationY()) {
19058             invalidateViewProperty(true, false);
19059             mRenderNode.setTranslationY(translationY);
19060             invalidateViewProperty(false, true);
19061 
19062             invalidateParentIfNeededAndWasQuickRejected();
19063             notifySubtreeAccessibilityStateChangedIfNeeded();
19064         }
19065     }
19066 
19067     /**
19068      * The depth location of this view relative to its {@link #getElevation() elevation}.
19069      *
19070      * @return The depth of this view relative to its elevation.
19071      */
19072     @ViewDebug.ExportedProperty(category = "drawing")
19073     @InspectableProperty
getTranslationZ()19074     public float getTranslationZ() {
19075         return mRenderNode.getTranslationZ();
19076     }
19077 
19078     /**
19079      * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
19080      *
19081      * @attr ref android.R.styleable#View_translationZ
19082      */
19083     @RemotableViewMethod
setTranslationZ(float translationZ)19084     public void setTranslationZ(float translationZ) {
19085         if (translationZ != getTranslationZ()) {
19086             translationZ = sanitizeFloatPropertyValue(translationZ, "translationZ");
19087             invalidateViewProperty(true, false);
19088             mRenderNode.setTranslationZ(translationZ);
19089             invalidateViewProperty(false, true);
19090 
19091             invalidateParentIfNeededAndWasQuickRejected();
19092         }
19093     }
19094 
19095     /**
19096      * Changes the transformation matrix on the view. This is used in animation frameworks,
19097      * such as {@link android.transition.Transition}. When the animation finishes, the matrix
19098      * should be cleared by calling this method with <code>null</code> as the matrix parameter.
19099      * Application developers should use transformation methods like {@link #setRotation(float)},
19100      * {@link #setScaleX(float)}, {@link #setScaleX(float)}, {@link #setTranslationX(float)}}
19101      * and {@link #setTranslationY(float)} (float)}} instead.
19102      *
19103      * @param matrix The matrix, null indicates that the matrix should be cleared.
19104      * @see #getAnimationMatrix()
19105      */
setAnimationMatrix(@ullable Matrix matrix)19106     public void setAnimationMatrix(@Nullable Matrix matrix) {
19107         invalidateViewProperty(true, false);
19108         mRenderNode.setAnimationMatrix(matrix);
19109         invalidateViewProperty(false, true);
19110 
19111         invalidateParentIfNeededAndWasQuickRejected();
19112     }
19113 
19114     /**
19115      * Return the current transformation matrix of the view. This is used in animation frameworks,
19116      * such as {@link android.transition.Transition}. Returns <code>null</code> when there is no
19117      * transformation provided by {@link #setAnimationMatrix(Matrix)}.
19118      * Application developers should use transformation methods like {@link #setRotation(float)},
19119      * {@link #setScaleX(float)}, {@link #setScaleX(float)}, {@link #setTranslationX(float)}}
19120      * and {@link #setTranslationY(float)} (float)}} instead.
19121      *
19122      * @return the Matrix, null indicates there is no transformation
19123      * @see #setAnimationMatrix(Matrix)
19124      */
19125     @Nullable
getAnimationMatrix()19126     public Matrix getAnimationMatrix() {
19127         return mRenderNode.getAnimationMatrix();
19128     }
19129 
19130     /**
19131      * Returns the current StateListAnimator if exists.
19132      *
19133      * @return StateListAnimator or null if it does not exists
19134      * @see    #setStateListAnimator(android.animation.StateListAnimator)
19135      */
19136     @InspectableProperty
getStateListAnimator()19137     public StateListAnimator getStateListAnimator() {
19138         return mStateListAnimator;
19139     }
19140 
19141     /**
19142      * Attaches the provided StateListAnimator to this View.
19143      * <p>
19144      * Any previously attached StateListAnimator will be detached.
19145      *
19146      * @param stateListAnimator The StateListAnimator to update the view
19147      * @see android.animation.StateListAnimator
19148      */
setStateListAnimator(StateListAnimator stateListAnimator)19149     public void setStateListAnimator(StateListAnimator stateListAnimator) {
19150         if (mStateListAnimator == stateListAnimator) {
19151             return;
19152         }
19153         if (mStateListAnimator != null) {
19154             mStateListAnimator.setTarget(null);
19155         }
19156         mStateListAnimator = stateListAnimator;
19157         if (stateListAnimator != null) {
19158             stateListAnimator.setTarget(this);
19159             if (isAttachedToWindow()) {
19160                 stateListAnimator.setState(getDrawableState());
19161             }
19162         }
19163     }
19164 
19165     /**
19166      * Returns whether the Outline should be used to clip the contents of the View.
19167      * <p>
19168      * Note that this flag will only be respected if the View's Outline returns true from
19169      * {@link Outline#canClip()}.
19170      *
19171      * @see #setOutlineProvider(ViewOutlineProvider)
19172      * @see #setClipToOutline(boolean)
19173      */
getClipToOutline()19174     public final boolean getClipToOutline() {
19175         return mRenderNode.getClipToOutline();
19176     }
19177 
19178     /**
19179      * Sets whether the View's Outline should be used to clip the contents of the View.
19180      * <p>
19181      * Only a single non-rectangular clip can be applied on a View at any time.
19182      * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
19183      * circular reveal} animation take priority over Outline clipping, and
19184      * child Outline clipping takes priority over Outline clipping done by a
19185      * parent.
19186      * <p>
19187      * Note that this flag will only be respected if the View's Outline returns true from
19188      * {@link Outline#canClip()}.
19189      *
19190      * @see #setOutlineProvider(ViewOutlineProvider)
19191      * @see #getClipToOutline()
19192      *
19193      * @attr ref android.R.styleable#View_clipToOutline
19194      */
19195     @RemotableViewMethod
setClipToOutline(boolean clipToOutline)19196     public void setClipToOutline(boolean clipToOutline) {
19197         damageInParent();
19198         if (getClipToOutline() != clipToOutline) {
19199             mRenderNode.setClipToOutline(clipToOutline);
19200         }
19201     }
19202 
19203     // correspond to the enum values of View_outlineProvider
19204     private static final int PROVIDER_BACKGROUND = 0;
19205     private static final int PROVIDER_NONE = 1;
19206     private static final int PROVIDER_BOUNDS = 2;
19207     private static final int PROVIDER_PADDED_BOUNDS = 3;
setOutlineProviderFromAttribute(int providerInt)19208     private void setOutlineProviderFromAttribute(int providerInt) {
19209         switch (providerInt) {
19210             case PROVIDER_BACKGROUND:
19211                 setOutlineProvider(ViewOutlineProvider.BACKGROUND);
19212                 break;
19213             case PROVIDER_NONE:
19214                 setOutlineProvider(null);
19215                 break;
19216             case PROVIDER_BOUNDS:
19217                 setOutlineProvider(ViewOutlineProvider.BOUNDS);
19218                 break;
19219             case PROVIDER_PADDED_BOUNDS:
19220                 setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
19221                 break;
19222         }
19223     }
19224 
19225     /**
19226      * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
19227      * the shape of the shadow it casts, and enables outline clipping.
19228      * <p>
19229      * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
19230      * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
19231      * outline provider with this method allows this behavior to be overridden.
19232      * <p>
19233      * If the ViewOutlineProvider is null, if querying it for an outline returns false,
19234      * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
19235      * <p>
19236      * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
19237      *
19238      * @see #setClipToOutline(boolean)
19239      * @see #getClipToOutline()
19240      * @see #getOutlineProvider()
19241      */
setOutlineProvider(ViewOutlineProvider provider)19242     public void setOutlineProvider(ViewOutlineProvider provider) {
19243         if (mOutlineProvider != provider) {
19244             mOutlineProvider = provider;
19245             invalidateOutline();
19246         }
19247     }
19248 
19249     /**
19250      * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
19251      * that defines the shape of the shadow it casts, and enables outline clipping.
19252      *
19253      * @see #setOutlineProvider(ViewOutlineProvider)
19254      */
19255     @InspectableProperty
getOutlineProvider()19256     public ViewOutlineProvider getOutlineProvider() {
19257         return mOutlineProvider;
19258     }
19259 
19260     /**
19261      * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
19262      *
19263      * @see #setOutlineProvider(ViewOutlineProvider)
19264      */
invalidateOutline()19265     public void invalidateOutline() {
19266         rebuildOutline();
19267 
19268         notifySubtreeAccessibilityStateChangedIfNeeded();
19269         invalidateViewProperty(false, false);
19270     }
19271 
19272     /**
19273      * Internal version of {@link #invalidateOutline()} which invalidates the
19274      * outline without invalidating the view itself. This is intended to be called from
19275      * within methods in the View class itself which are the result of the view being
19276      * invalidated already. For example, when we are drawing the background of a View,
19277      * we invalidate the outline in case it changed in the meantime, but we do not
19278      * need to invalidate the view because we're already drawing the background as part
19279      * of drawing the view in response to an earlier invalidation of the view.
19280      */
rebuildOutline()19281     private void rebuildOutline() {
19282         // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
19283         if (mAttachInfo == null) return;
19284 
19285         if (mOutlineProvider == null) {
19286             // no provider, remove outline
19287             mRenderNode.setOutline(null);
19288         } else {
19289             final Outline outline = mAttachInfo.mTmpOutline;
19290             outline.setEmpty();
19291             outline.setAlpha(1.0f);
19292 
19293             mOutlineProvider.getOutline(this, outline);
19294             mRenderNode.setOutline(outline);
19295         }
19296     }
19297 
19298     /**
19299      * HierarchyViewer only
19300      *
19301      * @hide
19302      */
19303     @ViewDebug.ExportedProperty(category = "drawing")
hasShadow()19304     public boolean hasShadow() {
19305         return mRenderNode.hasShadow();
19306     }
19307 
19308     /**
19309      * Sets the color of the spot shadow that is drawn when the view has a positive Z or
19310      * elevation value.
19311      * <p>
19312      * By default the shadow color is black. Generally, this color will be opaque so the intensity
19313      * of the shadow is consistent between different views with different colors.
19314      * <p>
19315      * The opacity of the final spot shadow is a function of the shadow caster height, the
19316      * alpha channel of the outlineSpotShadowColor (typically opaque), and the
19317      * {@link android.R.attr#spotShadowAlpha} theme attribute.
19318      *
19319      * @attr ref android.R.styleable#View_outlineSpotShadowColor
19320      * @param color The color this View will cast for its elevation spot shadow.
19321      */
setOutlineSpotShadowColor(@olorInt int color)19322     public void setOutlineSpotShadowColor(@ColorInt int color) {
19323         if (mRenderNode.setSpotShadowColor(color)) {
19324             invalidateViewProperty(true, true);
19325         }
19326     }
19327 
19328     /**
19329      * @return The shadow color set by {@link #setOutlineSpotShadowColor(int)}, or black if nothing
19330      * was set
19331      */
19332     @InspectableProperty
getOutlineSpotShadowColor()19333     public @ColorInt int getOutlineSpotShadowColor() {
19334         return mRenderNode.getSpotShadowColor();
19335     }
19336 
19337     /**
19338      * Sets the color of the ambient shadow that is drawn when the view has a positive Z or
19339      * elevation value.
19340      * <p>
19341      * By default the shadow color is black. Generally, this color will be opaque so the intensity
19342      * of the shadow is consistent between different views with different colors.
19343      * <p>
19344      * The opacity of the final ambient shadow is a function of the shadow caster height, the
19345      * alpha channel of the outlineAmbientShadowColor (typically opaque), and the
19346      * {@link android.R.attr#ambientShadowAlpha} theme attribute.
19347      *
19348      * @attr ref android.R.styleable#View_outlineAmbientShadowColor
19349      * @param color The color this View will cast for its elevation shadow.
19350      */
setOutlineAmbientShadowColor(@olorInt int color)19351     public void setOutlineAmbientShadowColor(@ColorInt int color) {
19352         if (mRenderNode.setAmbientShadowColor(color)) {
19353             invalidateViewProperty(true, true);
19354         }
19355     }
19356 
19357     /**
19358      * @return The shadow color set by {@link #setOutlineAmbientShadowColor(int)}, or black if
19359      * nothing was set
19360      */
19361     @InspectableProperty
getOutlineAmbientShadowColor()19362     public @ColorInt int getOutlineAmbientShadowColor() {
19363         return mRenderNode.getAmbientShadowColor();
19364     }
19365 
19366 
19367     /** @hide */
setRevealClip(boolean shouldClip, float x, float y, float radius)19368     public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
19369         mRenderNode.setRevealClip(shouldClip, x, y, radius);
19370         invalidateViewProperty(false, false);
19371     }
19372 
19373     /**
19374      * Hit rectangle in parent's coordinates
19375      *
19376      * @param outRect The hit rectangle of the view.
19377      */
getHitRect(Rect outRect)19378     public void getHitRect(Rect outRect) {
19379         if (hasIdentityMatrix() || mAttachInfo == null) {
19380             outRect.set(mLeft, mTop, mRight, mBottom);
19381         } else {
19382             final RectF tmpRect = mAttachInfo.mTmpTransformRect;
19383             tmpRect.set(0, 0, getWidth(), getHeight());
19384             getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
19385             outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
19386                     (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
19387         }
19388     }
19389 
19390     /**
19391      * Determines whether the given point, in local coordinates is inside the view.
19392      */
pointInView(float localX, float localY)19393     /*package*/ final boolean pointInView(float localX, float localY) {
19394         return pointInView(localX, localY, 0);
19395     }
19396 
19397     /**
19398      * Utility method to determine whether the given point, in local coordinates,
19399      * is inside the view, where the area of the view is expanded by the slop factor.
19400      * This method is called while processing touch-move events to determine if the event
19401      * is still within the view.
19402      *
19403      * @hide
19404      */
19405     @UnsupportedAppUsage
pointInView(float localX, float localY, float slop)19406     public boolean pointInView(float localX, float localY, float slop) {
19407         return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
19408                 localY < ((mBottom - mTop) + slop);
19409     }
19410 
19411     /**
19412      * When a view has focus and the user navigates away from it, the next view is searched for
19413      * starting from the rectangle filled in by this method.
19414      *
19415      * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
19416      * of the view.  However, if your view maintains some idea of internal selection,
19417      * such as a cursor, or a selected row or column, you should override this method and
19418      * fill in a more specific rectangle.
19419      *
19420      * @param r The rectangle to fill in, in this view's coordinates.
19421      */
getFocusedRect(Rect r)19422     public void getFocusedRect(Rect r) {
19423         getDrawingRect(r);
19424     }
19425 
19426     /**
19427      * Sets {@code r} to the coordinates of the non-clipped area of this view in
19428      * the coordinate space of the view's root view. Sets {@code globalOffset}
19429      * to the offset of the view's x and y coordinates from the coordinate space
19430      * origin, which is the top left corner of the root view irrespective of
19431      * screen decorations and system UI elements.
19432      *
19433      * <p>To convert {@code r} to coordinates relative to the top left corner of
19434      * this view (without taking view rotations into account), offset {@code r}
19435      * by the inverse values of
19436      * {@code globalOffset}&mdash;{@code r.offset(-globalOffset.x,
19437      * -globalOffset.y)}&mdash;which is equivalent to calling
19438      * {@link #getLocalVisibleRect(Rect) getLocalVisibleRect(Rect)}.
19439      *
19440      * <p><b>Note:</b> Do not use this method to determine the size of a window
19441      * in multi-window mode; use
19442      * {@link WindowManager#getCurrentWindowMetrics()}.
19443      *
19444      * @param r If the method returns true, contains the coordinates of the
19445      *      visible portion of this view in the coordinate space of the view's
19446      *      root view. If the method returns false, the contents of {@code r}
19447      *      are undefined.
19448      * @param globalOffset If the method returns true, contains the offset of
19449      *      the x and y coordinates of this view from the top left corner of the
19450      *      view's root view. If the method returns false, the contents of
19451      *      {@code globalOffset} are undefined. The argument can be null (see
19452      *      {@link #getGlobalVisibleRect(Rect) getGlobalVisibleRect(Rect)}.
19453      * @return true if at least part of the view is visible within the root
19454      *      view; false if the view is completely clipped or translated out of
19455      *      the visible area of the root view.
19456      *
19457      * @see #getLocalVisibleRect(Rect)
19458      */
getGlobalVisibleRect(Rect r, Point globalOffset)19459     public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
19460         int width = mRight - mLeft;
19461         int height = mBottom - mTop;
19462         if (width > 0 && height > 0) {
19463             r.set(0, 0, width, height);
19464             if (globalOffset != null) {
19465                 globalOffset.set(-mScrollX, -mScrollY);
19466             }
19467             return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
19468         }
19469         return false;
19470     }
19471 
19472     /**
19473      * Sets {@code r} to the coordinates of the non-clipped area of this view in
19474      * the coordinate space of the view's root view.
19475      *
19476      * <p>See {@link #getGlobalVisibleRect(Rect, Point)
19477      * getGlobalVisibleRect(Rect, Point)} for more information.
19478      *
19479      * @param r If the method returns true, contains the coordinates of the
19480      *      visible portion of this view in the coordinate space of the view's
19481      *      root view. If the method returns false, the contents of {@code r}
19482      *      are undefined.
19483      * @return true if at least part of the view is visible within the root
19484      *      view; otherwise false.
19485      */
getGlobalVisibleRect(Rect r)19486     public final boolean getGlobalVisibleRect(Rect r) {
19487         return getGlobalVisibleRect(r, null);
19488     }
19489 
19490     /**
19491      * Sets {@code r} to the coordinates of the non-clipped area of this view
19492      * relative to the top left corner of the view.
19493      *
19494      * <p>If the view is clipped on the left or top, the left and top
19495      * coordinates are offset from 0 by the clipped amount. For example, if the
19496      * view is off screen 50px on the left and 30px at the top, the left and top
19497      * coordinates are 50 and 30 respectively.
19498      *
19499      * <p>If the view is clipped on the right or bottom, the right and bottom
19500      * coordinates are reduced by the clipped amount. For example, if the view
19501      * is off screen 40px on the right and 20px at the bottom, the right
19502      * coordinate is the view width - 40, and the bottom coordinate is the view
19503      * height - 20.
19504      *
19505      * @param r If the method returns true, contains the coordinates of the
19506      *      visible portion of this view relative to the top left corner of the
19507      *      view. If the method returns false, the contents of {@code r} are
19508      *      undefined.
19509      * @return true if at least part of the view is visible; false if the view
19510      *      is completely clipped or translated out of the visible area.
19511      *
19512      * @see #getGlobalVisibleRect(Rect, Point)
19513      */
getLocalVisibleRect(Rect r)19514     public final boolean getLocalVisibleRect(Rect r) {
19515         final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
19516         if (getGlobalVisibleRect(r, offset)) {
19517             r.offset(-offset.x, -offset.y); // make r local
19518             return true;
19519         }
19520         return false;
19521     }
19522 
19523     /**
19524      * Offset this view's vertical location by the specified number of pixels.
19525      *
19526      * @param offset the number of pixels to offset the view by
19527      */
offsetTopAndBottom(int offset)19528     public void offsetTopAndBottom(int offset) {
19529         if (offset != 0) {
19530             final boolean matrixIsIdentity = hasIdentityMatrix();
19531             if (matrixIsIdentity) {
19532                 if (isHardwareAccelerated()) {
19533                     invalidateViewProperty(false, false);
19534                 } else {
19535                     final ViewParent p = mParent;
19536                     if (p != null && mAttachInfo != null) {
19537                         final Rect r = mAttachInfo.mTmpInvalRect;
19538                         int minTop;
19539                         int maxBottom;
19540                         int yLoc;
19541                         if (offset < 0) {
19542                             minTop = mTop + offset;
19543                             maxBottom = mBottom;
19544                             yLoc = offset;
19545                         } else {
19546                             minTop = mTop;
19547                             maxBottom = mBottom + offset;
19548                             yLoc = 0;
19549                         }
19550                         r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
19551                         p.invalidateChild(this, r);
19552                     }
19553                 }
19554             } else {
19555                 invalidateViewProperty(false, false);
19556             }
19557 
19558             mTop += offset;
19559             mBottom += offset;
19560             mRenderNode.offsetTopAndBottom(offset);
19561             if (isHardwareAccelerated()) {
19562                 invalidateViewProperty(false, false);
19563                 invalidateParentIfNeededAndWasQuickRejected();
19564             } else {
19565                 if (!matrixIsIdentity) {
19566                     invalidateViewProperty(false, true);
19567                 }
19568                 invalidateParentIfNeeded();
19569             }
19570             notifySubtreeAccessibilityStateChangedIfNeeded();
19571         }
19572     }
19573 
19574     /**
19575      * Offset this view's horizontal location by the specified amount of pixels.
19576      *
19577      * @param offset the number of pixels to offset the view by
19578      */
offsetLeftAndRight(int offset)19579     public void offsetLeftAndRight(int offset) {
19580         if (offset != 0) {
19581             final boolean matrixIsIdentity = hasIdentityMatrix();
19582             if (matrixIsIdentity) {
19583                 if (isHardwareAccelerated()) {
19584                     invalidateViewProperty(false, false);
19585                 } else {
19586                     final ViewParent p = mParent;
19587                     if (p != null && mAttachInfo != null) {
19588                         final Rect r = mAttachInfo.mTmpInvalRect;
19589                         int minLeft;
19590                         int maxRight;
19591                         if (offset < 0) {
19592                             minLeft = mLeft + offset;
19593                             maxRight = mRight;
19594                         } else {
19595                             minLeft = mLeft;
19596                             maxRight = mRight + offset;
19597                         }
19598                         r.set(0, 0, maxRight - minLeft, mBottom - mTop);
19599                         p.invalidateChild(this, r);
19600                     }
19601                 }
19602             } else {
19603                 invalidateViewProperty(false, false);
19604             }
19605 
19606             mLeft += offset;
19607             mRight += offset;
19608             mRenderNode.offsetLeftAndRight(offset);
19609             if (isHardwareAccelerated()) {
19610                 invalidateViewProperty(false, false);
19611                 invalidateParentIfNeededAndWasQuickRejected();
19612             } else {
19613                 if (!matrixIsIdentity) {
19614                     invalidateViewProperty(false, true);
19615                 }
19616                 invalidateParentIfNeeded();
19617             }
19618             notifySubtreeAccessibilityStateChangedIfNeeded();
19619         }
19620     }
19621 
19622     /**
19623      * Get the LayoutParams associated with this view. All views should have
19624      * layout parameters. These supply parameters to the <i>parent</i> of this
19625      * view specifying how it should be arranged. There are many subclasses of
19626      * ViewGroup.LayoutParams, and these correspond to the different subclasses
19627      * of ViewGroup that are responsible for arranging their children.
19628      *
19629      * This method may return null if this View is not attached to a parent
19630      * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
19631      * was not invoked successfully. When a View is attached to a parent
19632      * ViewGroup, this method must not return null.
19633      *
19634      * @return The LayoutParams associated with this view, or null if no
19635      *         parameters have been set yet
19636      */
19637     @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
getLayoutParams()19638     public ViewGroup.LayoutParams getLayoutParams() {
19639         return mLayoutParams;
19640     }
19641 
19642     /**
19643      * Set the layout parameters associated with this view. These supply
19644      * parameters to the <i>parent</i> of this view specifying how it should be
19645      * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
19646      * correspond to the different subclasses of ViewGroup that are responsible
19647      * for arranging their children.
19648      *
19649      * @param params The layout parameters for this view, cannot be null
19650      */
setLayoutParams(ViewGroup.LayoutParams params)19651     public void setLayoutParams(ViewGroup.LayoutParams params) {
19652         if (params == null) {
19653             throw new NullPointerException("Layout parameters cannot be null");
19654         }
19655         mLayoutParams = params;
19656         resolveLayoutParams();
19657         if (mParent instanceof ViewGroup) {
19658             ((ViewGroup) mParent).onSetLayoutParams(this, params);
19659         }
19660         requestLayout();
19661     }
19662 
19663     /**
19664      * Resolve the layout parameters depending on the resolved layout direction
19665      *
19666      * @hide
19667      */
resolveLayoutParams()19668     public void resolveLayoutParams() {
19669         if (mLayoutParams != null) {
19670             mLayoutParams.resolveLayoutDirection(getLayoutDirection());
19671         }
19672     }
19673 
19674     /**
19675      * Set the scrolled position of your view. This will cause a call to
19676      * {@link #onScrollChanged(int, int, int, int)} and the view will be
19677      * invalidated.
19678      * @param x the x position to scroll to
19679      * @param y the y position to scroll to
19680      */
scrollTo(int x, int y)19681     public void scrollTo(int x, int y) {
19682         if (mScrollX != x || mScrollY != y) {
19683             int oldX = mScrollX;
19684             int oldY = mScrollY;
19685             mScrollX = x;
19686             mScrollY = y;
19687             invalidateParentCaches();
19688             onScrollChanged(mScrollX, mScrollY, oldX, oldY);
19689             if (!awakenScrollBars()) {
19690                 postInvalidateOnAnimation();
19691             }
19692         }
19693     }
19694 
19695     /**
19696      * Move the scrolled position of your view. This will cause a call to
19697      * {@link #onScrollChanged(int, int, int, int)} and the view will be
19698      * invalidated.
19699      * @param x the amount of pixels to scroll by horizontally
19700      * @param y the amount of pixels to scroll by vertically
19701      */
scrollBy(int x, int y)19702     public void scrollBy(int x, int y) {
19703         scrollTo(mScrollX + x, mScrollY + y);
19704     }
19705 
19706     /**
19707      * <p>Trigger the scrollbars to draw. When invoked this method starts an
19708      * animation to fade the scrollbars out after a default delay. If a subclass
19709      * provides animated scrolling, the start delay should equal the duration
19710      * of the scrolling animation.</p>
19711      *
19712      * <p>The animation starts only if at least one of the scrollbars is
19713      * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
19714      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
19715      * this method returns true, and false otherwise. If the animation is
19716      * started, this method calls {@link #invalidate()}; in that case the
19717      * caller should not call {@link #invalidate()}.</p>
19718      *
19719      * <p>This method should be invoked every time a subclass directly updates
19720      * the scroll parameters.</p>
19721      *
19722      * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
19723      * and {@link #scrollTo(int, int)}.</p>
19724      *
19725      * @return true if the animation is played, false otherwise
19726      *
19727      * @see #awakenScrollBars(int)
19728      * @see #scrollBy(int, int)
19729      * @see #scrollTo(int, int)
19730      * @see #isHorizontalScrollBarEnabled()
19731      * @see #isVerticalScrollBarEnabled()
19732      * @see #setHorizontalScrollBarEnabled(boolean)
19733      * @see #setVerticalScrollBarEnabled(boolean)
19734      */
awakenScrollBars()19735     protected boolean awakenScrollBars() {
19736         return mScrollCache != null &&
19737                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
19738     }
19739 
19740     /**
19741      * Trigger the scrollbars to draw.
19742      * This method differs from awakenScrollBars() only in its default duration.
19743      * initialAwakenScrollBars() will show the scroll bars for longer than
19744      * usual to give the user more of a chance to notice them.
19745      *
19746      * @return true if the animation is played, false otherwise.
19747      */
initialAwakenScrollBars()19748     private boolean initialAwakenScrollBars() {
19749         return mScrollCache != null &&
19750                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
19751     }
19752 
19753     /**
19754      * <p>
19755      * Trigger the scrollbars to draw. When invoked this method starts an
19756      * animation to fade the scrollbars out after a fixed delay. If a subclass
19757      * provides animated scrolling, the start delay should equal the duration of
19758      * the scrolling animation.
19759      * </p>
19760      *
19761      * <p>
19762      * The animation starts only if at least one of the scrollbars is enabled,
19763      * as specified by {@link #isHorizontalScrollBarEnabled()} and
19764      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
19765      * this method returns true, and false otherwise. If the animation is
19766      * started, this method calls {@link #invalidate()}; in that case the caller
19767      * should not call {@link #invalidate()}.
19768      * </p>
19769      *
19770      * <p>
19771      * This method should be invoked every time a subclass directly updates the
19772      * scroll parameters.
19773      * </p>
19774      *
19775      * @param startDelay the delay, in milliseconds, after which the animation
19776      *        should start; when the delay is 0, the animation starts
19777      *        immediately
19778      * @return true if the animation is played, false otherwise
19779      *
19780      * @see #scrollBy(int, int)
19781      * @see #scrollTo(int, int)
19782      * @see #isHorizontalScrollBarEnabled()
19783      * @see #isVerticalScrollBarEnabled()
19784      * @see #setHorizontalScrollBarEnabled(boolean)
19785      * @see #setVerticalScrollBarEnabled(boolean)
19786      */
awakenScrollBars(int startDelay)19787     protected boolean awakenScrollBars(int startDelay) {
19788         return awakenScrollBars(startDelay, true);
19789     }
19790 
19791     /**
19792      * <p>
19793      * Trigger the scrollbars to draw. When invoked this method starts an
19794      * animation to fade the scrollbars out after a fixed delay. If a subclass
19795      * provides animated scrolling, the start delay should equal the duration of
19796      * the scrolling animation.
19797      * </p>
19798      *
19799      * <p>
19800      * The animation starts only if at least one of the scrollbars is enabled,
19801      * as specified by {@link #isHorizontalScrollBarEnabled()} and
19802      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
19803      * this method returns true, and false otherwise. If the animation is
19804      * started, this method calls {@link #invalidate()} if the invalidate parameter
19805      * is set to true; in that case the caller
19806      * should not call {@link #invalidate()}.
19807      * </p>
19808      *
19809      * <p>
19810      * This method should be invoked every time a subclass directly updates the
19811      * scroll parameters.
19812      * </p>
19813      *
19814      * @param startDelay the delay, in milliseconds, after which the animation
19815      *        should start; when the delay is 0, the animation starts
19816      *        immediately
19817      *
19818      * @param invalidate Whether this method should call invalidate
19819      *
19820      * @return true if the animation is played, false otherwise
19821      *
19822      * @see #scrollBy(int, int)
19823      * @see #scrollTo(int, int)
19824      * @see #isHorizontalScrollBarEnabled()
19825      * @see #isVerticalScrollBarEnabled()
19826      * @see #setHorizontalScrollBarEnabled(boolean)
19827      * @see #setVerticalScrollBarEnabled(boolean)
19828      */
awakenScrollBars(int startDelay, boolean invalidate)19829     protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
19830         final ScrollabilityCache scrollCache = mScrollCache;
19831 
19832         if (scrollCache == null || !scrollCache.fadeScrollBars) {
19833             return false;
19834         }
19835 
19836         if (scrollCache.scrollBar == null) {
19837             scrollCache.scrollBar = new ScrollBarDrawable();
19838             scrollCache.scrollBar.setState(getDrawableState());
19839             scrollCache.scrollBar.setCallback(this);
19840         }
19841 
19842         if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
19843 
19844             if (invalidate) {
19845                 // Invalidate to show the scrollbars
19846                 postInvalidateOnAnimation();
19847             }
19848 
19849             if (scrollCache.state == ScrollabilityCache.OFF) {
19850                 // FIXME: this is copied from WindowManagerService.
19851                 // We should get this value from the system when it
19852                 // is possible to do so.
19853                 final int KEY_REPEAT_FIRST_DELAY = 750;
19854                 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
19855             }
19856 
19857             // Tell mScrollCache when we should start fading. This may
19858             // extend the fade start time if one was already scheduled
19859             long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
19860             scrollCache.fadeStartTime = fadeStartTime;
19861             scrollCache.state = ScrollabilityCache.ON;
19862 
19863             // Schedule our fader to run, unscheduling any old ones first
19864             if (mAttachInfo != null) {
19865                 mAttachInfo.mHandler.removeCallbacks(scrollCache);
19866                 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
19867             }
19868 
19869             return true;
19870         }
19871 
19872         return false;
19873     }
19874 
19875     /**
19876      * Do not invalidate views which are not visible and which are not running an animation. They
19877      * will not get drawn and they should not set dirty flags as if they will be drawn
19878      */
skipInvalidate()19879     private boolean skipInvalidate() {
19880         return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
19881                 (!(mParent instanceof ViewGroup) ||
19882                         !((ViewGroup) mParent).isViewTransitioning(this));
19883     }
19884 
19885     /**
19886      * Mark the area defined by dirty as needing to be drawn. If the view is
19887      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
19888      * point in the future.
19889      * <p>
19890      * This must be called from a UI thread. To call from a non-UI thread, call
19891      * {@link #postInvalidate()}.
19892      * <p>
19893      * <b>WARNING:</b> In API 19 and below, this method may be destructive to
19894      * {@code dirty}.
19895      *
19896      * @param dirty the rectangle representing the bounds of the dirty region
19897      *
19898      * @deprecated The switch to hardware accelerated rendering in API 14 reduced
19899      * the importance of the dirty rectangle. In API 21 the given rectangle is
19900      * ignored entirely in favor of an internally-calculated area instead.
19901      * Because of this, clients are encouraged to just call {@link #invalidate()}.
19902      */
19903     @Deprecated
invalidate(Rect dirty)19904     public void invalidate(Rect dirty) {
19905         final int scrollX = mScrollX;
19906         final int scrollY = mScrollY;
19907         invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
19908                 dirty.right - scrollX, dirty.bottom - scrollY, true, false);
19909     }
19910 
19911     /**
19912      * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
19913      * coordinates of the dirty rect are relative to the view. If the view is
19914      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
19915      * point in the future.
19916      * <p>
19917      * This must be called from a UI thread. To call from a non-UI thread, call
19918      * {@link #postInvalidate()}.
19919      *
19920      * @param l the left position of the dirty region
19921      * @param t the top position of the dirty region
19922      * @param r the right position of the dirty region
19923      * @param b the bottom position of the dirty region
19924      *
19925      * @deprecated The switch to hardware accelerated rendering in API 14 reduced
19926      * the importance of the dirty rectangle. In API 21 the given rectangle is
19927      * ignored entirely in favor of an internally-calculated area instead.
19928      * Because of this, clients are encouraged to just call {@link #invalidate()}.
19929      */
19930     @Deprecated
invalidate(int l, int t, int r, int b)19931     public void invalidate(int l, int t, int r, int b) {
19932         final int scrollX = mScrollX;
19933         final int scrollY = mScrollY;
19934         invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
19935     }
19936 
19937     /**
19938      * Invalidate the whole view. If the view is visible,
19939      * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
19940      * the future.
19941      * <p>
19942      * This must be called from a UI thread. To call from a non-UI thread, call
19943      * {@link #postInvalidate()}.
19944      */
invalidate()19945     public void invalidate() {
19946         invalidate(true);
19947     }
19948 
19949     /**
19950      * This is where the invalidate() work actually happens. A full invalidate()
19951      * causes the drawing cache to be invalidated, but this function can be
19952      * called with invalidateCache set to false to skip that invalidation step
19953      * for cases that do not need it (for example, a component that remains at
19954      * the same dimensions with the same content).
19955      *
19956      * @param invalidateCache Whether the drawing cache for this view should be
19957      *            invalidated as well. This is usually true for a full
19958      *            invalidate, but may be set to false if the View's contents or
19959      *            dimensions have not changed.
19960      * @hide
19961      */
19962     @UnsupportedAppUsage
invalidate(boolean invalidateCache)19963     public void invalidate(boolean invalidateCache) {
19964         invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
19965     }
19966 
invalidateInternal(int l, int t, int r, int b, boolean invalidateCache, boolean fullInvalidate)19967     void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
19968             boolean fullInvalidate) {
19969         if (mGhostView != null) {
19970             mGhostView.invalidate(true);
19971             return;
19972         }
19973 
19974         if (skipInvalidate()) {
19975             return;
19976         }
19977 
19978         // Reset content capture caches
19979         mPrivateFlags4 &= ~PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK;
19980         mContentCaptureSessionCached = false;
19981 
19982         if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
19983                 || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
19984                 || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
19985                 || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
19986             if (fullInvalidate) {
19987                 mLastIsOpaque = isOpaque();
19988                 mPrivateFlags &= ~PFLAG_DRAWN;
19989             }
19990 
19991             mPrivateFlags |= PFLAG_DIRTY;
19992 
19993             if (invalidateCache) {
19994                 mPrivateFlags |= PFLAG_INVALIDATED;
19995                 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
19996             }
19997 
19998             // Propagate the damage rectangle to the parent view.
19999             final AttachInfo ai = mAttachInfo;
20000             final ViewParent p = mParent;
20001             if (p != null && ai != null && l < r && t < b) {
20002                 final Rect damage = ai.mTmpInvalRect;
20003                 damage.set(l, t, r, b);
20004                 p.invalidateChild(this, damage);
20005             }
20006 
20007             // Damage the entire projection receiver, if necessary.
20008             if (mBackground != null && mBackground.isProjected()) {
20009                 final View receiver = getProjectionReceiver();
20010                 if (receiver != null) {
20011                     receiver.damageInParent();
20012                 }
20013             }
20014         }
20015     }
20016 
20017     /**
20018      * @return this view's projection receiver, or {@code null} if none exists
20019      */
getProjectionReceiver()20020     private View getProjectionReceiver() {
20021         ViewParent p = getParent();
20022         while (p != null && p instanceof View) {
20023             final View v = (View) p;
20024             if (v.isProjectionReceiver()) {
20025                 return v;
20026             }
20027             p = p.getParent();
20028         }
20029 
20030         return null;
20031     }
20032 
20033     /**
20034      * @return whether the view is a projection receiver
20035      */
isProjectionReceiver()20036     private boolean isProjectionReceiver() {
20037         return mBackground != null;
20038     }
20039 
20040     /**
20041      * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
20042      * set any flags or handle all of the cases handled by the default invalidation methods.
20043      * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
20044      * dirty rect. This method calls into fast invalidation methods in ViewGroup that
20045      * walk up the hierarchy, transforming the dirty rect as necessary.
20046      *
20047      * The method also handles normal invalidation logic if display list properties are not
20048      * being used in this view. The invalidateParent and forceRedraw flags are used by that
20049      * backup approach, to handle these cases used in the various property-setting methods.
20050      *
20051      * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
20052      * are not being used in this view
20053      * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
20054      * list properties are not being used in this view
20055      */
20056     @UnsupportedAppUsage
invalidateViewProperty(boolean invalidateParent, boolean forceRedraw)20057     void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
20058         if (!isHardwareAccelerated()
20059                 || !mRenderNode.hasDisplayList()
20060                 || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
20061             if (invalidateParent) {
20062                 invalidateParentCaches();
20063             }
20064             if (forceRedraw) {
20065                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
20066             }
20067             invalidate(false);
20068         } else {
20069             damageInParent();
20070         }
20071     }
20072 
20073     /**
20074      * Tells the parent view to damage this view's bounds.
20075      *
20076      * @hide
20077      */
damageInParent()20078     protected void damageInParent() {
20079         if (mParent != null && mAttachInfo != null) {
20080             mParent.onDescendantInvalidated(this, this);
20081         }
20082     }
20083 
20084     /**
20085      * Used to indicate that the parent of this view should clear its caches. This functionality
20086      * is used to force the parent to rebuild its display list (when hardware-accelerated),
20087      * which is necessary when various parent-managed properties of the view change, such as
20088      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
20089      * clears the parent caches and does not causes an invalidate event.
20090      *
20091      * @hide
20092      */
20093     @UnsupportedAppUsage
invalidateParentCaches()20094     protected void invalidateParentCaches() {
20095         if (mParent instanceof View) {
20096             ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
20097         }
20098     }
20099 
20100     /**
20101      * Used to indicate that the parent of this view should be invalidated. This functionality
20102      * is used to force the parent to rebuild its display list (when hardware-accelerated),
20103      * which is necessary when various parent-managed properties of the view change, such as
20104      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
20105      * an invalidation event to the parent.
20106      *
20107      * @hide
20108      */
20109     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
invalidateParentIfNeeded()20110     protected void invalidateParentIfNeeded() {
20111         if (isHardwareAccelerated() && mParent instanceof View) {
20112             ((View) mParent).invalidate(true);
20113         }
20114     }
20115 
20116     /**
20117      * @hide
20118      */
invalidateParentIfNeededAndWasQuickRejected()20119     protected void invalidateParentIfNeededAndWasQuickRejected() {
20120         if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
20121             // View was rejected last time it was drawn by its parent; this may have changed
20122             invalidateParentIfNeeded();
20123         }
20124     }
20125 
20126     /**
20127      * Indicates whether this View is opaque. An opaque View guarantees that it will
20128      * draw all the pixels overlapping its bounds using a fully opaque color.
20129      *
20130      * Subclasses of View should override this method whenever possible to indicate
20131      * whether an instance is opaque. Opaque Views are treated in a special way by
20132      * the View hierarchy, possibly allowing it to perform optimizations during
20133      * invalidate/draw passes.
20134      *
20135      * @return True if this View is guaranteed to be fully opaque, false otherwise.
20136      */
20137     @ViewDebug.ExportedProperty(category = "drawing")
isOpaque()20138     public boolean isOpaque() {
20139         return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
20140                 getFinalAlpha() >= 1.0f;
20141     }
20142 
20143     /**
20144      * @hide
20145      */
20146     @UnsupportedAppUsage
computeOpaqueFlags()20147     protected void computeOpaqueFlags() {
20148         // Opaque if:
20149         //   - Has a background
20150         //   - Background is opaque
20151         //   - Doesn't have scrollbars or scrollbars overlay
20152 
20153         if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
20154             mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
20155         } else {
20156             mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
20157         }
20158 
20159         final int flags = mViewFlags;
20160         if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
20161                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
20162                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
20163             mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
20164         } else {
20165             mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
20166         }
20167     }
20168 
20169     /**
20170      * @hide
20171      */
hasOpaqueScrollbars()20172     protected boolean hasOpaqueScrollbars() {
20173         return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
20174     }
20175 
20176     /**
20177      * @return A handler associated with the thread running the View. This
20178      * handler can be used to pump events in the UI events queue.
20179      */
getHandler()20180     public Handler getHandler() {
20181         final AttachInfo attachInfo = mAttachInfo;
20182         if (attachInfo != null) {
20183             return attachInfo.mHandler;
20184         }
20185         return null;
20186     }
20187 
20188     /**
20189      * Returns the queue of runnable for this view.
20190      *
20191      * @return the queue of runnables for this view
20192      */
getRunQueue()20193     private HandlerActionQueue getRunQueue() {
20194         if (mRunQueue == null) {
20195             mRunQueue = new HandlerActionQueue();
20196         }
20197         return mRunQueue;
20198     }
20199 
20200     /**
20201      * Gets the view root associated with the View.
20202      * @return The view root, or null if none.
20203      * @hide
20204      */
20205     @UnsupportedAppUsage
getViewRootImpl()20206     public ViewRootImpl getViewRootImpl() {
20207         if (mAttachInfo != null) {
20208             return mAttachInfo.mViewRootImpl;
20209         }
20210         return null;
20211     }
20212 
20213     /**
20214      * @hide
20215      */
20216     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getThreadedRenderer()20217     public ThreadedRenderer getThreadedRenderer() {
20218         return mAttachInfo != null ? mAttachInfo.mThreadedRenderer : null;
20219     }
20220 
20221     /**
20222      * <p>Causes the Runnable to be added to the message queue.
20223      * The runnable will be run on the user interface thread.</p>
20224      *
20225      * @param action The Runnable that will be executed.
20226      *
20227      * @return Returns true if the Runnable was successfully placed in to the
20228      *         message queue.  Returns false on failure, usually because the
20229      *         looper processing the message queue is exiting.
20230      *
20231      * @see #postDelayed
20232      * @see #removeCallbacks
20233      */
post(Runnable action)20234     public boolean post(Runnable action) {
20235         final AttachInfo attachInfo = mAttachInfo;
20236         if (attachInfo != null) {
20237             return attachInfo.mHandler.post(action);
20238         }
20239 
20240         // Postpone the runnable until we know on which thread it needs to run.
20241         // Assume that the runnable will be successfully placed after attach.
20242         getRunQueue().post(action);
20243         return true;
20244     }
20245 
20246     /**
20247      * <p>Causes the Runnable to be added to the message queue, to be run
20248      * after the specified amount of time elapses.
20249      * The runnable will be run on the user interface thread.</p>
20250      *
20251      * @param action The Runnable that will be executed.
20252      * @param delayMillis The delay (in milliseconds) until the Runnable
20253      *        will be executed.
20254      *
20255      * @return true if the Runnable was successfully placed in to the
20256      *         message queue.  Returns false on failure, usually because the
20257      *         looper processing the message queue is exiting.  Note that a
20258      *         result of true does not mean the Runnable will be processed --
20259      *         if the looper is quit before the delivery time of the message
20260      *         occurs then the message will be dropped.
20261      *
20262      * @see #post
20263      * @see #removeCallbacks
20264      */
postDelayed(Runnable action, long delayMillis)20265     public boolean postDelayed(Runnable action, long delayMillis) {
20266         final AttachInfo attachInfo = mAttachInfo;
20267         if (attachInfo != null) {
20268             return attachInfo.mHandler.postDelayed(action, delayMillis);
20269         }
20270 
20271         // Postpone the runnable until we know on which thread it needs to run.
20272         // Assume that the runnable will be successfully placed after attach.
20273         getRunQueue().postDelayed(action, delayMillis);
20274         return true;
20275     }
20276 
20277     /**
20278      * <p>Causes the Runnable to execute on the next animation time step.
20279      * The runnable will be run on the user interface thread.</p>
20280      *
20281      * @param action The Runnable that will be executed.
20282      *
20283      * @see #postOnAnimationDelayed
20284      * @see #removeCallbacks
20285      */
postOnAnimation(Runnable action)20286     public void postOnAnimation(Runnable action) {
20287         final AttachInfo attachInfo = mAttachInfo;
20288         if (attachInfo != null) {
20289             attachInfo.mViewRootImpl.mChoreographer.postCallback(
20290                     Choreographer.CALLBACK_ANIMATION, action, null);
20291         } else {
20292             // Postpone the runnable until we know
20293             // on which thread it needs to run.
20294             getRunQueue().post(action);
20295         }
20296     }
20297 
20298     /**
20299      * <p>Causes the Runnable to execute on the next animation time step,
20300      * after the specified amount of time elapses.
20301      * The runnable will be run on the user interface thread.</p>
20302      *
20303      * @param action The Runnable that will be executed.
20304      * @param delayMillis The delay (in milliseconds) until the Runnable
20305      *        will be executed.
20306      *
20307      * @see #postOnAnimation
20308      * @see #removeCallbacks
20309      */
postOnAnimationDelayed(Runnable action, long delayMillis)20310     public void postOnAnimationDelayed(Runnable action, long delayMillis) {
20311         final AttachInfo attachInfo = mAttachInfo;
20312         if (attachInfo != null) {
20313             attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
20314                     Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
20315         } else {
20316             // Postpone the runnable until we know
20317             // on which thread it needs to run.
20318             getRunQueue().postDelayed(action, delayMillis);
20319         }
20320     }
20321 
20322     /**
20323      * <p>Removes the specified Runnable from the message queue.</p>
20324      *
20325      * @param action The Runnable to remove from the message handling queue
20326      *
20327      * @return true if this view could ask the Handler to remove the Runnable,
20328      *         false otherwise. When the returned value is true, the Runnable
20329      *         may or may not have been actually removed from the message queue
20330      *         (for instance, if the Runnable was not in the queue already.)
20331      *
20332      * @see #post
20333      * @see #postDelayed
20334      * @see #postOnAnimation
20335      * @see #postOnAnimationDelayed
20336      */
removeCallbacks(Runnable action)20337     public boolean removeCallbacks(Runnable action) {
20338         if (action != null) {
20339             final AttachInfo attachInfo = mAttachInfo;
20340             if (attachInfo != null) {
20341                 attachInfo.mHandler.removeCallbacks(action);
20342                 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
20343                         Choreographer.CALLBACK_ANIMATION, action, null);
20344             }
20345             getRunQueue().removeCallbacks(action);
20346         }
20347         return true;
20348     }
20349 
20350     /**
20351      * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
20352      * Use this to invalidate the View from a non-UI thread.</p>
20353      *
20354      * <p>This method can be invoked from outside of the UI thread
20355      * only when this View is attached to a window.</p>
20356      *
20357      * @see #invalidate()
20358      * @see #postInvalidateDelayed(long)
20359      */
postInvalidate()20360     public void postInvalidate() {
20361         postInvalidateDelayed(0);
20362     }
20363 
20364     /**
20365      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
20366      * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
20367      *
20368      * <p>This method can be invoked from outside of the UI thread
20369      * only when this View is attached to a window.</p>
20370      *
20371      * @param left The left coordinate of the rectangle to invalidate.
20372      * @param top The top coordinate of the rectangle to invalidate.
20373      * @param right The right coordinate of the rectangle to invalidate.
20374      * @param bottom The bottom coordinate of the rectangle to invalidate.
20375      *
20376      * @see #invalidate(int, int, int, int)
20377      * @see #invalidate(Rect)
20378      * @see #postInvalidateDelayed(long, int, int, int, int)
20379      */
postInvalidate(int left, int top, int right, int bottom)20380     public void postInvalidate(int left, int top, int right, int bottom) {
20381         postInvalidateDelayed(0, left, top, right, bottom);
20382     }
20383 
20384     /**
20385      * <p>Cause an invalidate to happen on a subsequent cycle through the event
20386      * loop. Waits for the specified amount of time.</p>
20387      *
20388      * <p>This method can be invoked from outside of the UI thread
20389      * only when this View is attached to a window.</p>
20390      *
20391      * @param delayMilliseconds the duration in milliseconds to delay the
20392      *         invalidation by
20393      *
20394      * @see #invalidate()
20395      * @see #postInvalidate()
20396      */
postInvalidateDelayed(long delayMilliseconds)20397     public void postInvalidateDelayed(long delayMilliseconds) {
20398         // We try only with the AttachInfo because there's no point in invalidating
20399         // if we are not attached to our window
20400         final AttachInfo attachInfo = mAttachInfo;
20401         if (attachInfo != null) {
20402             attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
20403         }
20404     }
20405 
20406     /**
20407      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
20408      * through the event loop. Waits for the specified amount of time.</p>
20409      *
20410      * <p>This method can be invoked from outside of the UI thread
20411      * only when this View is attached to a window.</p>
20412      *
20413      * @param delayMilliseconds the duration in milliseconds to delay the
20414      *         invalidation by
20415      * @param left The left coordinate of the rectangle to invalidate.
20416      * @param top The top coordinate of the rectangle to invalidate.
20417      * @param right The right coordinate of the rectangle to invalidate.
20418      * @param bottom The bottom coordinate of the rectangle to invalidate.
20419      *
20420      * @see #invalidate(int, int, int, int)
20421      * @see #invalidate(Rect)
20422      * @see #postInvalidate(int, int, int, int)
20423      */
postInvalidateDelayed(long delayMilliseconds, int left, int top, int right, int bottom)20424     public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
20425             int right, int bottom) {
20426 
20427         // We try only with the AttachInfo because there's no point in invalidating
20428         // if we are not attached to our window
20429         final AttachInfo attachInfo = mAttachInfo;
20430         if (attachInfo != null) {
20431             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
20432             info.target = this;
20433             info.left = left;
20434             info.top = top;
20435             info.right = right;
20436             info.bottom = bottom;
20437 
20438             attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
20439         }
20440     }
20441 
20442     /**
20443      * <p>Cause an invalidate to happen on the next animation time step, typically the
20444      * next display frame.</p>
20445      *
20446      * <p>This method can be invoked from outside of the UI thread
20447      * only when this View is attached to a window.</p>
20448      *
20449      * @see #invalidate()
20450      */
postInvalidateOnAnimation()20451     public void postInvalidateOnAnimation() {
20452         // We try only with the AttachInfo because there's no point in invalidating
20453         // if we are not attached to our window
20454         final AttachInfo attachInfo = mAttachInfo;
20455         if (attachInfo != null) {
20456             attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
20457         }
20458     }
20459 
20460     /**
20461      * <p>Cause an invalidate of the specified area to happen on the next animation
20462      * time step, typically the next display frame.</p>
20463      *
20464      * <p>This method can be invoked from outside of the UI thread
20465      * only when this View is attached to a window.</p>
20466      *
20467      * @param left The left coordinate of the rectangle to invalidate.
20468      * @param top The top coordinate of the rectangle to invalidate.
20469      * @param right The right coordinate of the rectangle to invalidate.
20470      * @param bottom The bottom coordinate of the rectangle to invalidate.
20471      *
20472      * @see #invalidate(int, int, int, int)
20473      * @see #invalidate(Rect)
20474      */
postInvalidateOnAnimation(int left, int top, int right, int bottom)20475     public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
20476         // We try only with the AttachInfo because there's no point in invalidating
20477         // if we are not attached to our window
20478         final AttachInfo attachInfo = mAttachInfo;
20479         if (attachInfo != null) {
20480             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
20481             info.target = this;
20482             info.left = left;
20483             info.top = top;
20484             info.right = right;
20485             info.bottom = bottom;
20486 
20487             attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
20488         }
20489     }
20490 
20491     /**
20492      * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
20493      * This event is sent at most once every
20494      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
20495      */
postSendViewScrolledAccessibilityEventCallback(int dx, int dy)20496     private void postSendViewScrolledAccessibilityEventCallback(int dx, int dy) {
20497         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
20498             AccessibilityEvent event =
20499                     AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_SCROLLED);
20500             event.setScrollDeltaX(dx);
20501             event.setScrollDeltaY(dy);
20502             sendAccessibilityEventUnchecked(event);
20503         }
20504     }
20505 
20506     /**
20507      * Called by a parent to request that a child update its values for mScrollX
20508      * and mScrollY if necessary. This will typically be done if the child is
20509      * animating a scroll using a {@link android.widget.Scroller Scroller}
20510      * object.
20511      */
computeScroll()20512     public void computeScroll() {
20513     }
20514 
20515     /**
20516      * <p>Indicate whether the horizontal edges are faded when the view is
20517      * scrolled horizontally.</p>
20518      *
20519      * @return true if the horizontal edges should are faded on scroll, false
20520      *         otherwise
20521      *
20522      * @see #setHorizontalFadingEdgeEnabled(boolean)
20523      *
20524      * @attr ref android.R.styleable#View_requiresFadingEdge
20525      */
isHorizontalFadingEdgeEnabled()20526     public boolean isHorizontalFadingEdgeEnabled() {
20527         return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
20528     }
20529 
20530     /**
20531      * <p>Define whether the horizontal edges should be faded when this view
20532      * is scrolled horizontally.</p>
20533      *
20534      * @param horizontalFadingEdgeEnabled true if the horizontal edges should
20535      *                                    be faded when the view is scrolled
20536      *                                    horizontally
20537      *
20538      * @see #isHorizontalFadingEdgeEnabled()
20539      *
20540      * @attr ref android.R.styleable#View_requiresFadingEdge
20541      */
setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled)20542     public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
20543         if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
20544             if (horizontalFadingEdgeEnabled) {
20545                 initScrollCache();
20546             }
20547 
20548             mViewFlags ^= FADING_EDGE_HORIZONTAL;
20549         }
20550     }
20551 
20552     /**
20553      * <p>Indicate whether the vertical edges are faded when the view is
20554      * scrolled horizontally.</p>
20555      *
20556      * @return true if the vertical edges should are faded on scroll, false
20557      *         otherwise
20558      *
20559      * @see #setVerticalFadingEdgeEnabled(boolean)
20560      *
20561      * @attr ref android.R.styleable#View_requiresFadingEdge
20562      */
isVerticalFadingEdgeEnabled()20563     public boolean isVerticalFadingEdgeEnabled() {
20564         return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
20565     }
20566 
20567     /**
20568      * <p>Define whether the vertical edges should be faded when this view
20569      * is scrolled vertically.</p>
20570      *
20571      * @param verticalFadingEdgeEnabled true if the vertical edges should
20572      *                                  be faded when the view is scrolled
20573      *                                  vertically
20574      *
20575      * @see #isVerticalFadingEdgeEnabled()
20576      *
20577      * @attr ref android.R.styleable#View_requiresFadingEdge
20578      */
setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled)20579     public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
20580         if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
20581             if (verticalFadingEdgeEnabled) {
20582                 initScrollCache();
20583             }
20584 
20585             mViewFlags ^= FADING_EDGE_VERTICAL;
20586         }
20587     }
20588 
20589     /**
20590      * Get the fading edge flags, used for inspection.
20591      *
20592      * @return One of {@link #FADING_EDGE_NONE}, {@link #FADING_EDGE_VERTICAL},
20593      *         or {@link #FADING_EDGE_HORIZONTAL}
20594      * @hide
20595      */
20596     @InspectableProperty(name = "requiresFadingEdge", flagMapping = {
20597             @FlagEntry(target = FADING_EDGE_NONE, mask = FADING_EDGE_MASK, name = "none"),
20598             @FlagEntry(target = FADING_EDGE_VERTICAL, name = "vertical"),
20599             @FlagEntry(target = FADING_EDGE_HORIZONTAL, name = "horizontal")
20600     })
getFadingEdge()20601     public int getFadingEdge() {
20602         return mViewFlags & FADING_EDGE_MASK;
20603     }
20604 
20605     /**
20606      * Get the fading edge length, used for inspection
20607      *
20608      * @return The fading edge length or 0
20609      * @hide
20610      */
20611     @InspectableProperty
getFadingEdgeLength()20612     public int getFadingEdgeLength() {
20613         if (mScrollCache != null && (mViewFlags & FADING_EDGE_MASK) != FADING_EDGE_NONE) {
20614             return mScrollCache.fadingEdgeLength;
20615         }
20616         return 0;
20617     }
20618 
20619     /**
20620      * Returns the strength, or intensity, of the top faded edge. The strength is
20621      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
20622      * returns 0.0 or 1.0 but no value in between.
20623      *
20624      * Subclasses should override this method to provide a smoother fade transition
20625      * when scrolling occurs.
20626      *
20627      * @return the intensity of the top fade as a float between 0.0f and 1.0f
20628      */
getTopFadingEdgeStrength()20629     protected float getTopFadingEdgeStrength() {
20630         return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
20631     }
20632 
20633     /**
20634      * Returns the strength, or intensity, of the bottom faded edge. The strength is
20635      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
20636      * returns 0.0 or 1.0 but no value in between.
20637      *
20638      * Subclasses should override this method to provide a smoother fade transition
20639      * when scrolling occurs.
20640      *
20641      * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
20642      */
getBottomFadingEdgeStrength()20643     protected float getBottomFadingEdgeStrength() {
20644         return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
20645                 computeVerticalScrollRange() ? 1.0f : 0.0f;
20646     }
20647 
20648     /**
20649      * Returns the strength, or intensity, of the left faded edge. The strength is
20650      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
20651      * returns 0.0 or 1.0 but no value in between.
20652      *
20653      * Subclasses should override this method to provide a smoother fade transition
20654      * when scrolling occurs.
20655      *
20656      * @return the intensity of the left fade as a float between 0.0f and 1.0f
20657      */
getLeftFadingEdgeStrength()20658     protected float getLeftFadingEdgeStrength() {
20659         return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
20660     }
20661 
20662     /**
20663      * Returns the strength, or intensity, of the right faded edge. The strength is
20664      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
20665      * returns 0.0 or 1.0 but no value in between.
20666      *
20667      * Subclasses should override this method to provide a smoother fade transition
20668      * when scrolling occurs.
20669      *
20670      * @return the intensity of the right fade as a float between 0.0f and 1.0f
20671      */
getRightFadingEdgeStrength()20672     protected float getRightFadingEdgeStrength() {
20673         return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
20674                 computeHorizontalScrollRange() ? 1.0f : 0.0f;
20675     }
20676 
20677     /**
20678      * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
20679      * scrollbar is not drawn by default.</p>
20680      *
20681      * @return true if the horizontal scrollbar should be painted, false
20682      *         otherwise
20683      *
20684      * @see #setHorizontalScrollBarEnabled(boolean)
20685      */
isHorizontalScrollBarEnabled()20686     public boolean isHorizontalScrollBarEnabled() {
20687         return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
20688     }
20689 
20690     /**
20691      * <p>Define whether the horizontal scrollbar should be drawn or not. The
20692      * scrollbar is not drawn by default.</p>
20693      *
20694      * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
20695      *                                   be painted
20696      *
20697      * @see #isHorizontalScrollBarEnabled()
20698      */
setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled)20699     public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
20700         if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
20701             mViewFlags ^= SCROLLBARS_HORIZONTAL;
20702             computeOpaqueFlags();
20703             resolvePadding();
20704         }
20705     }
20706 
20707     /**
20708      * <p>Indicate whether the vertical scrollbar should be drawn or not. The
20709      * scrollbar is not drawn by default.</p>
20710      *
20711      * @return true if the vertical scrollbar should be painted, false
20712      *         otherwise
20713      *
20714      * @see #setVerticalScrollBarEnabled(boolean)
20715      */
isVerticalScrollBarEnabled()20716     public boolean isVerticalScrollBarEnabled() {
20717         return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
20718     }
20719 
20720     /**
20721      * <p>Define whether the vertical scrollbar should be drawn or not. The
20722      * scrollbar is not drawn by default.</p>
20723      *
20724      * @param verticalScrollBarEnabled true if the vertical scrollbar should
20725      *                                 be painted
20726      *
20727      * @see #isVerticalScrollBarEnabled()
20728      */
setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled)20729     public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
20730         if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
20731             mViewFlags ^= SCROLLBARS_VERTICAL;
20732             computeOpaqueFlags();
20733             resolvePadding();
20734         }
20735     }
20736 
20737     /**
20738      * @hide
20739      */
20740     @UnsupportedAppUsage
recomputePadding()20741     protected void recomputePadding() {
20742         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
20743     }
20744 
20745     /**
20746      * Define whether scrollbars will fade when the view is not scrolling.
20747      *
20748      * @param fadeScrollbars whether to enable fading
20749      *
20750      * @attr ref android.R.styleable#View_fadeScrollbars
20751      */
setScrollbarFadingEnabled(boolean fadeScrollbars)20752     public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
20753         initScrollCache();
20754         final ScrollabilityCache scrollabilityCache = mScrollCache;
20755         scrollabilityCache.fadeScrollBars = fadeScrollbars;
20756         if (fadeScrollbars) {
20757             scrollabilityCache.state = ScrollabilityCache.OFF;
20758         } else {
20759             scrollabilityCache.state = ScrollabilityCache.ON;
20760         }
20761     }
20762 
20763     /**
20764      *
20765      * Returns true if scrollbars will fade when this view is not scrolling
20766      *
20767      * @return true if scrollbar fading is enabled
20768      *
20769      * @attr ref android.R.styleable#View_fadeScrollbars
20770      */
isScrollbarFadingEnabled()20771     public boolean isScrollbarFadingEnabled() {
20772         return mScrollCache != null && mScrollCache.fadeScrollBars;
20773     }
20774 
20775     /**
20776      *
20777      * Returns the delay before scrollbars fade.
20778      *
20779      * @return the delay before scrollbars fade
20780      *
20781      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
20782      */
20783     @InspectableProperty(name = "scrollbarDefaultDelayBeforeFade")
getScrollBarDefaultDelayBeforeFade()20784     public int getScrollBarDefaultDelayBeforeFade() {
20785         return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
20786                 mScrollCache.scrollBarDefaultDelayBeforeFade;
20787     }
20788 
20789     /**
20790      * Define the delay before scrollbars fade.
20791      *
20792      * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
20793      *
20794      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
20795      */
setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade)20796     public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
20797         getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
20798     }
20799 
20800     /**
20801      *
20802      * Returns the scrollbar fade duration.
20803      *
20804      * @return the scrollbar fade duration, in milliseconds
20805      *
20806      * @attr ref android.R.styleable#View_scrollbarFadeDuration
20807      */
20808     @InspectableProperty(name = "scrollbarFadeDuration")
getScrollBarFadeDuration()20809     public int getScrollBarFadeDuration() {
20810         return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
20811                 mScrollCache.scrollBarFadeDuration;
20812     }
20813 
20814     /**
20815      * Define the scrollbar fade duration.
20816      *
20817      * @param scrollBarFadeDuration - the scrollbar fade duration, in milliseconds
20818      *
20819      * @attr ref android.R.styleable#View_scrollbarFadeDuration
20820      */
setScrollBarFadeDuration(int scrollBarFadeDuration)20821     public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
20822         getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
20823     }
20824 
20825     /**
20826      *
20827      * Returns the scrollbar size.
20828      *
20829      * @return the scrollbar size
20830      *
20831      * @attr ref android.R.styleable#View_scrollbarSize
20832      */
20833     @InspectableProperty(name = "scrollbarSize")
getScrollBarSize()20834     public int getScrollBarSize() {
20835         return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
20836                 mScrollCache.scrollBarSize;
20837     }
20838 
20839     /**
20840      * Define the scrollbar size.
20841      *
20842      * @param scrollBarSize - the scrollbar size
20843      *
20844      * @attr ref android.R.styleable#View_scrollbarSize
20845      */
setScrollBarSize(int scrollBarSize)20846     public void setScrollBarSize(int scrollBarSize) {
20847         getScrollCache().scrollBarSize = scrollBarSize;
20848     }
20849 
20850     /**
20851      * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
20852      * inset. When inset, they add to the padding of the view. And the scrollbars
20853      * can be drawn inside the padding area or on the edge of the view. For example,
20854      * if a view has a background drawable and you want to draw the scrollbars
20855      * inside the padding specified by the drawable, you can use
20856      * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
20857      * appear at the edge of the view, ignoring the padding, then you can use
20858      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
20859      * @param style the style of the scrollbars. Should be one of
20860      * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
20861      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
20862      * @see #SCROLLBARS_INSIDE_OVERLAY
20863      * @see #SCROLLBARS_INSIDE_INSET
20864      * @see #SCROLLBARS_OUTSIDE_OVERLAY
20865      * @see #SCROLLBARS_OUTSIDE_INSET
20866      *
20867      * @attr ref android.R.styleable#View_scrollbarStyle
20868      */
setScrollBarStyle(@crollBarStyle int style)20869     public void setScrollBarStyle(@ScrollBarStyle int style) {
20870         if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
20871             mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
20872             computeOpaqueFlags();
20873             resolvePadding();
20874         }
20875     }
20876 
20877     /**
20878      * <p>Returns the current scrollbar style.</p>
20879      * @return the current scrollbar style
20880      * @see #SCROLLBARS_INSIDE_OVERLAY
20881      * @see #SCROLLBARS_INSIDE_INSET
20882      * @see #SCROLLBARS_OUTSIDE_OVERLAY
20883      * @see #SCROLLBARS_OUTSIDE_INSET
20884      *
20885      * @attr ref android.R.styleable#View_scrollbarStyle
20886      */
20887     @ViewDebug.ExportedProperty(mapping = {
20888             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
20889             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
20890             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
20891             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
20892     })
20893     @InspectableProperty(name = "scrollbarStyle", enumMapping = {
20894             @EnumEntry(value = SCROLLBARS_INSIDE_OVERLAY, name = "insideOverlay"),
20895             @EnumEntry(value = SCROLLBARS_INSIDE_INSET, name = "insideInset"),
20896             @EnumEntry(value = SCROLLBARS_OUTSIDE_OVERLAY, name = "outsideOverlay"),
20897             @EnumEntry(value = SCROLLBARS_OUTSIDE_INSET, name = "outsideInset")
20898     })
20899     @ScrollBarStyle
getScrollBarStyle()20900     public int getScrollBarStyle() {
20901         return mViewFlags & SCROLLBARS_STYLE_MASK;
20902     }
20903 
20904     /**
20905      * <p>Compute the horizontal range that the horizontal scrollbar
20906      * represents.</p>
20907      *
20908      * <p>The range is expressed in arbitrary units that must be the same as the
20909      * units used by {@link #computeHorizontalScrollExtent()} and
20910      * {@link #computeHorizontalScrollOffset()}.</p>
20911      *
20912      * <p>The default range is the drawing width of this view.</p>
20913      *
20914      * @return the total horizontal range represented by the horizontal
20915      *         scrollbar
20916      *
20917      * @see #computeHorizontalScrollExtent()
20918      * @see #computeHorizontalScrollOffset()
20919      */
computeHorizontalScrollRange()20920     protected int computeHorizontalScrollRange() {
20921         return getWidth();
20922     }
20923 
20924     /**
20925      * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
20926      * within the horizontal range. This value is used to compute the position
20927      * of the thumb within the scrollbar's track.</p>
20928      *
20929      * <p>The range is expressed in arbitrary units that must be the same as the
20930      * units used by {@link #computeHorizontalScrollRange()} and
20931      * {@link #computeHorizontalScrollExtent()}.</p>
20932      *
20933      * <p>The default offset is the scroll offset of this view.</p>
20934      *
20935      * @return the horizontal offset of the scrollbar's thumb
20936      *
20937      * @see #computeHorizontalScrollRange()
20938      * @see #computeHorizontalScrollExtent()
20939      */
computeHorizontalScrollOffset()20940     protected int computeHorizontalScrollOffset() {
20941         return mScrollX;
20942     }
20943 
20944     /**
20945      * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
20946      * within the horizontal range. This value is used to compute the length
20947      * of the thumb within the scrollbar's track.</p>
20948      *
20949      * <p>The range is expressed in arbitrary units that must be the same as the
20950      * units used by {@link #computeHorizontalScrollRange()} and
20951      * {@link #computeHorizontalScrollOffset()}.</p>
20952      *
20953      * <p>The default extent is the drawing width of this view.</p>
20954      *
20955      * @return the horizontal extent of the scrollbar's thumb
20956      *
20957      * @see #computeHorizontalScrollRange()
20958      * @see #computeHorizontalScrollOffset()
20959      */
computeHorizontalScrollExtent()20960     protected int computeHorizontalScrollExtent() {
20961         return getWidth();
20962     }
20963 
20964     /**
20965      * <p>Compute the vertical range that the vertical scrollbar represents.</p>
20966      *
20967      * <p>The range is expressed in arbitrary units that must be the same as the
20968      * units used by {@link #computeVerticalScrollExtent()} and
20969      * {@link #computeVerticalScrollOffset()}.</p>
20970      *
20971      * @return the total vertical range represented by the vertical scrollbar
20972      *
20973      * <p>The default range is the drawing height of this view.</p>
20974      *
20975      * @see #computeVerticalScrollExtent()
20976      * @see #computeVerticalScrollOffset()
20977      */
computeVerticalScrollRange()20978     protected int computeVerticalScrollRange() {
20979         return getHeight();
20980     }
20981 
20982     /**
20983      * <p>Compute the vertical offset of the vertical scrollbar's thumb
20984      * within the horizontal range. This value is used to compute the position
20985      * of the thumb within the scrollbar's track.</p>
20986      *
20987      * <p>The range is expressed in arbitrary units that must be the same as the
20988      * units used by {@link #computeVerticalScrollRange()} and
20989      * {@link #computeVerticalScrollExtent()}.</p>
20990      *
20991      * <p>The default offset is the scroll offset of this view.</p>
20992      *
20993      * @return the vertical offset of the scrollbar's thumb
20994      *
20995      * @see #computeVerticalScrollRange()
20996      * @see #computeVerticalScrollExtent()
20997      */
computeVerticalScrollOffset()20998     protected int computeVerticalScrollOffset() {
20999         return mScrollY;
21000     }
21001 
21002     /**
21003      * <p>Compute the vertical extent of the vertical scrollbar's thumb
21004      * within the vertical range. This value is used to compute the length
21005      * of the thumb within the scrollbar's track.</p>
21006      *
21007      * <p>The range is expressed in arbitrary units that must be the same as the
21008      * units used by {@link #computeVerticalScrollRange()} and
21009      * {@link #computeVerticalScrollOffset()}.</p>
21010      *
21011      * <p>The default extent is the drawing height of this view.</p>
21012      *
21013      * @return the vertical extent of the scrollbar's thumb
21014      *
21015      * @see #computeVerticalScrollRange()
21016      * @see #computeVerticalScrollOffset()
21017      */
computeVerticalScrollExtent()21018     protected int computeVerticalScrollExtent() {
21019         return getHeight();
21020     }
21021 
21022     /**
21023      * Check if this view can be scrolled horizontally in a certain direction.
21024      *
21025      * <p>This is without regard to whether the view is enabled or not, or if it will scroll
21026      * in response to user input or not.
21027      *
21028      * @param direction Negative to check scrolling left, positive to check scrolling right.
21029      * @return true if this view can be scrolled in the specified direction, false otherwise.
21030      */
canScrollHorizontally(int direction)21031     public boolean canScrollHorizontally(int direction) {
21032         final int offset = computeHorizontalScrollOffset();
21033         final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
21034         if (range == 0) return false;
21035         if (direction < 0) {
21036             return offset > 0;
21037         } else {
21038             return offset < range - 1;
21039         }
21040     }
21041 
21042     /**
21043      * Check if this view can be scrolled vertically in a certain direction.
21044      *
21045      * <p>This is without regard to whether the view is enabled or not, or if it will scroll
21046      * in response to user input or not.
21047      *
21048      * @param direction Negative to check scrolling up, positive to check scrolling down.
21049      * @return true if this view can be scrolled in the specified direction, false otherwise.
21050      */
canScrollVertically(int direction)21051     public boolean canScrollVertically(int direction) {
21052         final int offset = computeVerticalScrollOffset();
21053         final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
21054         if (range == 0) return false;
21055         if (direction < 0) {
21056             return offset > 0;
21057         } else {
21058             return offset < range - 1;
21059         }
21060     }
21061 
getScrollIndicatorBounds(@onNull Rect out)21062     void getScrollIndicatorBounds(@NonNull Rect out) {
21063         out.left = mScrollX;
21064         out.right = mScrollX + mRight - mLeft;
21065         out.top = mScrollY;
21066         out.bottom = mScrollY + mBottom - mTop;
21067     }
21068 
onDrawScrollIndicators(@onNull Canvas c)21069     private void onDrawScrollIndicators(@NonNull Canvas c) {
21070         if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
21071             // No scroll indicators enabled.
21072             return;
21073         }
21074 
21075         final Drawable dr = mScrollIndicatorDrawable;
21076         if (dr == null) {
21077             // Scroll indicators aren't supported here.
21078             return;
21079         }
21080 
21081         if (mAttachInfo == null) {
21082             // View is not attached.
21083             return;
21084         }
21085 
21086         final int h = dr.getIntrinsicHeight();
21087         final int w = dr.getIntrinsicWidth();
21088         final Rect rect = mAttachInfo.mTmpInvalRect;
21089         getScrollIndicatorBounds(rect);
21090 
21091         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
21092             final boolean canScrollUp = canScrollVertically(-1);
21093             if (canScrollUp) {
21094                 dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
21095                 dr.draw(c);
21096             }
21097         }
21098 
21099         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
21100             final boolean canScrollDown = canScrollVertically(1);
21101             if (canScrollDown) {
21102                 dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
21103                 dr.draw(c);
21104             }
21105         }
21106 
21107         final int leftRtl;
21108         final int rightRtl;
21109         if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
21110             leftRtl = PFLAG3_SCROLL_INDICATOR_END;
21111             rightRtl = PFLAG3_SCROLL_INDICATOR_START;
21112         } else {
21113             leftRtl = PFLAG3_SCROLL_INDICATOR_START;
21114             rightRtl = PFLAG3_SCROLL_INDICATOR_END;
21115         }
21116 
21117         final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
21118         if ((mPrivateFlags3 & leftMask) != 0) {
21119             final boolean canScrollLeft = canScrollHorizontally(-1);
21120             if (canScrollLeft) {
21121                 dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
21122                 dr.draw(c);
21123             }
21124         }
21125 
21126         final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
21127         if ((mPrivateFlags3 & rightMask) != 0) {
21128             final boolean canScrollRight = canScrollHorizontally(1);
21129             if (canScrollRight) {
21130                 dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
21131                 dr.draw(c);
21132             }
21133         }
21134     }
21135 
getHorizontalScrollBarBounds(@ullable Rect drawBounds, @Nullable Rect touchBounds)21136     private void getHorizontalScrollBarBounds(@Nullable Rect drawBounds,
21137             @Nullable Rect touchBounds) {
21138         final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
21139         if (bounds == null) {
21140             return;
21141         }
21142         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
21143         final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
21144                 && !isVerticalScrollBarHidden();
21145         final int size = getHorizontalScrollbarHeight();
21146         final int verticalScrollBarGap = drawVerticalScrollBar ?
21147                 getVerticalScrollbarWidth() : 0;
21148         final int width = mRight - mLeft;
21149         final int height = mBottom - mTop;
21150         bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
21151         bounds.left = mScrollX + (mPaddingLeft & inside);
21152         bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
21153         bounds.bottom = bounds.top + size;
21154 
21155         if (touchBounds == null) {
21156             return;
21157         }
21158         if (touchBounds != bounds) {
21159             touchBounds.set(bounds);
21160         }
21161         final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
21162         if (touchBounds.height() < minTouchTarget) {
21163             final int adjust = (minTouchTarget - touchBounds.height()) / 2;
21164             touchBounds.bottom = Math.min(touchBounds.bottom + adjust, mScrollY + height);
21165             touchBounds.top = touchBounds.bottom - minTouchTarget;
21166         }
21167         if (touchBounds.width() < minTouchTarget) {
21168             final int adjust = (minTouchTarget - touchBounds.width()) / 2;
21169             touchBounds.left -= adjust;
21170             touchBounds.right = touchBounds.left + minTouchTarget;
21171         }
21172     }
21173 
getVerticalScrollBarBounds(@ullable Rect bounds, @Nullable Rect touchBounds)21174     private void getVerticalScrollBarBounds(@Nullable Rect bounds, @Nullable Rect touchBounds) {
21175         if (mRoundScrollbarRenderer == null) {
21176             getStraightVerticalScrollBarBounds(bounds, touchBounds);
21177         } else {
21178             getRoundVerticalScrollBarBounds(bounds != null ? bounds : touchBounds);
21179         }
21180     }
21181 
getRoundVerticalScrollBarBounds(Rect bounds)21182     private void getRoundVerticalScrollBarBounds(Rect bounds) {
21183         final int width = mRight - mLeft;
21184         final int height = mBottom - mTop;
21185         // Do not take padding into account as we always want the scrollbars
21186         // to hug the screen for round wearable devices.
21187         bounds.left = mScrollX;
21188         bounds.top = mScrollY;
21189         bounds.right = bounds.left + width;
21190         bounds.bottom = mScrollY + height;
21191     }
21192 
getStraightVerticalScrollBarBounds(@ullable Rect drawBounds, @Nullable Rect touchBounds)21193     private void getStraightVerticalScrollBarBounds(@Nullable Rect drawBounds,
21194             @Nullable Rect touchBounds) {
21195         final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
21196         if (bounds == null) {
21197             return;
21198         }
21199         final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
21200         final int size = getVerticalScrollbarWidth();
21201         int verticalScrollbarPosition = mVerticalScrollbarPosition;
21202         if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
21203             verticalScrollbarPosition = isLayoutRtl() ?
21204                     SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
21205         }
21206         final int width = mRight - mLeft;
21207         final int height = mBottom - mTop;
21208         switch (verticalScrollbarPosition) {
21209             default:
21210             case SCROLLBAR_POSITION_RIGHT:
21211                 bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
21212                 break;
21213             case SCROLLBAR_POSITION_LEFT:
21214                 bounds.left = mScrollX + (mUserPaddingLeft & inside);
21215                 break;
21216         }
21217         bounds.top = mScrollY + (mPaddingTop & inside);
21218         bounds.right = bounds.left + size;
21219         bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
21220 
21221         if (touchBounds == null) {
21222             return;
21223         }
21224         if (touchBounds != bounds) {
21225             touchBounds.set(bounds);
21226         }
21227         final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
21228         if (touchBounds.width() < minTouchTarget) {
21229             final int adjust = (minTouchTarget - touchBounds.width()) / 2;
21230             if (verticalScrollbarPosition == SCROLLBAR_POSITION_RIGHT) {
21231                 touchBounds.right = Math.min(touchBounds.right + adjust, mScrollX + width);
21232                 touchBounds.left = touchBounds.right - minTouchTarget;
21233             } else {
21234                 touchBounds.left = Math.max(touchBounds.left + adjust, mScrollX);
21235                 touchBounds.right = touchBounds.left + minTouchTarget;
21236             }
21237         }
21238         if (touchBounds.height() < minTouchTarget) {
21239             final int adjust = (minTouchTarget - touchBounds.height()) / 2;
21240             touchBounds.top -= adjust;
21241             touchBounds.bottom = touchBounds.top + minTouchTarget;
21242         }
21243     }
21244 
21245     /**
21246      * <p>Request the drawing of the horizontal and the vertical scrollbar. The
21247      * scrollbars are painted only if they have been awakened first.</p>
21248      *
21249      * @param canvas the canvas on which to draw the scrollbars
21250      *
21251      * @see #awakenScrollBars(int)
21252      */
onDrawScrollBars(@onNull Canvas canvas)21253     protected final void onDrawScrollBars(@NonNull Canvas canvas) {
21254         // scrollbars are drawn only when the animation is running
21255         final ScrollabilityCache cache = mScrollCache;
21256 
21257         if (cache != null) {
21258 
21259             int state = cache.state;
21260 
21261             if (state == ScrollabilityCache.OFF) {
21262                 return;
21263             }
21264 
21265             boolean invalidate = false;
21266 
21267             if (state == ScrollabilityCache.FADING) {
21268                 // We're fading -- get our fade interpolation
21269                 if (cache.interpolatorValues == null) {
21270                     cache.interpolatorValues = new float[1];
21271                 }
21272 
21273                 float[] values = cache.interpolatorValues;
21274 
21275                 // Stops the animation if we're done
21276                 if (cache.scrollBarInterpolator.timeToValues(values) ==
21277                         Interpolator.Result.FREEZE_END) {
21278                     cache.state = ScrollabilityCache.OFF;
21279                 } else {
21280                     cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
21281                 }
21282 
21283                 // This will make the scroll bars inval themselves after
21284                 // drawing. We only want this when we're fading so that
21285                 // we prevent excessive redraws
21286                 invalidate = true;
21287             } else {
21288                 // We're just on -- but we may have been fading before so
21289                 // reset alpha
21290                 cache.scrollBar.mutate().setAlpha(255);
21291             }
21292 
21293             final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
21294             final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
21295                     && !isVerticalScrollBarHidden();
21296 
21297             // Fork out the scroll bar drawing for round wearable devices.
21298             if (mRoundScrollbarRenderer != null) {
21299                 if (drawVerticalScrollBar) {
21300                     final Rect bounds = cache.mScrollBarBounds;
21301                     getVerticalScrollBarBounds(bounds, null);
21302                     mRoundScrollbarRenderer.drawRoundScrollbars(
21303                             canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
21304                     if (invalidate) {
21305                         invalidate();
21306                     }
21307                 }
21308                 // Do not draw horizontal scroll bars for round wearable devices.
21309             } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
21310                 final ScrollBarDrawable scrollBar = cache.scrollBar;
21311 
21312                 if (drawHorizontalScrollBar) {
21313                     scrollBar.setParameters(computeHorizontalScrollRange(),
21314                             computeHorizontalScrollOffset(),
21315                             computeHorizontalScrollExtent(), false);
21316                     final Rect bounds = cache.mScrollBarBounds;
21317                     getHorizontalScrollBarBounds(bounds, null);
21318                     onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
21319                             bounds.right, bounds.bottom);
21320                     if (invalidate) {
21321                         invalidate(bounds);
21322                     }
21323                 }
21324 
21325                 if (drawVerticalScrollBar) {
21326                     scrollBar.setParameters(computeVerticalScrollRange(),
21327                             computeVerticalScrollOffset(),
21328                             computeVerticalScrollExtent(), true);
21329                     final Rect bounds = cache.mScrollBarBounds;
21330                     getVerticalScrollBarBounds(bounds, null);
21331                     onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
21332                             bounds.right, bounds.bottom);
21333                     if (invalidate) {
21334                         invalidate(bounds);
21335                     }
21336                 }
21337             }
21338         }
21339     }
21340 
21341     /**
21342      * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
21343      * FastScroller is visible.
21344      * @return whether to temporarily hide the vertical scrollbar
21345      * @hide
21346      */
isVerticalScrollBarHidden()21347     protected boolean isVerticalScrollBarHidden() {
21348         return false;
21349     }
21350 
21351     /**
21352      * <p>Draw the horizontal scrollbar if
21353      * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
21354      *
21355      * @param canvas the canvas on which to draw the scrollbar
21356      * @param scrollBar the scrollbar's drawable
21357      *
21358      * @see #isHorizontalScrollBarEnabled()
21359      * @see #computeHorizontalScrollRange()
21360      * @see #computeHorizontalScrollExtent()
21361      * @see #computeHorizontalScrollOffset()
21362      * @hide
21363      */
21364     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
onDrawHorizontalScrollBar(@onNull Canvas canvas, Drawable scrollBar, int l, int t, int r, int b)21365     protected void onDrawHorizontalScrollBar(@NonNull Canvas canvas, Drawable scrollBar,
21366             int l, int t, int r, int b) {
21367         scrollBar.setBounds(l, t, r, b);
21368         scrollBar.draw(canvas);
21369     }
21370 
21371     /**
21372      * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
21373      * returns true.</p>
21374      *
21375      * @param canvas the canvas on which to draw the scrollbar
21376      * @param scrollBar the scrollbar's drawable
21377      *
21378      * @see #isVerticalScrollBarEnabled()
21379      * @see #computeVerticalScrollRange()
21380      * @see #computeVerticalScrollExtent()
21381      * @see #computeVerticalScrollOffset()
21382      * @hide
21383      */
21384     @UnsupportedAppUsage
onDrawVerticalScrollBar(@onNull Canvas canvas, Drawable scrollBar, int l, int t, int r, int b)21385     protected void onDrawVerticalScrollBar(@NonNull Canvas canvas, Drawable scrollBar,
21386             int l, int t, int r, int b) {
21387         scrollBar.setBounds(l, t, r, b);
21388         scrollBar.draw(canvas);
21389     }
21390 
21391     /**
21392      * Implement this to do your drawing.
21393      *
21394      * @param canvas the canvas on which the background will be drawn
21395      */
onDraw(@onNull Canvas canvas)21396     protected void onDraw(@NonNull Canvas canvas) {
21397     }
21398 
21399     /*
21400      * Caller is responsible for calling requestLayout if necessary.
21401      * (This allows addViewInLayout to not request a new layout.)
21402      */
21403     @UnsupportedAppUsage
assignParent(ViewParent parent)21404     void assignParent(ViewParent parent) {
21405         if (mParent == null) {
21406             mParent = parent;
21407         } else if (parent == null) {
21408             mParent = null;
21409         } else {
21410             throw new RuntimeException("view " + this + " being added, but"
21411                     + " it already has a parent");
21412         }
21413     }
21414 
21415     /**
21416      * This is called when the view is attached to a window.  At this point it
21417      * has a Surface and will start drawing.  Note that this function is
21418      * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
21419      * however it may be called any time before the first onDraw -- including
21420      * before or after {@link #onMeasure(int, int)}.
21421      *
21422      * @see #onDetachedFromWindow()
21423      */
21424     @CallSuper
onAttachedToWindow()21425     protected void onAttachedToWindow() {
21426         if (mParent != null && (mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
21427             mParent.requestTransparentRegion(this);
21428         }
21429 
21430         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
21431 
21432         jumpDrawablesToCurrentState();
21433 
21434         AccessibilityNodeIdManager.getInstance().registerViewWithId(this, getAccessibilityViewId());
21435         resetSubtreeAccessibilityStateChanged();
21436 
21437         // rebuild, since Outline not maintained while View is detached
21438         rebuildOutline();
21439 
21440         if (isFocused()) {
21441             notifyFocusChangeToImeFocusController(true /* hasFocus */);
21442         }
21443 
21444         if (sTraceLayoutSteps) {
21445             setTraversalTracingEnabled(true);
21446         }
21447         if (sTraceRequestLayoutClass != null
21448                 && sTraceRequestLayoutClass.equals(getClass().getSimpleName())) {
21449             setRelayoutTracingEnabled(true);
21450         }
21451     }
21452 
21453     /**
21454      * Resolve all RTL related properties.
21455      *
21456      * @return true if resolution of RTL properties has been done
21457      *
21458      * @hide
21459      */
resolveRtlPropertiesIfNeeded()21460     public boolean resolveRtlPropertiesIfNeeded() {
21461         if (!needRtlPropertiesResolution()) return false;
21462 
21463         // Order is important here: LayoutDirection MUST be resolved first
21464         if (!isLayoutDirectionResolved()) {
21465             resolveLayoutDirection();
21466             resolveLayoutParams();
21467         }
21468         // ... then we can resolve the others properties depending on the resolved LayoutDirection.
21469         if (!isTextDirectionResolved()) {
21470             resolveTextDirection();
21471         }
21472         if (!isTextAlignmentResolved()) {
21473             resolveTextAlignment();
21474         }
21475         // Should resolve Drawables before Padding because we need the layout direction of the
21476         // Drawable to correctly resolve Padding.
21477         if (!areDrawablesResolved()) {
21478             resolveDrawables();
21479         }
21480         if (!isPaddingResolved()) {
21481             resolvePadding();
21482         }
21483         onRtlPropertiesChanged(getLayoutDirection());
21484         return true;
21485     }
21486 
21487     /**
21488      * Reset resolution of all RTL related properties.
21489      *
21490      * @hide
21491      */
21492     @TestApi
resetRtlProperties()21493     public void resetRtlProperties() {
21494         resetResolvedLayoutDirection();
21495         resetResolvedTextDirection();
21496         resetResolvedTextAlignment();
21497         resetResolvedPadding();
21498         resetResolvedDrawables();
21499     }
21500 
21501     /**
21502      * @see #onScreenStateChanged(int)
21503      */
dispatchScreenStateChanged(int screenState)21504     void dispatchScreenStateChanged(int screenState) {
21505         onScreenStateChanged(screenState);
21506     }
21507 
21508     /**
21509      * This method is called whenever the state of the screen this view is
21510      * attached to changes. A state change will usually occurs when the screen
21511      * turns on or off (whether it happens automatically or the user does it
21512      * manually.)
21513      *
21514      * @param screenState The new state of the screen. Can be either
21515      *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
21516      */
onScreenStateChanged(int screenState)21517     public void onScreenStateChanged(int screenState) {
21518     }
21519 
21520     /**
21521      * @see #onMovedToDisplay(int, Configuration)
21522      */
dispatchMovedToDisplay(Display display, Configuration config)21523     void dispatchMovedToDisplay(Display display, Configuration config) {
21524         mAttachInfo.mDisplay = display;
21525         mAttachInfo.mDisplayState = display.getState();
21526         onMovedToDisplay(display.getDisplayId(), config);
21527     }
21528 
21529     /**
21530      * Called by the system when the hosting activity is moved from one display to another without
21531      * recreation. This means that the activity is declared to handle all changes to configuration
21532      * that happened when it was switched to another display, so it wasn't destroyed and created
21533      * again.
21534      *
21535      * <p>This call will be followed by {@link #onConfigurationChanged(Configuration)} if the
21536      * applied configuration actually changed. It is up to app developer to choose whether to handle
21537      * the change in this method or in the following {@link #onConfigurationChanged(Configuration)}
21538      * call.
21539      *
21540      * <p>Use this callback to track changes to the displays if some functionality relies on an
21541      * association with some display properties.
21542      *
21543      * @param displayId The id of the display to which the view was moved.
21544      * @param config Configuration of the resources on new display after move.
21545      *
21546      * @see #onConfigurationChanged(Configuration)
21547      * @hide
21548      */
onMovedToDisplay(int displayId, Configuration config)21549     public void onMovedToDisplay(int displayId, Configuration config) {
21550     }
21551 
21552     /**
21553      * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
21554      */
21555     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
hasRtlSupport()21556     private boolean hasRtlSupport() {
21557         return mContext.getApplicationInfo().hasRtlSupport();
21558     }
21559 
21560     /**
21561      * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
21562      * RTL not supported)
21563      */
isRtlCompatibilityMode()21564     private boolean isRtlCompatibilityMode() {
21565         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
21566         return targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1 || !hasRtlSupport();
21567     }
21568 
21569     /**
21570      * @return true if RTL properties need resolution.
21571      *
21572      */
needRtlPropertiesResolution()21573     private boolean needRtlPropertiesResolution() {
21574         return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
21575     }
21576 
21577     /**
21578      * Called when any RTL property (layout direction or text direction or text alignment) has
21579      * been changed.
21580      *
21581      * Subclasses need to override this method to take care of cached information that depends on the
21582      * resolved layout direction, or to inform child views that inherit their layout direction.
21583      *
21584      * The default implementation does nothing.
21585      *
21586      * @param layoutDirection the direction of the layout
21587      *
21588      * @see #LAYOUT_DIRECTION_LTR
21589      * @see #LAYOUT_DIRECTION_RTL
21590      */
onRtlPropertiesChanged(@esolvedLayoutDir int layoutDirection)21591     public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
21592     }
21593 
21594     /**
21595      * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
21596      * that the parent directionality can and will be resolved before its children.
21597      *
21598      * @return true if resolution has been done, false otherwise.
21599      *
21600      * @hide
21601      */
resolveLayoutDirection()21602     public boolean resolveLayoutDirection() {
21603         // Clear any previous layout direction resolution
21604         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
21605 
21606         if (hasRtlSupport()) {
21607             // Set resolved depending on layout direction
21608             switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
21609                     PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
21610                 case LAYOUT_DIRECTION_INHERIT:
21611                     // We cannot resolve yet. LTR is by default and let the resolution happen again
21612                     // later to get the correct resolved value
21613                     if (!canResolveLayoutDirection()) return false;
21614 
21615                     // Parent has not yet resolved, LTR is still the default
21616                     try {
21617                         if (!mParent.isLayoutDirectionResolved()) return false;
21618 
21619                         if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
21620                             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
21621                         }
21622                     } catch (AbstractMethodError e) {
21623                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21624                                 " does not fully implement ViewParent", e);
21625                     }
21626                     break;
21627                 case LAYOUT_DIRECTION_RTL:
21628                     mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
21629                     break;
21630                 case LAYOUT_DIRECTION_LOCALE:
21631                     if((LAYOUT_DIRECTION_RTL ==
21632                             TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
21633                         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
21634                     }
21635                     break;
21636                 default:
21637                     // Nothing to do, LTR by default
21638             }
21639         }
21640 
21641         // Set to resolved
21642         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
21643         return true;
21644     }
21645 
21646     /**
21647      * Check if layout direction resolution can be done.
21648      *
21649      * @return true if layout direction resolution can be done otherwise return false.
21650      */
canResolveLayoutDirection()21651     public boolean canResolveLayoutDirection() {
21652         switch (getRawLayoutDirection()) {
21653             case LAYOUT_DIRECTION_INHERIT:
21654                 if (mParent != null) {
21655                     try {
21656                         return mParent.canResolveLayoutDirection();
21657                     } catch (AbstractMethodError e) {
21658                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21659                                 " does not fully implement ViewParent", e);
21660                     }
21661                 }
21662                 return false;
21663 
21664             default:
21665                 return true;
21666         }
21667     }
21668 
21669     /**
21670      * Reset the resolved layout direction. Layout direction will be resolved during a call to
21671      * {@link #onMeasure(int, int)}.
21672      *
21673      * @hide
21674      */
21675     @TestApi
resetResolvedLayoutDirection()21676     public void resetResolvedLayoutDirection() {
21677         // Reset the current resolved bits
21678         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
21679     }
21680 
21681     /**
21682      * @return true if the layout direction is inherited.
21683      *
21684      * @hide
21685      */
isLayoutDirectionInherited()21686     public boolean isLayoutDirectionInherited() {
21687         return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
21688     }
21689 
21690     /**
21691      * @return true if layout direction has been resolved.
21692      */
isLayoutDirectionResolved()21693     public boolean isLayoutDirectionResolved() {
21694         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
21695     }
21696 
21697     /**
21698      * Return if padding has been resolved
21699      *
21700      * @hide
21701      */
21702     @UnsupportedAppUsage
isPaddingResolved()21703     boolean isPaddingResolved() {
21704         return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
21705     }
21706 
21707     /**
21708      * Resolves padding depending on layout direction, if applicable, and
21709      * recomputes internal padding values to adjust for scroll bars.
21710      *
21711      * @hide
21712      */
21713     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
resolvePadding()21714     public void resolvePadding() {
21715         final int resolvedLayoutDirection = getLayoutDirection();
21716 
21717         if (!isRtlCompatibilityMode()) {
21718             // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
21719             // If start / end padding are defined, they will be resolved (hence overriding) to
21720             // left / right or right / left depending on the resolved layout direction.
21721             // If start / end padding are not defined, use the left / right ones.
21722             if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
21723                 Rect padding = sThreadLocal.get();
21724                 if (padding == null) {
21725                     padding = new Rect();
21726                     sThreadLocal.set(padding);
21727                 }
21728                 mBackground.getPadding(padding);
21729                 if (!mLeftPaddingDefined) {
21730                     mUserPaddingLeftInitial = padding.left;
21731                 }
21732                 if (!mRightPaddingDefined) {
21733                     mUserPaddingRightInitial = padding.right;
21734                 }
21735             }
21736             switch (resolvedLayoutDirection) {
21737                 case LAYOUT_DIRECTION_RTL:
21738                     if (mUserPaddingStart != UNDEFINED_PADDING) {
21739                         mUserPaddingRight = mUserPaddingStart;
21740                     } else {
21741                         mUserPaddingRight = mUserPaddingRightInitial;
21742                     }
21743                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
21744                         mUserPaddingLeft = mUserPaddingEnd;
21745                     } else {
21746                         mUserPaddingLeft = mUserPaddingLeftInitial;
21747                     }
21748                     break;
21749                 case LAYOUT_DIRECTION_LTR:
21750                 default:
21751                     if (mUserPaddingStart != UNDEFINED_PADDING) {
21752                         mUserPaddingLeft = mUserPaddingStart;
21753                     } else {
21754                         mUserPaddingLeft = mUserPaddingLeftInitial;
21755                     }
21756                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
21757                         mUserPaddingRight = mUserPaddingEnd;
21758                     } else {
21759                         mUserPaddingRight = mUserPaddingRightInitial;
21760                     }
21761             }
21762 
21763             mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
21764         }
21765 
21766         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
21767         onRtlPropertiesChanged(resolvedLayoutDirection);
21768 
21769         mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
21770     }
21771 
21772     /**
21773      * Reset the resolved layout direction.
21774      *
21775      * @hide
21776      */
21777     @TestApi
resetResolvedPadding()21778     public void resetResolvedPadding() {
21779         resetResolvedPaddingInternal();
21780     }
21781 
21782     /**
21783      * Used when we only want to reset *this* view's padding and not trigger overrides
21784      * in ViewGroup that reset children too.
21785      */
resetResolvedPaddingInternal()21786     void resetResolvedPaddingInternal() {
21787         mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
21788     }
21789 
21790     /**
21791      * This is called when the view is detached from a window.  At this point it
21792      * no longer has a surface for drawing.
21793      *
21794      * @see #onAttachedToWindow()
21795      */
21796     @CallSuper
onDetachedFromWindow()21797     protected void onDetachedFromWindow() {
21798     }
21799 
21800     /**
21801      * This is a framework-internal mirror of onDetachedFromWindow() that's called
21802      * after onDetachedFromWindow().
21803      *
21804      * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
21805      * The super method should be called at the end of the overridden method to ensure
21806      * subclasses are destroyed first
21807      *
21808      * @hide
21809      */
21810     @CallSuper
21811     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
onDetachedFromWindowInternal()21812     protected void onDetachedFromWindowInternal() {
21813         mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
21814         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
21815         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
21816 
21817         removeUnsetPressCallback();
21818         removeLongPressCallback();
21819         removePerformClickCallback();
21820         clearAccessibilityThrottles();
21821         stopNestedScroll();
21822 
21823         // Anything that started animating right before detach should already
21824         // be in its final state when re-attached.
21825         jumpDrawablesToCurrentState();
21826 
21827         destroyDrawingCache();
21828 
21829         cleanupDraw();
21830         mCurrentAnimation = null;
21831 
21832         if ((mViewFlags & TOOLTIP) == TOOLTIP) {
21833             removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
21834             removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
21835             hideTooltip();
21836         }
21837 
21838         AccessibilityNodeIdManager.getInstance().unregisterViewWithId(getAccessibilityViewId());
21839 
21840         if (mBackgroundRenderNode != null) {
21841             mBackgroundRenderNode.forceEndAnimators();
21842         }
21843         mRenderNode.forceEndAnimators();
21844     }
21845 
cleanupDraw()21846     private void cleanupDraw() {
21847         resetDisplayList();
21848         if (mAttachInfo != null) {
21849             mAttachInfo.mViewRootImpl.cancelInvalidate(this);
21850         }
21851     }
21852 
invalidateInheritedLayoutMode(int layoutModeOfRoot)21853     void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
21854     }
21855 
21856     /**
21857      * @return The number of times this view has been attached to a window
21858      */
getWindowAttachCount()21859     protected int getWindowAttachCount() {
21860         return mWindowAttachCount;
21861     }
21862 
21863     /**
21864      * Retrieve a unique token identifying the window this view is attached to.
21865      * @return Return the window's token for use in
21866      * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
21867      */
getWindowToken()21868     public IBinder getWindowToken() {
21869         return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
21870     }
21871 
21872     /**
21873      * Retrieve the {@link WindowId} for the window this view is
21874      * currently attached to.
21875      */
getWindowId()21876     public WindowId getWindowId() {
21877         AttachInfo ai = mAttachInfo;
21878         if (ai == null) {
21879             return null;
21880         }
21881         if (ai.mWindowId == null) {
21882             try {
21883                 ai.mIWindowId = ai.mSession.getWindowId(ai.mWindowToken);
21884                 if (ai.mIWindowId != null) {
21885                     ai.mWindowId = new WindowId(ai.mIWindowId);
21886                 }
21887             } catch (RemoteException e) {
21888             }
21889         }
21890         return ai.mWindowId;
21891     }
21892 
21893     /**
21894      * Retrieve a unique token identifying the top-level "real" window of
21895      * the window that this view is attached to.  That is, this is like
21896      * {@link #getWindowToken}, except if the window this view in is a panel
21897      * window (attached to another containing window), then the token of
21898      * the containing window is returned instead.
21899      *
21900      * @return Returns the associated window token, either
21901      * {@link #getWindowToken()} or the containing window's token.
21902      */
getApplicationWindowToken()21903     public IBinder getApplicationWindowToken() {
21904         AttachInfo ai = mAttachInfo;
21905         if (ai != null) {
21906             IBinder appWindowToken = ai.mPanelParentWindowToken;
21907             if (appWindowToken == null) {
21908                 appWindowToken = ai.mWindowToken;
21909             }
21910             return appWindowToken;
21911         }
21912         return null;
21913     }
21914 
21915     /**
21916      * Gets the logical display to which the view's window has been attached.
21917      *
21918      * @return The logical display, or null if the view is not currently attached to a window.
21919      */
getDisplay()21920     public Display getDisplay() {
21921         return mAttachInfo != null ? mAttachInfo.mDisplay : null;
21922     }
21923 
21924     /**
21925      * Retrieve private session object this view hierarchy is using to
21926      * communicate with the window manager.
21927      * @return the session object to communicate with the window manager
21928      */
21929     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
getWindowSession()21930     /*package*/ IWindowSession getWindowSession() {
21931         return mAttachInfo != null ? mAttachInfo.mSession : null;
21932     }
21933 
21934     /**
21935      * Return the window this view is currently attached to.
21936      * @hide
21937      */
getWindow()21938     protected IWindow getWindow() {
21939         return mAttachInfo != null ? mAttachInfo.mWindow : null;
21940     }
21941 
21942     /**
21943      * Return the visibility value of the least visible component passed.
21944      */
combineVisibility(int vis1, int vis2)21945     int combineVisibility(int vis1, int vis2) {
21946         // This works because VISIBLE < INVISIBLE < GONE.
21947         return Math.max(vis1, vis2);
21948     }
21949 
21950     private boolean mShouldFakeFocus = false;
21951 
21952     /**
21953      * Fake send a focus event after attaching to window.
21954      * See {@link android.view.ViewRootImpl#dispatchCompatFakeFocus()} for details.
21955      * @hide
21956      */
fakeFocusAfterAttachingToWindow()21957     public void fakeFocusAfterAttachingToWindow() {
21958         mShouldFakeFocus = true;
21959     }
21960 
21961     /**
21962      * @param info the {@link android.view.View.AttachInfo} to associated with
21963      *        this view
21964      */
21965     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
dispatchAttachedToWindow(AttachInfo info, int visibility)21966     void dispatchAttachedToWindow(AttachInfo info, int visibility) {
21967         mAttachInfo = info;
21968         if (mOverlay != null) {
21969             mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
21970         }
21971         mWindowAttachCount++;
21972         // We will need to evaluate the drawable state at least once.
21973         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
21974         if (mFloatingTreeObserver != null) {
21975             info.mTreeObserver.merge(mFloatingTreeObserver);
21976             mFloatingTreeObserver = null;
21977         }
21978 
21979         registerPendingFrameMetricsObservers();
21980 
21981         if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
21982             mAttachInfo.mScrollContainers.add(this);
21983             mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
21984         }
21985         // Transfer all pending runnables.
21986         if (mRunQueue != null) {
21987             mRunQueue.executeActions(info.mHandler);
21988             mRunQueue = null;
21989         }
21990         performCollectViewAttributes(mAttachInfo, visibility);
21991         onAttachedToWindow();
21992 
21993         ListenerInfo li = mListenerInfo;
21994         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
21995                 li != null ? li.mOnAttachStateChangeListeners : null;
21996         if (listeners != null && listeners.size() > 0) {
21997             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
21998             // perform the dispatching. The iterator is a safe guard against listeners that
21999             // could mutate the list by calling the various add/remove methods. This prevents
22000             // the array from being modified while we iterate it.
22001             for (OnAttachStateChangeListener listener : listeners) {
22002                 listener.onViewAttachedToWindow(this);
22003             }
22004         }
22005 
22006         int vis = info.mWindowVisibility;
22007         if (vis != GONE) {
22008             onWindowVisibilityChanged(vis);
22009             if (isShown()) {
22010                 // Calling onVisibilityAggregated directly here since the subtree will also
22011                 // receive dispatchAttachedToWindow and this same call
22012                 onVisibilityAggregated(vis == VISIBLE);
22013             }
22014         }
22015 
22016         // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
22017         // As all views in the subtree will already receive dispatchAttachedToWindow
22018         // traversing the subtree again here is not desired.
22019         onVisibilityChanged(this, visibility);
22020 
22021         if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
22022             // If nobody has evaluated the drawable state yet, then do it now.
22023             refreshDrawableState();
22024         }
22025         needGlobalAttributesUpdate(false);
22026 
22027         notifyEnterOrExitForAutoFillIfNeeded(true);
22028         notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
22029 
22030         if (mShouldFakeFocus) {
22031             getViewRootImpl().dispatchCompatFakeFocus();
22032             mShouldFakeFocus = false;
22033         }
22034     }
22035 
22036     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
dispatchDetachedFromWindow()22037     void dispatchDetachedFromWindow() {
22038         AttachInfo info = mAttachInfo;
22039         if (info != null) {
22040             int vis = info.mWindowVisibility;
22041             if (vis != GONE) {
22042                 onWindowVisibilityChanged(GONE);
22043                 if (isShown()) {
22044                     // Invoking onVisibilityAggregated directly here since the subtree
22045                     // will also receive detached from window
22046                     onVisibilityAggregated(false);
22047                 }
22048             }
22049         }
22050 
22051         onDetachedFromWindow();
22052         onDetachedFromWindowInternal();
22053 
22054         if (info != null) {
22055             info.mViewRootImpl.getImeFocusController().onViewDetachedFromWindow(this);
22056         }
22057 
22058         ListenerInfo li = mListenerInfo;
22059         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
22060                 li != null ? li.mOnAttachStateChangeListeners : null;
22061         if (listeners != null && listeners.size() > 0) {
22062             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
22063             // perform the dispatching. The iterator is a safe guard against listeners that
22064             // could mutate the list by calling the various add/remove methods. This prevents
22065             // the array from being modified while we iterate it.
22066             for (OnAttachStateChangeListener listener : listeners) {
22067                 listener.onViewDetachedFromWindow(this);
22068             }
22069         }
22070 
22071         if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
22072             mAttachInfo.mScrollContainers.remove(this);
22073             mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
22074         }
22075 
22076         notifyAppearedOrDisappearedForContentCaptureIfNeeded(false);
22077 
22078         mAttachInfo = null;
22079         if (mOverlay != null) {
22080             mOverlay.getOverlayView().dispatchDetachedFromWindow();
22081         }
22082 
22083         notifyEnterOrExitForAutoFillIfNeeded(false);
22084 
22085         if (info != null && !collectPreferKeepClearRects().isEmpty()) {
22086             info.mViewRootImpl.updateKeepClearRectsForView(this);
22087         }
22088     }
22089 
22090     /**
22091      * Cancel any deferred high-level input events that were previously posted to the event queue.
22092      *
22093      * <p>Many views post high-level events such as click handlers to the event queue
22094      * to run deferred in order to preserve a desired user experience - clearing visible
22095      * pressed states before executing, etc. This method will abort any events of this nature
22096      * that are currently in flight.</p>
22097      *
22098      * <p>Custom views that generate their own high-level deferred input events should override
22099      * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
22100      *
22101      * <p>This will also cancel pending input events for any child views.</p>
22102      *
22103      * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
22104      * This will not impact newer events posted after this call that may occur as a result of
22105      * lower-level input events still waiting in the queue. If you are trying to prevent
22106      * double-submitted  events for the duration of some sort of asynchronous transaction
22107      * you should also take other steps to protect against unexpected double inputs e.g. calling
22108      * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
22109      * the transaction completes, tracking already submitted transaction IDs, etc.</p>
22110      */
cancelPendingInputEvents()22111     public final void cancelPendingInputEvents() {
22112         dispatchCancelPendingInputEvents();
22113     }
22114 
22115     /**
22116      * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
22117      * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
22118      */
dispatchCancelPendingInputEvents()22119     void dispatchCancelPendingInputEvents() {
22120         mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
22121         onCancelPendingInputEvents();
22122         if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
22123             throw new SuperNotCalledException("View " + getClass().getSimpleName() +
22124                     " did not call through to super.onCancelPendingInputEvents()");
22125         }
22126     }
22127 
22128     /**
22129      * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
22130      * a parent view.
22131      *
22132      * <p>This method is responsible for removing any pending high-level input events that were
22133      * posted to the event queue to run later. Custom view classes that post their own deferred
22134      * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
22135      * {@link android.os.Handler} should override this method, call
22136      * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
22137      * </p>
22138      */
onCancelPendingInputEvents()22139     public void onCancelPendingInputEvents() {
22140         removePerformClickCallback();
22141         cancelLongPress();
22142         mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
22143     }
22144 
22145     /**
22146      * Store this view hierarchy's frozen state into the given container.
22147      *
22148      * @param container The SparseArray in which to save the view's state.
22149      *
22150      * @see #restoreHierarchyState(android.util.SparseArray)
22151      * @see #dispatchSaveInstanceState(android.util.SparseArray)
22152      * @see #onSaveInstanceState()
22153      */
saveHierarchyState(SparseArray<Parcelable> container)22154     public void saveHierarchyState(SparseArray<Parcelable> container) {
22155         dispatchSaveInstanceState(container);
22156     }
22157 
22158     /**
22159      * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
22160      * this view and its children. May be overridden to modify how freezing happens to a
22161      * view's children; for example, some views may want to not store state for their children.
22162      *
22163      * @param container The SparseArray in which to save the view's state.
22164      *
22165      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
22166      * @see #saveHierarchyState(android.util.SparseArray)
22167      * @see #onSaveInstanceState()
22168      */
dispatchSaveInstanceState(SparseArray<Parcelable> container)22169     protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
22170         if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
22171             mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
22172             Parcelable state = onSaveInstanceState();
22173             if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
22174                 throw new IllegalStateException(
22175                         "Derived class did not call super.onSaveInstanceState()");
22176             }
22177             if (state != null) {
22178                 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
22179                 // + ": " + state);
22180                 container.put(mID, state);
22181             }
22182         }
22183     }
22184 
22185     /**
22186      * Hook allowing a view to generate a representation of its internal state
22187      * that can later be used to create a new instance with that same state.
22188      * This state should only contain information that is not persistent or can
22189      * not be reconstructed later. For example, you will never store your
22190      * current position on screen because that will be computed again when a
22191      * new instance of the view is placed in its view hierarchy.
22192      * <p>
22193      * Some examples of things you may store here: the current cursor position
22194      * in a text view (but usually not the text itself since that is stored in a
22195      * content provider or other persistent storage), the currently selected
22196      * item in a list view.
22197      *
22198      * @return Returns a Parcelable object containing the view's current dynamic
22199      *         state, or null if there is nothing interesting to save.
22200      * @see #onRestoreInstanceState(Parcelable)
22201      * @see #saveHierarchyState(SparseArray)
22202      * @see #dispatchSaveInstanceState(SparseArray)
22203      * @see #setSaveEnabled(boolean)
22204      */
22205     @CallSuper
onSaveInstanceState()22206     @Nullable protected Parcelable onSaveInstanceState() {
22207         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
22208         if (mStartActivityRequestWho != null || isAutofilled()
22209                 || mAutofillViewId > LAST_APP_AUTOFILL_ID) {
22210             BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
22211 
22212             if (mStartActivityRequestWho != null) {
22213                 state.mSavedData |= BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED;
22214             }
22215 
22216             if (isAutofilled()) {
22217                 state.mSavedData |= BaseSavedState.IS_AUTOFILLED;
22218             }
22219 
22220             if (mAutofillViewId > LAST_APP_AUTOFILL_ID) {
22221                 state.mSavedData |= BaseSavedState.AUTOFILL_ID;
22222             }
22223 
22224             state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
22225             state.mIsAutofilled = isAutofilled();
22226             state.mHideHighlight = hideAutofillHighlight();
22227             state.mAutofillViewId = mAutofillViewId;
22228             return state;
22229         }
22230         return BaseSavedState.EMPTY_STATE;
22231     }
22232 
22233     /**
22234      * Restore this view hierarchy's frozen state from the given container.
22235      *
22236      * @param container The SparseArray which holds previously frozen states.
22237      *
22238      * @see #saveHierarchyState(android.util.SparseArray)
22239      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
22240      * @see #onRestoreInstanceState(android.os.Parcelable)
22241      */
restoreHierarchyState(SparseArray<Parcelable> container)22242     public void restoreHierarchyState(SparseArray<Parcelable> container) {
22243         dispatchRestoreInstanceState(container);
22244     }
22245 
22246     /**
22247      * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
22248      * state for this view and its children. May be overridden to modify how restoring
22249      * happens to a view's children; for example, some views may want to not store state
22250      * for their children.
22251      *
22252      * @param container The SparseArray which holds previously saved state.
22253      *
22254      * @see #dispatchSaveInstanceState(android.util.SparseArray)
22255      * @see #restoreHierarchyState(android.util.SparseArray)
22256      * @see #onRestoreInstanceState(android.os.Parcelable)
22257      */
dispatchRestoreInstanceState(SparseArray<Parcelable> container)22258     protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
22259         if (mID != NO_ID) {
22260             Parcelable state = container.get(mID);
22261             if (state != null) {
22262                 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
22263                 // + ": " + state);
22264                 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
22265                 onRestoreInstanceState(state);
22266                 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
22267                     throw new IllegalStateException(
22268                             "Derived class did not call super.onRestoreInstanceState()");
22269                 }
22270             }
22271         }
22272     }
22273 
22274     /**
22275      * Hook allowing a view to re-apply a representation of its internal state that had previously
22276      * been generated by {@link #onSaveInstanceState}. This function will never be called with a
22277      * null state.
22278      *
22279      * @param state The frozen state that had previously been returned by
22280      *        {@link #onSaveInstanceState}.
22281      *
22282      * @see #onSaveInstanceState()
22283      * @see #restoreHierarchyState(android.util.SparseArray)
22284      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
22285      */
22286     @CallSuper
onRestoreInstanceState(Parcelable state)22287     protected void onRestoreInstanceState(Parcelable state) {
22288         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
22289         if (state != null && !(state instanceof AbsSavedState)) {
22290             throw new IllegalArgumentException("Wrong state class, expecting View State but "
22291                     + "received " + state.getClass().toString() + " instead. This usually happens "
22292                     + "when two views of different type have the same id in the same hierarchy. "
22293                     + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
22294                     + "other views do not use the same id.");
22295         }
22296         if (state != null && state instanceof BaseSavedState) {
22297             BaseSavedState baseState = (BaseSavedState) state;
22298 
22299             if ((baseState.mSavedData & BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED) != 0) {
22300                 mStartActivityRequestWho = baseState.mStartActivityRequestWhoSaved;
22301             }
22302             if ((baseState.mSavedData & BaseSavedState.IS_AUTOFILLED) != 0) {
22303                 setAutofilled(baseState.mIsAutofilled, baseState.mHideHighlight);
22304             }
22305             if ((baseState.mSavedData & BaseSavedState.AUTOFILL_ID) != 0) {
22306                 // It can happen that views have the same view id and the restoration path will not
22307                 // be able to distinguish between them. The autofill id needs to be unique though.
22308                 // Hence prevent the same autofill view id from being restored multiple times.
22309                 ((BaseSavedState) state).mSavedData &= ~BaseSavedState.AUTOFILL_ID;
22310 
22311                 if ((mPrivateFlags3 & PFLAG3_AUTOFILLID_EXPLICITLY_SET) != 0) {
22312                     // Ignore when view already set it through setAutofillId();
22313                     if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.DEBUG)) {
22314                         Log.d(AUTOFILL_LOG_TAG, "onRestoreInstanceState(): not setting autofillId "
22315                                 + "to " + baseState.mAutofillViewId + " because view explicitly set"
22316                                 + " it to " + mAutofillId);
22317                     }
22318                 } else {
22319                     mAutofillViewId = baseState.mAutofillViewId;
22320                     mAutofillId = null; // will be set on demand by getAutofillId()
22321                 }
22322             }
22323         }
22324     }
22325 
22326     /**
22327      * <p>Return the time at which the drawing of the view hierarchy started.</p>
22328      *
22329      * @return the drawing start time in milliseconds
22330      */
getDrawingTime()22331     public long getDrawingTime() {
22332         return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
22333     }
22334 
22335     /**
22336      * <p>Enables or disables the duplication of the parent's state into this view. When
22337      * duplication is enabled, this view gets its drawable state from its parent rather
22338      * than from its own internal properties.</p>
22339      *
22340      * <p>Note: in the current implementation, setting this property to true after the
22341      * view was added to a ViewGroup might have no effect at all. This property should
22342      * always be used from XML or set to true before adding this view to a ViewGroup.</p>
22343      *
22344      * <p>Note: if this view's parent addStateFromChildren property is enabled and this
22345      * property is enabled, an exception will be thrown.</p>
22346      *
22347      * <p>Note: if the child view uses and updates additional states which are unknown to the
22348      * parent, these states should not be affected by this method.</p>
22349      *
22350      * @param enabled True to enable duplication of the parent's drawable state, false
22351      *                to disable it.
22352      *
22353      * @see #getDrawableState()
22354      * @see #isDuplicateParentStateEnabled()
22355      */
setDuplicateParentStateEnabled(boolean enabled)22356     public void setDuplicateParentStateEnabled(boolean enabled) {
22357         setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
22358     }
22359 
22360     /**
22361      * <p>Indicates whether this duplicates its drawable state from its parent.</p>
22362      *
22363      * @return True if this view's drawable state is duplicated from the parent,
22364      *         false otherwise
22365      *
22366      * @see #getDrawableState()
22367      * @see #setDuplicateParentStateEnabled(boolean)
22368      */
22369     @InspectableProperty(name = "duplicateParentState")
isDuplicateParentStateEnabled()22370     public boolean isDuplicateParentStateEnabled() {
22371         return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
22372     }
22373 
22374     /**
22375      * <p>Specifies the type of layer backing this view. The layer can be
22376      * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
22377      * {@link #LAYER_TYPE_HARDWARE}.</p>
22378      *
22379      * <p>A layer is associated with an optional {@link android.graphics.Paint}
22380      * instance that controls how the layer is composed on screen. The following
22381      * properties of the paint are taken into account when composing the layer:</p>
22382      * <ul>
22383      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
22384      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
22385      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
22386      * </ul>
22387      *
22388      * <p>If this view has an alpha value set to < 1.0 by calling
22389      * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
22390      * by this view's alpha value.</p>
22391      *
22392      * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
22393      * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
22394      * for more information on when and how to use layers.</p>
22395      *
22396      * @param layerType The type of layer to use with this view, must be one of
22397      *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
22398      *        {@link #LAYER_TYPE_HARDWARE}
22399      * @param paint The paint used to compose the layer. This argument is optional
22400      *        and can be null. It is ignored when the layer type is
22401      *        {@link #LAYER_TYPE_NONE}
22402      *
22403      * @see #getLayerType()
22404      * @see #LAYER_TYPE_NONE
22405      * @see #LAYER_TYPE_SOFTWARE
22406      * @see #LAYER_TYPE_HARDWARE
22407      * @see #setAlpha(float)
22408      *
22409      * @attr ref android.R.styleable#View_layerType
22410      */
setLayerType(@ayerType int layerType, @Nullable Paint paint)22411     public void setLayerType(@LayerType int layerType, @Nullable Paint paint) {
22412         if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
22413             throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
22414                     + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
22415         }
22416 
22417         boolean typeChanged = mRenderNode.setLayerType(layerType);
22418 
22419         if (!typeChanged) {
22420             setLayerPaint(paint);
22421             return;
22422         }
22423 
22424         if (layerType != LAYER_TYPE_SOFTWARE) {
22425             // Destroy any previous software drawing cache if present
22426             // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
22427             // drawing cache created in View#draw when drawing to a SW canvas.
22428             destroyDrawingCache();
22429         }
22430 
22431         mLayerType = layerType;
22432         mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
22433         mRenderNode.setLayerPaint(mLayerPaint);
22434 
22435         // draw() behaves differently if we are on a layer, so we need to
22436         // invalidate() here
22437         invalidateParentCaches();
22438         invalidate(true);
22439     }
22440 
22441     /**
22442      * Configure the {@link android.graphics.RenderEffect} to apply to this View.
22443      * This will apply a visual effect to the results of the View before it is drawn. For example if
22444      * {@link RenderEffect#createBlurEffect(float, float, RenderEffect, Shader.TileMode)}
22445      * is provided, the contents will be drawn in a separate layer, then this layer will be blurred
22446      * when this View is drawn.
22447      * @param renderEffect to be applied to the View. Passing null clears the previously configured
22448      *                     {@link RenderEffect}
22449      */
setRenderEffect(@ullable RenderEffect renderEffect)22450     public void setRenderEffect(@Nullable RenderEffect renderEffect) {
22451         if (mRenderNode.setRenderEffect(renderEffect)) {
22452             invalidateViewProperty(true, true);
22453         }
22454     }
22455 
22456     /**
22457      * Updates the {@link Paint} object used with the current layer (used only if the current
22458      * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
22459      * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
22460      * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
22461      * ensure that the view gets redrawn immediately.
22462      *
22463      * <p>A layer is associated with an optional {@link android.graphics.Paint}
22464      * instance that controls how the layer is composed on screen. The following
22465      * properties of the paint are taken into account when composing the layer:</p>
22466      * <ul>
22467      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
22468      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
22469      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
22470      * </ul>
22471      *
22472      * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
22473      * alpha value of the layer's paint is superseded by this view's alpha value.</p>
22474      *
22475      * @param paint The paint used to compose the layer. This argument is optional
22476      *        and can be null. It is ignored when the layer type is
22477      *        {@link #LAYER_TYPE_NONE}
22478      *
22479      * @see #setLayerType(int, android.graphics.Paint)
22480      */
setLayerPaint(@ullable Paint paint)22481     public void setLayerPaint(@Nullable Paint paint) {
22482         int layerType = getLayerType();
22483         if (layerType != LAYER_TYPE_NONE) {
22484             mLayerPaint = paint;
22485             if (layerType == LAYER_TYPE_HARDWARE) {
22486                 if (mRenderNode.setLayerPaint(paint)) {
22487                     invalidateViewProperty(false, false);
22488                 }
22489             } else {
22490                 invalidate();
22491             }
22492         }
22493     }
22494 
22495     /**
22496      * Indicates what type of layer is currently associated with this view. By default
22497      * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
22498      * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
22499      * for more information on the different types of layers.
22500      *
22501      * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
22502      *         {@link #LAYER_TYPE_HARDWARE}
22503      *
22504      * @see #setLayerType(int, android.graphics.Paint)
22505      * @see #buildLayer()
22506      * @see #LAYER_TYPE_NONE
22507      * @see #LAYER_TYPE_SOFTWARE
22508      * @see #LAYER_TYPE_HARDWARE
22509      */
22510     @InspectableProperty(enumMapping = {
22511             @EnumEntry(value = LAYER_TYPE_NONE, name = "none"),
22512             @EnumEntry(value = LAYER_TYPE_SOFTWARE, name = "software"),
22513             @EnumEntry(value = LAYER_TYPE_HARDWARE, name = "hardware")
22514     })
22515     @LayerType
getLayerType()22516     public int getLayerType() {
22517         return mLayerType;
22518     }
22519 
22520     /**
22521      * Forces this view's layer to be created and this view to be rendered
22522      * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
22523      * invoking this method will have no effect.
22524      *
22525      * This method can for instance be used to render a view into its layer before
22526      * starting an animation. If this view is complex, rendering into the layer
22527      * before starting the animation will avoid skipping frames.
22528      *
22529      * @throws IllegalStateException If this view is not attached to a window
22530      *
22531      * @see #setLayerType(int, android.graphics.Paint)
22532      */
buildLayer()22533     public void buildLayer() {
22534         if (mLayerType == LAYER_TYPE_NONE) return;
22535 
22536         final AttachInfo attachInfo = mAttachInfo;
22537         if (attachInfo == null) {
22538             throw new IllegalStateException("This view must be attached to a window first");
22539         }
22540 
22541         if (getWidth() == 0 || getHeight() == 0) {
22542             return;
22543         }
22544 
22545         switch (mLayerType) {
22546             case LAYER_TYPE_HARDWARE:
22547                 updateDisplayListIfDirty();
22548                 if (attachInfo.mThreadedRenderer != null && mRenderNode.hasDisplayList()) {
22549                     attachInfo.mThreadedRenderer.buildLayer(mRenderNode);
22550                 }
22551                 break;
22552             case LAYER_TYPE_SOFTWARE:
22553                 buildDrawingCache(true);
22554                 break;
22555         }
22556     }
22557 
22558     /**
22559      * Destroys all hardware rendering resources. This method is invoked
22560      * when the system needs to reclaim resources. Upon execution of this
22561      * method, you should free any OpenGL resources created by the view.
22562      *
22563      * Note: you <strong>must</strong> call
22564      * <code>super.destroyHardwareResources()</code> when overriding
22565      * this method.
22566      *
22567      * @hide
22568      */
22569     @CallSuper
22570     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
destroyHardwareResources()22571     protected void destroyHardwareResources() {
22572         if (mOverlay != null) {
22573             mOverlay.getOverlayView().destroyHardwareResources();
22574         }
22575         if (mGhostView != null) {
22576             mGhostView.destroyHardwareResources();
22577         }
22578     }
22579 
22580     /**
22581      * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
22582      * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
22583      * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
22584      * the cache is enabled. To benefit from the cache, you must request the drawing cache by
22585      * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
22586      * null.</p>
22587      *
22588      * <p>Enabling the drawing cache is similar to
22589      * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
22590      * acceleration is turned off. When hardware acceleration is turned on, enabling the
22591      * drawing cache has no effect on rendering because the system uses a different mechanism
22592      * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
22593      * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
22594      * for information on how to enable software and hardware layers.</p>
22595      *
22596      * <p>This API can be used to manually generate
22597      * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
22598      * {@link #getDrawingCache()}.</p>
22599      *
22600      * @param enabled true to enable the drawing cache, false otherwise
22601      *
22602      * @see #isDrawingCacheEnabled()
22603      * @see #getDrawingCache()
22604      * @see #buildDrawingCache()
22605      * @see #setLayerType(int, android.graphics.Paint)
22606      *
22607      * @deprecated The view drawing cache was largely made obsolete with the introduction of
22608      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
22609      * layers are largely unnecessary and can easily result in a net loss in performance due to the
22610      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
22611      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
22612      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
22613      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
22614      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
22615      * software-rendered usages are discouraged and have compatibility issues with hardware-only
22616      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
22617      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
22618      * reports or unit testing the {@link PixelCopy} API is recommended.
22619      */
22620     @Deprecated
setDrawingCacheEnabled(boolean enabled)22621     public void setDrawingCacheEnabled(boolean enabled) {
22622         mCachingFailed = false;
22623         setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
22624     }
22625 
22626     /**
22627      * <p>Indicates whether the drawing cache is enabled for this view.</p>
22628      *
22629      * @return true if the drawing cache is enabled
22630      *
22631      * @see #setDrawingCacheEnabled(boolean)
22632      * @see #getDrawingCache()
22633      *
22634      * @deprecated The view drawing cache was largely made obsolete with the introduction of
22635      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
22636      * layers are largely unnecessary and can easily result in a net loss in performance due to the
22637      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
22638      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
22639      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
22640      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
22641      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
22642      * software-rendered usages are discouraged and have compatibility issues with hardware-only
22643      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
22644      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
22645      * reports or unit testing the {@link PixelCopy} API is recommended.
22646      */
22647     @Deprecated
22648     @ViewDebug.ExportedProperty(category = "drawing")
isDrawingCacheEnabled()22649     public boolean isDrawingCacheEnabled() {
22650         return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
22651     }
22652 
22653     /**
22654      * Debugging utility which recursively outputs the dirty state of a view and its
22655      * descendants.
22656      *
22657      * @hide
22658      */
22659     @SuppressWarnings({"UnusedDeclaration"})
outputDirtyFlags(String indent, boolean clear, int clearMask)22660     public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
22661         Log.d(VIEW_LOG_TAG, indent + this + "             DIRTY("
22662                 + (mPrivateFlags & View.PFLAG_DIRTY_MASK)
22663                 + ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID("
22664                 + (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID)
22665                 + ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
22666         if (clear) {
22667             mPrivateFlags &= clearMask;
22668         }
22669         if (this instanceof ViewGroup) {
22670             ViewGroup parent = (ViewGroup) this;
22671             final int count = parent.getChildCount();
22672             for (int i = 0; i < count; i++) {
22673                 final View child = parent.getChildAt(i);
22674                 child.outputDirtyFlags(indent + "  ", clear, clearMask);
22675             }
22676         }
22677     }
22678 
22679     /**
22680      * This method is used by ViewGroup to cause its children to restore or recreate their
22681      * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
22682      * to recreate its own display list, which would happen if it went through the normal
22683      * draw/dispatchDraw mechanisms.
22684      *
22685      * @hide
22686      */
dispatchGetDisplayList()22687     protected void dispatchGetDisplayList() {}
22688 
22689     /**
22690      * A view that is not attached or hardware accelerated cannot create a display list.
22691      * This method checks these conditions and returns the appropriate result.
22692      *
22693      * @return true if view has the ability to create a display list, false otherwise.
22694      *
22695      * @hide
22696      */
canHaveDisplayList()22697     public boolean canHaveDisplayList() {
22698         return !(mAttachInfo == null || mAttachInfo.mThreadedRenderer == null);
22699     }
22700 
22701     /**
22702      * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
22703      * @hide
22704      */
22705     @NonNull
22706     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
updateDisplayListIfDirty()22707     public RenderNode updateDisplayListIfDirty() {
22708         final RenderNode renderNode = mRenderNode;
22709         if (!canHaveDisplayList()) {
22710             // can't populate RenderNode, don't try
22711             return renderNode;
22712         }
22713 
22714         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
22715                 || !renderNode.hasDisplayList()
22716                 || (mRecreateDisplayList)) {
22717             // Don't need to recreate the display list, just need to tell our
22718             // children to restore/recreate theirs
22719             if (renderNode.hasDisplayList()
22720                     && !mRecreateDisplayList) {
22721                 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
22722                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
22723                 dispatchGetDisplayList();
22724 
22725                 return renderNode; // no work needed
22726             }
22727 
22728             // If we got here, we're recreating it. Mark it as such to ensure that
22729             // we copy in child display lists into ours in drawChild()
22730             mRecreateDisplayList = true;
22731 
22732             int width = mRight - mLeft;
22733             int height = mBottom - mTop;
22734             int layerType = getLayerType();
22735 
22736             // Hacky hack: Reset any stretch effects as those are applied during the draw pass
22737             // instead of being "stateful" like other RenderNode properties
22738             renderNode.clearStretch();
22739 
22740             final RecordingCanvas canvas = renderNode.beginRecording(width, height);
22741 
22742             try {
22743                 if (layerType == LAYER_TYPE_SOFTWARE) {
22744                     buildDrawingCache(true);
22745                     Bitmap cache = getDrawingCache(true);
22746                     if (cache != null) {
22747                         canvas.drawBitmap(cache, 0, 0, mLayerPaint);
22748                     }
22749                 } else {
22750                     computeScroll();
22751 
22752                     canvas.translate(-mScrollX, -mScrollY);
22753                     mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
22754                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
22755 
22756                     // Fast path for layouts with no backgrounds
22757                     if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
22758                         dispatchDraw(canvas);
22759                         drawAutofilledHighlight(canvas);
22760                         if (mOverlay != null && !mOverlay.isEmpty()) {
22761                             mOverlay.getOverlayView().draw(canvas);
22762                         }
22763                         if (isShowingLayoutBounds()) {
22764                             debugDrawFocus(canvas);
22765                         }
22766                     } else {
22767                         draw(canvas);
22768                     }
22769                 }
22770             } finally {
22771                 renderNode.endRecording();
22772                 setDisplayListProperties(renderNode);
22773             }
22774         } else {
22775             mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
22776             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
22777         }
22778         return renderNode;
22779     }
22780 
22781     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
resetDisplayList()22782     private void resetDisplayList() {
22783         mRenderNode.discardDisplayList();
22784         if (mBackgroundRenderNode != null) {
22785             mBackgroundRenderNode.discardDisplayList();
22786         }
22787     }
22788 
22789     /**
22790      * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
22791      *
22792      * @return A non-scaled bitmap representing this view or null if cache is disabled.
22793      *
22794      * @see #getDrawingCache(boolean)
22795      *
22796      * @deprecated The view drawing cache was largely made obsolete with the introduction of
22797      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
22798      * layers are largely unnecessary and can easily result in a net loss in performance due to the
22799      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
22800      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
22801      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
22802      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
22803      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
22804      * software-rendered usages are discouraged and have compatibility issues with hardware-only
22805      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
22806      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
22807      * reports or unit testing the {@link PixelCopy} API is recommended.
22808      */
22809     @Deprecated
getDrawingCache()22810     public Bitmap getDrawingCache() {
22811         return getDrawingCache(false);
22812     }
22813 
22814     /**
22815      * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
22816      * is null when caching is disabled. If caching is enabled and the cache is not ready,
22817      * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
22818      * draw from the cache when the cache is enabled. To benefit from the cache, you must
22819      * request the drawing cache by calling this method and draw it on screen if the
22820      * returned bitmap is not null.</p>
22821      *
22822      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
22823      * this method will create a bitmap of the same size as this view. Because this bitmap
22824      * will be drawn scaled by the parent ViewGroup, the result on screen might show
22825      * scaling artifacts. To avoid such artifacts, you should call this method by setting
22826      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
22827      * size than the view. This implies that your application must be able to handle this
22828      * size.</p>
22829      *
22830      * @param autoScale Indicates whether the generated bitmap should be scaled based on
22831      *        the current density of the screen when the application is in compatibility
22832      *        mode.
22833      *
22834      * @return A bitmap representing this view or null if cache is disabled.
22835      *
22836      * @see #setDrawingCacheEnabled(boolean)
22837      * @see #isDrawingCacheEnabled()
22838      * @see #buildDrawingCache(boolean)
22839      * @see #destroyDrawingCache()
22840      *
22841      * @deprecated The view drawing cache was largely made obsolete with the introduction of
22842      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
22843      * layers are largely unnecessary and can easily result in a net loss in performance due to the
22844      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
22845      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
22846      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
22847      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
22848      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
22849      * software-rendered usages are discouraged and have compatibility issues with hardware-only
22850      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
22851      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
22852      * reports or unit testing the {@link PixelCopy} API is recommended.
22853      */
22854     @Deprecated
getDrawingCache(boolean autoScale)22855     public Bitmap getDrawingCache(boolean autoScale) {
22856         if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
22857             return null;
22858         }
22859         if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
22860             buildDrawingCache(autoScale);
22861         }
22862         return autoScale ? mDrawingCache : mUnscaledDrawingCache;
22863     }
22864 
22865     /**
22866      * <p>Frees the resources used by the drawing cache. If you call
22867      * {@link #buildDrawingCache()} manually without calling
22868      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
22869      * should cleanup the cache with this method afterwards.</p>
22870      *
22871      * @see #setDrawingCacheEnabled(boolean)
22872      * @see #buildDrawingCache()
22873      * @see #getDrawingCache()
22874      *
22875      * @deprecated The view drawing cache was largely made obsolete with the introduction of
22876      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
22877      * layers are largely unnecessary and can easily result in a net loss in performance due to the
22878      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
22879      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
22880      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
22881      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
22882      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
22883      * software-rendered usages are discouraged and have compatibility issues with hardware-only
22884      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
22885      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
22886      * reports or unit testing the {@link PixelCopy} API is recommended.
22887      */
22888     @Deprecated
destroyDrawingCache()22889     public void destroyDrawingCache() {
22890         if (mDrawingCache != null) {
22891             mDrawingCache.recycle();
22892             mDrawingCache = null;
22893         }
22894         if (mUnscaledDrawingCache != null) {
22895             mUnscaledDrawingCache.recycle();
22896             mUnscaledDrawingCache = null;
22897         }
22898     }
22899 
22900     /**
22901      * Setting a solid background color for the drawing cache's bitmaps will improve
22902      * performance and memory usage. Note, though that this should only be used if this
22903      * view will always be drawn on top of a solid color.
22904      *
22905      * @param color The background color to use for the drawing cache's bitmap
22906      *
22907      * @see #setDrawingCacheEnabled(boolean)
22908      * @see #buildDrawingCache()
22909      * @see #getDrawingCache()
22910      *
22911      * @deprecated The view drawing cache was largely made obsolete with the introduction of
22912      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
22913      * layers are largely unnecessary and can easily result in a net loss in performance due to the
22914      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
22915      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
22916      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
22917      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
22918      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
22919      * software-rendered usages are discouraged and have compatibility issues with hardware-only
22920      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
22921      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
22922      * reports or unit testing the {@link PixelCopy} API is recommended.
22923      */
22924     @Deprecated
setDrawingCacheBackgroundColor(@olorInt int color)22925     public void setDrawingCacheBackgroundColor(@ColorInt int color) {
22926         if (color != mDrawingCacheBackgroundColor) {
22927             mDrawingCacheBackgroundColor = color;
22928             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
22929         }
22930     }
22931 
22932     /**
22933      * @see #setDrawingCacheBackgroundColor(int)
22934      *
22935      * @return The background color to used for the drawing cache's bitmap
22936      *
22937      * @deprecated The view drawing cache was largely made obsolete with the introduction of
22938      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
22939      * layers are largely unnecessary and can easily result in a net loss in performance due to the
22940      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
22941      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
22942      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
22943      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
22944      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
22945      * software-rendered usages are discouraged and have compatibility issues with hardware-only
22946      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
22947      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
22948      * reports or unit testing the {@link PixelCopy} API is recommended.
22949      */
22950     @Deprecated
22951     @ColorInt
getDrawingCacheBackgroundColor()22952     public int getDrawingCacheBackgroundColor() {
22953         return mDrawingCacheBackgroundColor;
22954     }
22955 
22956     /**
22957      * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
22958      *
22959      * @see #buildDrawingCache(boolean)
22960      *
22961      * @deprecated The view drawing cache was largely made obsolete with the introduction of
22962      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
22963      * layers are largely unnecessary and can easily result in a net loss in performance due to the
22964      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
22965      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
22966      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
22967      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
22968      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
22969      * software-rendered usages are discouraged and have compatibility issues with hardware-only
22970      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
22971      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
22972      * reports or unit testing the {@link PixelCopy} API is recommended.
22973      */
22974     @Deprecated
buildDrawingCache()22975     public void buildDrawingCache() {
22976         buildDrawingCache(false);
22977     }
22978 
22979     /**
22980      * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
22981      *
22982      * <p>If you call {@link #buildDrawingCache()} manually without calling
22983      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
22984      * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
22985      *
22986      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
22987      * this method will create a bitmap of the same size as this view. Because this bitmap
22988      * will be drawn scaled by the parent ViewGroup, the result on screen might show
22989      * scaling artifacts. To avoid such artifacts, you should call this method by setting
22990      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
22991      * size than the view. This implies that your application must be able to handle this
22992      * size.</p>
22993      *
22994      * <p>You should avoid calling this method when hardware acceleration is enabled. If
22995      * you do not need the drawing cache bitmap, calling this method will increase memory
22996      * usage and cause the view to be rendered in software once, thus negatively impacting
22997      * performance.</p>
22998      *
22999      * @see #getDrawingCache()
23000      * @see #destroyDrawingCache()
23001      *
23002      * @deprecated The view drawing cache was largely made obsolete with the introduction of
23003      * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache
23004      * layers are largely unnecessary and can easily result in a net loss in performance due to the
23005      * cost of creating and updating the layer. In the rare cases where caching layers are useful,
23006      * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware
23007      * rendering. For software-rendered snapshots of a small part of the View hierarchy or
23008      * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or
23009      * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these
23010      * software-rendered usages are discouraged and have compatibility issues with hardware-only
23011      * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE}
23012      * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback
23013      * reports or unit testing the {@link PixelCopy} API is recommended.
23014      */
23015     @Deprecated
buildDrawingCache(boolean autoScale)23016     public void buildDrawingCache(boolean autoScale) {
23017         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
23018                 mDrawingCache == null : mUnscaledDrawingCache == null)) {
23019             if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
23020                 Trace.traceBegin(Trace.TRACE_TAG_VIEW,
23021                         "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
23022             }
23023             try {
23024                 buildDrawingCacheImpl(autoScale);
23025             } finally {
23026                 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
23027             }
23028         }
23029     }
23030 
23031     /**
23032      * private, internal implementation of buildDrawingCache, used to enable tracing
23033      */
buildDrawingCacheImpl(boolean autoScale)23034     private void buildDrawingCacheImpl(boolean autoScale) {
23035         mCachingFailed = false;
23036 
23037         int width = mRight - mLeft;
23038         int height = mBottom - mTop;
23039 
23040         final AttachInfo attachInfo = mAttachInfo;
23041         final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
23042 
23043         if (autoScale && scalingRequired) {
23044             width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
23045             height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
23046         }
23047 
23048         final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
23049         final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
23050         final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
23051 
23052         final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
23053         final long drawingCacheSize =
23054                 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
23055         if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
23056             if (width > 0 && height > 0) {
23057                 Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
23058                         + " too large to fit into a software layer (or drawing cache), needs "
23059                         + projectedBitmapSize + " bytes, only "
23060                         + drawingCacheSize + " available");
23061             }
23062             destroyDrawingCache();
23063             mCachingFailed = true;
23064             return;
23065         }
23066 
23067         boolean clear = true;
23068         Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
23069 
23070         if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
23071             Bitmap.Config quality;
23072             if (!opaque) {
23073                 // Never pick ARGB_4444 because it looks awful
23074                 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
23075                 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
23076                     case DRAWING_CACHE_QUALITY_AUTO:
23077                     case DRAWING_CACHE_QUALITY_LOW:
23078                     case DRAWING_CACHE_QUALITY_HIGH:
23079                     default:
23080                         quality = Bitmap.Config.ARGB_8888;
23081                         break;
23082                 }
23083             } else {
23084                 // Optimization for translucent windows
23085                 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
23086                 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
23087             }
23088 
23089             // Try to cleanup memory
23090             if (bitmap != null) bitmap.recycle();
23091 
23092             try {
23093                 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
23094                         width, height, quality);
23095                 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
23096                 if (autoScale) {
23097                     mDrawingCache = bitmap;
23098                 } else {
23099                     mUnscaledDrawingCache = bitmap;
23100                 }
23101                 if (opaque && use32BitCache) bitmap.setHasAlpha(false);
23102             } catch (OutOfMemoryError e) {
23103                 // If there is not enough memory to create the bitmap cache, just
23104                 // ignore the issue as bitmap caches are not required to draw the
23105                 // view hierarchy
23106                 if (autoScale) {
23107                     mDrawingCache = null;
23108                 } else {
23109                     mUnscaledDrawingCache = null;
23110                 }
23111                 mCachingFailed = true;
23112                 return;
23113             }
23114 
23115             clear = drawingCacheBackgroundColor != 0;
23116         }
23117 
23118         Canvas canvas;
23119         if (attachInfo != null) {
23120             canvas = attachInfo.mCanvas;
23121             if (canvas == null) {
23122                 canvas = new Canvas();
23123             }
23124             canvas.setBitmap(bitmap);
23125             // Temporarily clobber the cached Canvas in case one of our children
23126             // is also using a drawing cache. Without this, the children would
23127             // steal the canvas by attaching their own bitmap to it and bad, bad
23128             // thing would happen (invisible views, corrupted drawings, etc.)
23129             attachInfo.mCanvas = null;
23130         } else {
23131             // This case should hopefully never or seldom happen
23132             canvas = new Canvas(bitmap);
23133         }
23134 
23135         if (clear) {
23136             bitmap.eraseColor(drawingCacheBackgroundColor);
23137         }
23138 
23139         computeScroll();
23140         final int restoreCount = canvas.save();
23141 
23142         if (autoScale && scalingRequired) {
23143             final float scale = attachInfo.mApplicationScale;
23144             canvas.scale(scale, scale);
23145         }
23146 
23147         canvas.translate(-mScrollX, -mScrollY);
23148 
23149         mPrivateFlags |= PFLAG_DRAWN;
23150         if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
23151                 mLayerType != LAYER_TYPE_NONE) {
23152             mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
23153         }
23154 
23155         // Fast path for layouts with no backgrounds
23156         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
23157             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
23158             dispatchDraw(canvas);
23159             drawAutofilledHighlight(canvas);
23160             if (mOverlay != null && !mOverlay.isEmpty()) {
23161                 mOverlay.getOverlayView().draw(canvas);
23162             }
23163         } else {
23164             draw(canvas);
23165         }
23166 
23167         canvas.restoreToCount(restoreCount);
23168         canvas.setBitmap(null);
23169 
23170         if (attachInfo != null) {
23171             // Restore the cached Canvas for our siblings
23172             attachInfo.mCanvas = canvas;
23173         }
23174     }
23175 
23176     /**
23177      * Create a snapshot of the view into a bitmap.  We should probably make
23178      * some form of this public, but should think about the API.
23179      *
23180      * @hide
23181      */
23182     @UnsupportedAppUsage
createSnapshot(ViewDebug.CanvasProvider canvasProvider, boolean skipChildren)23183     public Bitmap createSnapshot(ViewDebug.CanvasProvider canvasProvider, boolean skipChildren) {
23184         int width = mRight - mLeft;
23185         int height = mBottom - mTop;
23186 
23187         final AttachInfo attachInfo = mAttachInfo;
23188         final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
23189         width = (int) ((width * scale) + 0.5f);
23190         height = (int) ((height * scale) + 0.5f);
23191 
23192         Canvas oldCanvas = null;
23193         try {
23194             Canvas canvas = canvasProvider.getCanvas(this,
23195                     width > 0 ? width : 1, height > 0 ? height : 1);
23196 
23197             if (attachInfo != null) {
23198                 oldCanvas = attachInfo.mCanvas;
23199                 // Temporarily clobber the cached Canvas in case one of our children
23200                 // is also using a drawing cache. Without this, the children would
23201                 // steal the canvas by attaching their own bitmap to it and bad, bad
23202                 // things would happen (invisible views, corrupted drawings, etc.)
23203                 attachInfo.mCanvas = null;
23204             }
23205 
23206             computeScroll();
23207             final int restoreCount = canvas.save();
23208             canvas.scale(scale, scale);
23209             canvas.translate(-mScrollX, -mScrollY);
23210 
23211             // Temporarily remove the dirty mask
23212             int flags = mPrivateFlags;
23213             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
23214 
23215             // Fast path for layouts with no backgrounds
23216             if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
23217                 dispatchDraw(canvas);
23218                 drawAutofilledHighlight(canvas);
23219                 if (mOverlay != null && !mOverlay.isEmpty()) {
23220                     mOverlay.getOverlayView().draw(canvas);
23221                 }
23222             } else {
23223                 draw(canvas);
23224             }
23225 
23226             mPrivateFlags = flags;
23227             canvas.restoreToCount(restoreCount);
23228             return canvasProvider.createBitmap();
23229         } finally {
23230             if (oldCanvas != null) {
23231                 attachInfo.mCanvas = oldCanvas;
23232             }
23233         }
23234     }
23235 
23236     /**
23237      * Indicates whether this View is currently in edit mode. A View is usually
23238      * in edit mode when displayed within a developer tool. For instance, if
23239      * this View is being drawn by a visual user interface builder, this method
23240      * should return true.
23241      *
23242      * Subclasses should check the return value of this method to provide
23243      * different behaviors if their normal behavior might interfere with the
23244      * host environment. For instance: the class spawns a thread in its
23245      * constructor, the drawing code relies on device-specific features, etc.
23246      *
23247      * This method is usually checked in the drawing code of custom widgets.
23248      *
23249      * @return True if this View is in edit mode, false otherwise.
23250      */
isInEditMode()23251     public boolean isInEditMode() {
23252         return false;
23253     }
23254 
23255     /**
23256      * If the View draws content inside its padding and enables fading edges,
23257      * it needs to support padding offsets. Padding offsets are added to the
23258      * fading edges to extend the length of the fade so that it covers pixels
23259      * drawn inside the padding.
23260      *
23261      * Subclasses of this class should override this method if they need
23262      * to draw content inside the padding.
23263      *
23264      * @return True if padding offset must be applied, false otherwise.
23265      *
23266      * @see #getLeftPaddingOffset()
23267      * @see #getRightPaddingOffset()
23268      * @see #getTopPaddingOffset()
23269      * @see #getBottomPaddingOffset()
23270      *
23271      * @since CURRENT
23272      */
isPaddingOffsetRequired()23273     protected boolean isPaddingOffsetRequired() {
23274         return false;
23275     }
23276 
23277     /**
23278      * Amount by which to extend the left fading region. Called only when
23279      * {@link #isPaddingOffsetRequired()} returns true.
23280      *
23281      * @return The left padding offset in pixels.
23282      *
23283      * @see #isPaddingOffsetRequired()
23284      *
23285      * @since CURRENT
23286      */
getLeftPaddingOffset()23287     protected int getLeftPaddingOffset() {
23288         return 0;
23289     }
23290 
23291     /**
23292      * Amount by which to extend the right fading region. Called only when
23293      * {@link #isPaddingOffsetRequired()} returns true.
23294      *
23295      * @return The right padding offset in pixels.
23296      *
23297      * @see #isPaddingOffsetRequired()
23298      *
23299      * @since CURRENT
23300      */
getRightPaddingOffset()23301     protected int getRightPaddingOffset() {
23302         return 0;
23303     }
23304 
23305     /**
23306      * Amount by which to extend the top fading region. Called only when
23307      * {@link #isPaddingOffsetRequired()} returns true.
23308      *
23309      * @return The top padding offset in pixels.
23310      *
23311      * @see #isPaddingOffsetRequired()
23312      *
23313      * @since CURRENT
23314      */
getTopPaddingOffset()23315     protected int getTopPaddingOffset() {
23316         return 0;
23317     }
23318 
23319     /**
23320      * Amount by which to extend the bottom fading region. Called only when
23321      * {@link #isPaddingOffsetRequired()} returns true.
23322      *
23323      * @return The bottom padding offset in pixels.
23324      *
23325      * @see #isPaddingOffsetRequired()
23326      *
23327      * @since CURRENT
23328      */
getBottomPaddingOffset()23329     protected int getBottomPaddingOffset() {
23330         return 0;
23331     }
23332 
23333     /**
23334      * @hide
23335      * @param offsetRequired
23336      */
getFadeTop(boolean offsetRequired)23337     protected int getFadeTop(boolean offsetRequired) {
23338         int top = mPaddingTop;
23339         if (offsetRequired) top += getTopPaddingOffset();
23340         return top;
23341     }
23342 
23343     /**
23344      * @hide
23345      * @param offsetRequired
23346      */
getFadeHeight(boolean offsetRequired)23347     protected int getFadeHeight(boolean offsetRequired) {
23348         int padding = mPaddingTop;
23349         if (offsetRequired) padding += getTopPaddingOffset();
23350         return mBottom - mTop - mPaddingBottom - padding;
23351     }
23352 
23353     /**
23354      * <p>Indicates whether this view is attached to a hardware accelerated
23355      * window or not.</p>
23356      *
23357      * <p>Even if this method returns true, it does not mean that every call
23358      * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
23359      * accelerated {@link android.graphics.Canvas}. For instance, if this view
23360      * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
23361      * window is hardware accelerated,
23362      * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
23363      * return false, and this method will return true.</p>
23364      *
23365      * @return True if the view is attached to a window and the window is
23366      *         hardware accelerated; false in any other case.
23367      */
23368     @ViewDebug.ExportedProperty(category = "drawing")
isHardwareAccelerated()23369     public boolean isHardwareAccelerated() {
23370         return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
23371     }
23372 
23373     /**
23374      * Sets a rectangular area on this view to which the view will be clipped
23375      * when it is drawn. Setting the value to null will remove the clip bounds
23376      * and the view will draw normally, using its full bounds.
23377      *
23378      * @param clipBounds The rectangular area, in the local coordinates of
23379      * this view, to which future drawing operations will be clipped.
23380      */
setClipBounds(Rect clipBounds)23381     public void setClipBounds(Rect clipBounds) {
23382         if (clipBounds == mClipBounds
23383                 || (clipBounds != null && clipBounds.equals(mClipBounds))) {
23384             return;
23385         }
23386         if (clipBounds != null) {
23387             if (mClipBounds == null) {
23388                 mClipBounds = new Rect(clipBounds);
23389             } else {
23390                 mClipBounds.set(clipBounds);
23391             }
23392         } else {
23393             mClipBounds = null;
23394         }
23395         mRenderNode.setClipRect(mClipBounds);
23396         invalidateViewProperty(false, false);
23397     }
23398 
23399     /**
23400      * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
23401      *
23402      * @return A copy of the current clip bounds if clip bounds are set,
23403      * otherwise null.
23404      */
getClipBounds()23405     public Rect getClipBounds() {
23406         return (mClipBounds != null) ? new Rect(mClipBounds) : null;
23407     }
23408 
23409 
23410     /**
23411      * Populates an output rectangle with the clip bounds of the view,
23412      * returning {@code true} if successful or {@code false} if the view's
23413      * clip bounds are {@code null}.
23414      *
23415      * @param outRect rectangle in which to place the clip bounds of the view
23416      * @return {@code true} if successful or {@code false} if the view's
23417      *         clip bounds are {@code null}
23418      */
getClipBounds(Rect outRect)23419     public boolean getClipBounds(Rect outRect) {
23420         if (mClipBounds != null) {
23421             outRect.set(mClipBounds);
23422             return true;
23423         }
23424         return false;
23425     }
23426 
23427     /**
23428      * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
23429      * case of an active Animation being run on the view.
23430      */
applyLegacyAnimation(ViewGroup parent, long drawingTime, Animation a, boolean scalingRequired)23431     private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
23432             Animation a, boolean scalingRequired) {
23433         Transformation invalidationTransform;
23434         final int flags = parent.mGroupFlags;
23435         final boolean initialized = a.isInitialized();
23436         if (!initialized) {
23437             a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
23438             a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
23439             if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
23440             onAnimationStart();
23441         }
23442 
23443         final Transformation t = parent.getChildTransformation();
23444         boolean more = a.getTransformation(drawingTime, t, 1f);
23445         if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
23446             if (parent.mInvalidationTransformation == null) {
23447                 parent.mInvalidationTransformation = new Transformation();
23448             }
23449             invalidationTransform = parent.mInvalidationTransformation;
23450             a.getTransformation(drawingTime, invalidationTransform, 1f);
23451         } else {
23452             invalidationTransform = t;
23453         }
23454 
23455         if (more) {
23456             if (!a.willChangeBounds()) {
23457                 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
23458                         ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
23459                     parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
23460                 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
23461                     // The child need to draw an animation, potentially offscreen, so
23462                     // make sure we do not cancel invalidate requests
23463                     parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
23464                     parent.invalidate(mLeft, mTop, mRight, mBottom);
23465                 }
23466             } else {
23467                 if (parent.mInvalidateRegion == null) {
23468                     parent.mInvalidateRegion = new RectF();
23469                 }
23470                 final RectF region = parent.mInvalidateRegion;
23471                 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
23472                         invalidationTransform);
23473 
23474                 // The child need to draw an animation, potentially offscreen, so
23475                 // make sure we do not cancel invalidate requests
23476                 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
23477 
23478                 final int left = mLeft + (int) region.left;
23479                 final int top = mTop + (int) region.top;
23480                 parent.invalidate(left, top, left + (int) (region.width() + .5f),
23481                         top + (int) (region.height() + .5f));
23482             }
23483         }
23484         return more;
23485     }
23486 
23487     /**
23488      * This method is called by getDisplayList() when a display list is recorded for a View.
23489      * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
23490      */
setDisplayListProperties(RenderNode renderNode)23491     void setDisplayListProperties(RenderNode renderNode) {
23492         if (renderNode != null) {
23493             renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
23494             renderNode.setClipToBounds(mParent instanceof ViewGroup
23495                     && ((ViewGroup) mParent).getClipChildren());
23496 
23497             float alpha = 1;
23498             if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
23499                     ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
23500                 ViewGroup parentVG = (ViewGroup) mParent;
23501                 final Transformation t = parentVG.getChildTransformation();
23502                 if (parentVG.getChildStaticTransformation(this, t)) {
23503                     final int transformType = t.getTransformationType();
23504                     if (transformType != Transformation.TYPE_IDENTITY) {
23505                         if ((transformType & Transformation.TYPE_ALPHA) != 0) {
23506                             alpha = t.getAlpha();
23507                         }
23508                         if ((transformType & Transformation.TYPE_MATRIX) != 0) {
23509                             renderNode.setStaticMatrix(t.getMatrix());
23510                         }
23511                     }
23512                 }
23513             }
23514             if (mTransformationInfo != null) {
23515                 alpha *= getFinalAlpha();
23516                 if (alpha < 1) {
23517                     final int multipliedAlpha = (int) (255 * alpha);
23518                     if (onSetAlpha(multipliedAlpha)) {
23519                         alpha = 1;
23520                     }
23521                 }
23522                 renderNode.setAlpha(alpha);
23523             } else if (alpha < 1) {
23524                 renderNode.setAlpha(alpha);
23525             }
23526         }
23527     }
23528 
23529     /**
23530      * If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
23531      *
23532      * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
23533      * HW accelerated, it can't handle drawing RenderNodes.
23534      *
23535      * @hide
23536      */
drawsWithRenderNode(@onNull Canvas canvas)23537     protected final boolean drawsWithRenderNode(@NonNull Canvas canvas) {
23538         return mAttachInfo != null
23539                 && mAttachInfo.mHardwareAccelerated
23540                 && canvas.isHardwareAccelerated();
23541     }
23542 
23543     /**
23544      * This method is called by ViewGroup.drawChild() to have each child view draw itself.
23545      *
23546      * This is where the View specializes rendering behavior based on layer type,
23547      * and hardware acceleration.
23548      */
draw(@onNull Canvas canvas, ViewGroup parent, long drawingTime)23549     boolean draw(@NonNull Canvas canvas, ViewGroup parent, long drawingTime) {
23550 
23551         final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
23552 
23553         boolean drawingWithRenderNode = drawsWithRenderNode(canvas);
23554 
23555         boolean more = false;
23556         final boolean childHasIdentityMatrix = hasIdentityMatrix();
23557         final int parentFlags = parent.mGroupFlags;
23558 
23559         if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
23560             parent.getChildTransformation().clear();
23561             parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
23562         }
23563 
23564         Transformation transformToApply = null;
23565         boolean concatMatrix = false;
23566         final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
23567         final Animation a = getAnimation();
23568         if (a != null) {
23569             more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
23570             concatMatrix = a.willChangeTransformationMatrix();
23571             if (concatMatrix) {
23572                 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
23573             }
23574             transformToApply = parent.getChildTransformation();
23575         } else {
23576             if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
23577                 // No longer animating: clear out old animation matrix
23578                 mRenderNode.setAnimationMatrix(null);
23579                 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
23580             }
23581             if (!drawingWithRenderNode
23582                     && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
23583                 final Transformation t = parent.getChildTransformation();
23584                 final boolean hasTransform = parent.getChildStaticTransformation(this, t);
23585                 if (hasTransform) {
23586                     final int transformType = t.getTransformationType();
23587                     transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
23588                     concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
23589                 }
23590             }
23591         }
23592 
23593         concatMatrix |= !childHasIdentityMatrix;
23594 
23595         // Sets the flag as early as possible to allow draw() implementations
23596         // to call invalidate() successfully when doing animations
23597         mPrivateFlags |= PFLAG_DRAWN;
23598 
23599         if (!concatMatrix &&
23600                 (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
23601                         ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
23602                 canvas.quickReject(mLeft, mTop, mRight, mBottom) &&
23603                 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
23604             mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
23605             return more;
23606         }
23607         mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
23608 
23609         if (hardwareAcceleratedCanvas) {
23610             // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
23611             // retain the flag's value temporarily in the mRecreateDisplayList flag
23612             mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
23613             mPrivateFlags &= ~PFLAG_INVALIDATED;
23614         }
23615 
23616         RenderNode renderNode = null;
23617         Bitmap cache = null;
23618         int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
23619         if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
23620              if (layerType != LAYER_TYPE_NONE) {
23621                  // If not drawing with RenderNode, treat HW layers as SW
23622                  layerType = LAYER_TYPE_SOFTWARE;
23623                  buildDrawingCache(true);
23624             }
23625             cache = getDrawingCache(true);
23626         }
23627 
23628         if (drawingWithRenderNode) {
23629             // Delay getting the display list until animation-driven alpha values are
23630             // set up and possibly passed on to the view
23631             renderNode = updateDisplayListIfDirty();
23632             if (!renderNode.hasDisplayList()) {
23633                 // Uncommon, but possible. If a view is removed from the hierarchy during the call
23634                 // to getDisplayList(), the display list will be marked invalid and we should not
23635                 // try to use it again.
23636                 renderNode = null;
23637                 drawingWithRenderNode = false;
23638             }
23639         }
23640 
23641         int sx = 0;
23642         int sy = 0;
23643         if (!drawingWithRenderNode) {
23644             computeScroll();
23645             sx = mScrollX;
23646             sy = mScrollY;
23647         }
23648 
23649         final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
23650         final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
23651 
23652         int restoreTo = -1;
23653         if (!drawingWithRenderNode || transformToApply != null) {
23654             restoreTo = canvas.save();
23655         }
23656         if (offsetForScroll) {
23657             canvas.translate(mLeft - sx, mTop - sy);
23658         } else {
23659             if (!drawingWithRenderNode) {
23660                 canvas.translate(mLeft, mTop);
23661             }
23662             if (scalingRequired) {
23663                 if (drawingWithRenderNode) {
23664                     // TODO: Might not need this if we put everything inside the DL
23665                     restoreTo = canvas.save();
23666                 }
23667                 // mAttachInfo cannot be null, otherwise scalingRequired == false
23668                 final float scale = 1.0f / mAttachInfo.mApplicationScale;
23669                 canvas.scale(scale, scale);
23670             }
23671         }
23672 
23673         float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
23674         if (transformToApply != null
23675                 || alpha < 1
23676                 || !hasIdentityMatrix()
23677                 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
23678             if (transformToApply != null || !childHasIdentityMatrix) {
23679                 int transX = 0;
23680                 int transY = 0;
23681 
23682                 if (offsetForScroll) {
23683                     transX = -sx;
23684                     transY = -sy;
23685                 }
23686 
23687                 if (transformToApply != null) {
23688                     if (concatMatrix) {
23689                         if (drawingWithRenderNode) {
23690                             renderNode.setAnimationMatrix(transformToApply.getMatrix());
23691                         } else {
23692                             // Undo the scroll translation, apply the transformation matrix,
23693                             // then redo the scroll translate to get the correct result.
23694                             canvas.translate(-transX, -transY);
23695                             canvas.concat(transformToApply.getMatrix());
23696                             canvas.translate(transX, transY);
23697                         }
23698                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
23699                     }
23700 
23701                     float transformAlpha = transformToApply.getAlpha();
23702                     if (transformAlpha < 1) {
23703                         alpha *= transformAlpha;
23704                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
23705                     }
23706                 }
23707 
23708                 if (!childHasIdentityMatrix && !drawingWithRenderNode) {
23709                     canvas.translate(-transX, -transY);
23710                     canvas.concat(getMatrix());
23711                     canvas.translate(transX, transY);
23712                 }
23713             }
23714 
23715             // Deal with alpha if it is or used to be <1
23716             if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
23717                 if (alpha < 1) {
23718                     mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
23719                 } else {
23720                     mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
23721                 }
23722                 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
23723                 if (!drawingWithDrawingCache) {
23724                     final int multipliedAlpha = (int) (255 * alpha);
23725                     if (!onSetAlpha(multipliedAlpha)) {
23726                         if (drawingWithRenderNode) {
23727                             renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
23728                         } else if (layerType == LAYER_TYPE_NONE) {
23729                             canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
23730                                     multipliedAlpha);
23731                         }
23732                     } else {
23733                         // Alpha is handled by the child directly, clobber the layer's alpha
23734                         mPrivateFlags |= PFLAG_ALPHA_SET;
23735                     }
23736                 }
23737             }
23738         } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
23739             onSetAlpha(255);
23740             mPrivateFlags &= ~PFLAG_ALPHA_SET;
23741         }
23742 
23743         if (!drawingWithRenderNode) {
23744             // apply clips directly, since RenderNode won't do it for this draw
23745             if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
23746                 if (offsetForScroll) {
23747                     canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
23748                 } else {
23749                     if (!scalingRequired || cache == null) {
23750                         canvas.clipRect(0, 0, getWidth(), getHeight());
23751                     } else {
23752                         canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
23753                     }
23754                 }
23755             }
23756 
23757             if (mClipBounds != null) {
23758                 // clip bounds ignore scroll
23759                 canvas.clipRect(mClipBounds);
23760             }
23761         }
23762 
23763         if (!drawingWithDrawingCache) {
23764             if (drawingWithRenderNode) {
23765                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
23766                 ((RecordingCanvas) canvas).drawRenderNode(renderNode);
23767             } else {
23768                 // Fast path for layouts with no backgrounds
23769                 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
23770                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
23771                     dispatchDraw(canvas);
23772                 } else {
23773                     draw(canvas);
23774                 }
23775             }
23776         } else if (cache != null) {
23777             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
23778             if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
23779                 // no layer paint, use temporary paint to draw bitmap
23780                 Paint cachePaint = parent.mCachePaint;
23781                 if (cachePaint == null) {
23782                     cachePaint = new Paint();
23783                     cachePaint.setDither(false);
23784                     parent.mCachePaint = cachePaint;
23785                 }
23786                 cachePaint.setAlpha((int) (alpha * 255));
23787                 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
23788             } else {
23789                 // use layer paint to draw the bitmap, merging the two alphas, but also restore
23790                 int layerPaintAlpha = mLayerPaint.getAlpha();
23791                 if (alpha < 1) {
23792                     mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
23793                 }
23794                 canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
23795                 if (alpha < 1) {
23796                     mLayerPaint.setAlpha(layerPaintAlpha);
23797                 }
23798             }
23799         }
23800 
23801         if (restoreTo >= 0) {
23802             canvas.restoreToCount(restoreTo);
23803         }
23804 
23805         if (a != null && !more) {
23806             if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
23807                 onSetAlpha(255);
23808             }
23809             parent.finishAnimatingView(this, a);
23810         }
23811 
23812         if (more && hardwareAcceleratedCanvas) {
23813             if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
23814                 // alpha animations should cause the child to recreate its display list
23815                 invalidate(true);
23816             }
23817         }
23818 
23819         mRecreateDisplayList = false;
23820 
23821         return more;
23822     }
23823 
getDebugPaint()23824     static Paint getDebugPaint() {
23825         if (sDebugPaint == null) {
23826             sDebugPaint = new Paint();
23827             sDebugPaint.setAntiAlias(false);
23828         }
23829         return sDebugPaint;
23830     }
23831 
dipsToPixels(int dips)23832     final int dipsToPixels(int dips) {
23833         float scale = getContext().getResources().getDisplayMetrics().density;
23834         return (int) (dips * scale + 0.5f);
23835     }
23836 
debugDrawFocus(@onNull Canvas canvas)23837     private void debugDrawFocus(@NonNull Canvas canvas) {
23838         if (isFocused()) {
23839             final int cornerSquareSize = dipsToPixels(DEBUG_CORNERS_SIZE_DIP);
23840             final int l = mScrollX;
23841             final int r = l + mRight - mLeft;
23842             final int t = mScrollY;
23843             final int b = t + mBottom - mTop;
23844 
23845             final Paint paint = getDebugPaint();
23846             paint.setColor(DEBUG_CORNERS_COLOR);
23847 
23848             // Draw squares in corners.
23849             paint.setStyle(Paint.Style.FILL);
23850             canvas.drawRect(l, t, l + cornerSquareSize, t + cornerSquareSize, paint);
23851             canvas.drawRect(r - cornerSquareSize, t, r, t + cornerSquareSize, paint);
23852             canvas.drawRect(l, b - cornerSquareSize, l + cornerSquareSize, b, paint);
23853             canvas.drawRect(r - cornerSquareSize, b - cornerSquareSize, r, b, paint);
23854 
23855             // Draw big X across the view.
23856             paint.setStyle(Paint.Style.STROKE);
23857             canvas.drawLine(l, t, r, b, paint);
23858             canvas.drawLine(l, b, r, t, paint);
23859         }
23860     }
23861 
23862     /**
23863      * Manually render this view (and all of its children) to the given Canvas.
23864      * The view must have already done a full layout before this function is
23865      * called.  When implementing a view, implement
23866      * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
23867      * If you do need to override this method, call the superclass version.
23868      *
23869      * @param canvas The Canvas to which the View is rendered.
23870      */
23871     @CallSuper
draw(@onNull Canvas canvas)23872     public void draw(@NonNull Canvas canvas) {
23873         final int privateFlags = mPrivateFlags;
23874         mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
23875 
23876         /*
23877          * Draw traversal performs several drawing steps which must be executed
23878          * in the appropriate order:
23879          *
23880          *      1. Draw the background
23881          *      2. If necessary, save the canvas' layers to prepare for fading
23882          *      3. Draw view's content
23883          *      4. Draw children
23884          *      5. If necessary, draw the fading edges and restore layers
23885          *      6. Draw decorations (scrollbars for instance)
23886          *      7. If necessary, draw the default focus highlight
23887          */
23888 
23889         // Step 1, draw the background, if needed
23890         int saveCount;
23891 
23892         drawBackground(canvas);
23893 
23894         // skip step 2 & 5 if possible (common case)
23895         final int viewFlags = mViewFlags;
23896         boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
23897         boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
23898         if (!verticalEdges && !horizontalEdges) {
23899             // Step 3, draw the content
23900             onDraw(canvas);
23901 
23902             // Step 4, draw the children
23903             dispatchDraw(canvas);
23904 
23905             drawAutofilledHighlight(canvas);
23906 
23907             // Overlay is part of the content and draws beneath Foreground
23908             if (mOverlay != null && !mOverlay.isEmpty()) {
23909                 mOverlay.getOverlayView().dispatchDraw(canvas);
23910             }
23911 
23912             // Step 6, draw decorations (foreground, scrollbars)
23913             onDrawForeground(canvas);
23914 
23915             // Step 7, draw the default focus highlight
23916             drawDefaultFocusHighlight(canvas);
23917 
23918             if (isShowingLayoutBounds()) {
23919                 debugDrawFocus(canvas);
23920             }
23921 
23922             // we're done...
23923             return;
23924         }
23925 
23926         /*
23927          * Here we do the full fledged routine...
23928          * (this is an uncommon case where speed matters less,
23929          * this is why we repeat some of the tests that have been
23930          * done above)
23931          */
23932 
23933         boolean drawTop = false;
23934         boolean drawBottom = false;
23935         boolean drawLeft = false;
23936         boolean drawRight = false;
23937 
23938         float topFadeStrength = 0.0f;
23939         float bottomFadeStrength = 0.0f;
23940         float leftFadeStrength = 0.0f;
23941         float rightFadeStrength = 0.0f;
23942 
23943         // Step 2, save the canvas' layers
23944         int paddingLeft = mPaddingLeft;
23945 
23946         final boolean offsetRequired = isPaddingOffsetRequired();
23947         if (offsetRequired) {
23948             paddingLeft += getLeftPaddingOffset();
23949         }
23950 
23951         int left = mScrollX + paddingLeft;
23952         int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
23953         int top = mScrollY + getFadeTop(offsetRequired);
23954         int bottom = top + getFadeHeight(offsetRequired);
23955 
23956         if (offsetRequired) {
23957             right += getRightPaddingOffset();
23958             bottom += getBottomPaddingOffset();
23959         }
23960 
23961         final ScrollabilityCache scrollabilityCache = mScrollCache;
23962         final float fadeHeight = scrollabilityCache.fadingEdgeLength;
23963         int length = (int) fadeHeight;
23964 
23965         // clip the fade length if top and bottom fades overlap
23966         // overlapping fades produce odd-looking artifacts
23967         if (verticalEdges && (top + length > bottom - length)) {
23968             length = (bottom - top) / 2;
23969         }
23970 
23971         // also clip horizontal fades if necessary
23972         if (horizontalEdges && (left + length > right - length)) {
23973             length = (right - left) / 2;
23974         }
23975 
23976         if (verticalEdges) {
23977             topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
23978             drawTop = topFadeStrength * fadeHeight > 1.0f;
23979             bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
23980             drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
23981         }
23982 
23983         if (horizontalEdges) {
23984             leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
23985             drawLeft = leftFadeStrength * fadeHeight > 1.0f;
23986             rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
23987             drawRight = rightFadeStrength * fadeHeight > 1.0f;
23988         }
23989 
23990         saveCount = canvas.getSaveCount();
23991         int topSaveCount = -1;
23992         int bottomSaveCount = -1;
23993         int leftSaveCount = -1;
23994         int rightSaveCount = -1;
23995 
23996         int solidColor = getSolidColor();
23997         if (solidColor == 0) {
23998             if (drawTop) {
23999                 topSaveCount = canvas.saveUnclippedLayer(left, top, right, top + length);
24000             }
24001 
24002             if (drawBottom) {
24003                 bottomSaveCount = canvas.saveUnclippedLayer(left, bottom - length, right, bottom);
24004             }
24005 
24006             if (drawLeft) {
24007                 leftSaveCount = canvas.saveUnclippedLayer(left, top, left + length, bottom);
24008             }
24009 
24010             if (drawRight) {
24011                 rightSaveCount = canvas.saveUnclippedLayer(right - length, top, right, bottom);
24012             }
24013         } else {
24014             scrollabilityCache.setFadeColor(solidColor);
24015         }
24016 
24017         // Step 3, draw the content
24018         onDraw(canvas);
24019 
24020         // Step 4, draw the children
24021         dispatchDraw(canvas);
24022 
24023         // Step 5, draw the fade effect and restore layers
24024         final Paint p = scrollabilityCache.paint;
24025         final Matrix matrix = scrollabilityCache.matrix;
24026         final Shader fade = scrollabilityCache.shader;
24027 
24028         // must be restored in the reverse order that they were saved
24029         if (drawRight) {
24030             matrix.setScale(1, fadeHeight * rightFadeStrength);
24031             matrix.postRotate(90);
24032             matrix.postTranslate(right, top);
24033             fade.setLocalMatrix(matrix);
24034             p.setShader(fade);
24035             if (solidColor == 0) {
24036                 canvas.restoreUnclippedLayer(rightSaveCount, p);
24037 
24038             } else {
24039                 canvas.drawRect(right - length, top, right, bottom, p);
24040             }
24041         }
24042 
24043         if (drawLeft) {
24044             matrix.setScale(1, fadeHeight * leftFadeStrength);
24045             matrix.postRotate(-90);
24046             matrix.postTranslate(left, top);
24047             fade.setLocalMatrix(matrix);
24048             p.setShader(fade);
24049             if (solidColor == 0) {
24050                 canvas.restoreUnclippedLayer(leftSaveCount, p);
24051             } else {
24052                 canvas.drawRect(left, top, left + length, bottom, p);
24053             }
24054         }
24055 
24056         if (drawBottom) {
24057             matrix.setScale(1, fadeHeight * bottomFadeStrength);
24058             matrix.postRotate(180);
24059             matrix.postTranslate(left, bottom);
24060             fade.setLocalMatrix(matrix);
24061             p.setShader(fade);
24062             if (solidColor == 0) {
24063                 canvas.restoreUnclippedLayer(bottomSaveCount, p);
24064             } else {
24065                 canvas.drawRect(left, bottom - length, right, bottom, p);
24066             }
24067         }
24068 
24069         if (drawTop) {
24070             matrix.setScale(1, fadeHeight * topFadeStrength);
24071             matrix.postTranslate(left, top);
24072             fade.setLocalMatrix(matrix);
24073             p.setShader(fade);
24074             if (solidColor == 0) {
24075                 canvas.restoreUnclippedLayer(topSaveCount, p);
24076             } else {
24077                 canvas.drawRect(left, top, right, top + length, p);
24078             }
24079         }
24080 
24081         canvas.restoreToCount(saveCount);
24082 
24083         drawAutofilledHighlight(canvas);
24084 
24085         // Overlay is part of the content and draws beneath Foreground
24086         if (mOverlay != null && !mOverlay.isEmpty()) {
24087             mOverlay.getOverlayView().dispatchDraw(canvas);
24088         }
24089 
24090         // Step 6, draw decorations (foreground, scrollbars)
24091         onDrawForeground(canvas);
24092 
24093         // Step 7, draw the default focus highlight
24094         drawDefaultFocusHighlight(canvas);
24095 
24096         if (isShowingLayoutBounds()) {
24097             debugDrawFocus(canvas);
24098         }
24099     }
24100 
24101     /**
24102      * Draws the background onto the specified canvas.
24103      *
24104      * @param canvas Canvas on which to draw the background
24105      */
24106     @UnsupportedAppUsage
drawBackground(@onNull Canvas canvas)24107     private void drawBackground(@NonNull Canvas canvas) {
24108         final Drawable background = mBackground;
24109         if (background == null) {
24110             return;
24111         }
24112 
24113         setBackgroundBounds();
24114 
24115         // Attempt to use a display list if requested.
24116         if (canvas.isHardwareAccelerated() && mAttachInfo != null
24117                 && mAttachInfo.mThreadedRenderer != null) {
24118             mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
24119 
24120             final RenderNode renderNode = mBackgroundRenderNode;
24121             if (renderNode != null && renderNode.hasDisplayList()) {
24122                 setBackgroundRenderNodeProperties(renderNode);
24123                 ((RecordingCanvas) canvas).drawRenderNode(renderNode);
24124                 return;
24125             }
24126         }
24127 
24128         final int scrollX = mScrollX;
24129         final int scrollY = mScrollY;
24130         if ((scrollX | scrollY) == 0) {
24131             background.draw(canvas);
24132         } else {
24133             canvas.translate(scrollX, scrollY);
24134             background.draw(canvas);
24135             canvas.translate(-scrollX, -scrollY);
24136         }
24137     }
24138 
24139     /**
24140      * Sets the correct background bounds and rebuilds the outline, if needed.
24141      * <p/>
24142      * This is called by LayoutLib.
24143      */
setBackgroundBounds()24144     void setBackgroundBounds() {
24145         if (mBackgroundSizeChanged && mBackground != null) {
24146             mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
24147             mBackgroundSizeChanged = false;
24148             rebuildOutline();
24149         }
24150     }
24151 
setBackgroundRenderNodeProperties(RenderNode renderNode)24152     private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
24153         renderNode.setTranslationX(mScrollX);
24154         renderNode.setTranslationY(mScrollY);
24155     }
24156 
24157     /**
24158      * Creates a new display list or updates the existing display list for the
24159      * specified Drawable.
24160      *
24161      * @param drawable Drawable for which to create a display list
24162      * @param renderNode Existing RenderNode, or {@code null}
24163      * @return A valid display list for the specified drawable
24164      */
getDrawableRenderNode(Drawable drawable, RenderNode renderNode)24165     private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
24166         if (renderNode == null) {
24167             renderNode = RenderNode.create(drawable.getClass().getName(),
24168                     new ViewAnimationHostBridge(this));
24169             renderNode.setUsageHint(RenderNode.USAGE_BACKGROUND);
24170         }
24171 
24172         final Rect bounds = drawable.getBounds();
24173         final int width = bounds.width();
24174         final int height = bounds.height();
24175 
24176         // Hacky hack: Reset any stretch effects as those are applied during the draw pass
24177         // instead of being "stateful" like other RenderNode properties
24178         renderNode.clearStretch();
24179 
24180         final RecordingCanvas canvas = renderNode.beginRecording(width, height);
24181 
24182         // Reverse left/top translation done by drawable canvas, which will
24183         // instead be applied by rendernode's LTRB bounds below. This way, the
24184         // drawable's bounds match with its rendernode bounds and its content
24185         // will lie within those bounds in the rendernode tree.
24186         canvas.translate(-bounds.left, -bounds.top);
24187 
24188         try {
24189             drawable.draw(canvas);
24190         } finally {
24191             renderNode.endRecording();
24192         }
24193 
24194         // Set up drawable properties that are view-independent.
24195         renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
24196         renderNode.setProjectBackwards(drawable.isProjected());
24197         renderNode.setProjectionReceiver(true);
24198         renderNode.setClipToBounds(false);
24199         return renderNode;
24200     }
24201 
24202     /**
24203      * Returns the overlay for this view, creating it if it does not yet exist.
24204      * Adding drawables to the overlay will cause them to be displayed whenever
24205      * the view itself is redrawn. Objects in the overlay should be actively
24206      * managed: remove them when they should not be displayed anymore. The
24207      * overlay will always have the same size as its host view.
24208      *
24209      * <p>Note: Overlays do not currently work correctly with {@link
24210      * SurfaceView} or {@link TextureView}; contents in overlays for these
24211      * types of views may not display correctly.</p>
24212      *
24213      * @return The ViewOverlay object for this view.
24214      * @see ViewOverlay
24215      */
getOverlay()24216     public ViewOverlay getOverlay() {
24217         if (mOverlay == null) {
24218             mOverlay = new ViewOverlay(mContext, this);
24219         }
24220         return mOverlay;
24221     }
24222 
24223     /**
24224      * Override this if your view is known to always be drawn on top of a solid color background,
24225      * and needs to draw fading edges. Returning a non-zero color enables the view system to
24226      * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
24227      * should be set to 0xFF.
24228      *
24229      * @see #setVerticalFadingEdgeEnabled(boolean)
24230      * @see #setHorizontalFadingEdgeEnabled(boolean)
24231      *
24232      * @return The known solid color background for this view, or 0 if the color may vary
24233      */
24234     @ViewDebug.ExportedProperty(category = "drawing")
24235     @InspectableProperty
24236     @ColorInt
getSolidColor()24237     public int getSolidColor() {
24238         return 0;
24239     }
24240 
24241     /**
24242      * Build a human readable string representation of the specified view flags.
24243      *
24244      * @param flags the view flags to convert to a string
24245      * @return a String representing the supplied flags
24246      */
printFlags(int flags)24247     private static String printFlags(int flags) {
24248         String output = "";
24249         int numFlags = 0;
24250         if ((flags & FOCUSABLE) == FOCUSABLE) {
24251             output += "TAKES_FOCUS";
24252             numFlags++;
24253         }
24254 
24255         switch (flags & VISIBILITY_MASK) {
24256         case INVISIBLE:
24257             if (numFlags > 0) {
24258                 output += " ";
24259             }
24260             output += "INVISIBLE";
24261             // USELESS HERE numFlags++;
24262             break;
24263         case GONE:
24264             if (numFlags > 0) {
24265                 output += " ";
24266             }
24267             output += "GONE";
24268             // USELESS HERE numFlags++;
24269             break;
24270         default:
24271             break;
24272         }
24273         return output;
24274     }
24275 
24276     /**
24277      * Build a human readable string representation of the specified private
24278      * view flags.
24279      *
24280      * @param privateFlags the private view flags to convert to a string
24281      * @return a String representing the supplied flags
24282      */
printPrivateFlags(int privateFlags)24283     private static String printPrivateFlags(int privateFlags) {
24284         String output = "";
24285         int numFlags = 0;
24286 
24287         if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
24288             output += "WANTS_FOCUS";
24289             numFlags++;
24290         }
24291 
24292         if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
24293             if (numFlags > 0) {
24294                 output += " ";
24295             }
24296             output += "FOCUSED";
24297             numFlags++;
24298         }
24299 
24300         if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
24301             if (numFlags > 0) {
24302                 output += " ";
24303             }
24304             output += "SELECTED";
24305             numFlags++;
24306         }
24307 
24308         if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
24309             if (numFlags > 0) {
24310                 output += " ";
24311             }
24312             output += "IS_ROOT_NAMESPACE";
24313             numFlags++;
24314         }
24315 
24316         if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
24317             if (numFlags > 0) {
24318                 output += " ";
24319             }
24320             output += "HAS_BOUNDS";
24321             numFlags++;
24322         }
24323 
24324         if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
24325             if (numFlags > 0) {
24326                 output += " ";
24327             }
24328             output += "DRAWN";
24329             // USELESS HERE numFlags++;
24330         }
24331         return output;
24332     }
24333 
24334     /**
24335      * <p>Indicates whether or not this view's layout will be requested during
24336      * the next hierarchy layout pass.</p>
24337      *
24338      * @return true if the layout will be forced during next layout pass
24339      */
isLayoutRequested()24340     public boolean isLayoutRequested() {
24341         return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
24342     }
24343 
24344     /**
24345      * Return true if o is a ViewGroup that is laying out using optical bounds.
24346      * @hide
24347      */
isLayoutModeOptical(Object o)24348     public static boolean isLayoutModeOptical(Object o) {
24349         return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
24350     }
24351 
24352     /**
24353      * Enable measure/layout debugging on traces.
24354      *
24355      * @see Trace
24356      * @hide
24357      */
setTraceLayoutSteps(boolean traceLayoutSteps)24358     public static void setTraceLayoutSteps(boolean traceLayoutSteps) {
24359         sTraceLayoutSteps = traceLayoutSteps;
24360     }
24361 
24362     /**
24363      * Enable request layout tracing classes with {@code s} simple name.
24364      * <p>
24365      * When set, a {@link Trace} instant event and a log with the stacktrace is emitted every
24366      * time a requestLayout of a class matching {@code s} name happens.
24367      * This applies only to views attached from this point onwards.
24368      *
24369      * @see Trace#instant(long, String)
24370      * @hide
24371      */
setTracedRequestLayoutClassClass(String s)24372     public static void setTracedRequestLayoutClassClass(String s) {
24373         sTraceRequestLayoutClass = s;
24374     }
24375 
setOpticalFrame(int left, int top, int right, int bottom)24376     private boolean setOpticalFrame(int left, int top, int right, int bottom) {
24377         Insets parentInsets = mParent instanceof View ?
24378                 ((View) mParent).getOpticalInsets() : Insets.NONE;
24379         Insets childInsets = getOpticalInsets();
24380         return setFrame(
24381                 left   + parentInsets.left - childInsets.left,
24382                 top    + parentInsets.top  - childInsets.top,
24383                 right  + parentInsets.left + childInsets.right,
24384                 bottom + parentInsets.top  + childInsets.bottom);
24385     }
24386 
24387     /**
24388      * Assign a size and position to a view and all of its
24389      * descendants
24390      *
24391      * <p>This is the second phase of the layout mechanism.
24392      * (The first is measuring). In this phase, each parent calls
24393      * layout on all of its children to position them.
24394      * This is typically done using the child measurements
24395      * that were stored in the measure pass().</p>
24396      *
24397      * <p>Derived classes should not override this method.
24398      * Derived classes with children should override
24399      * onLayout. In that method, they should
24400      * call layout on each of their children.</p>
24401      *
24402      * @param l Left position, relative to parent
24403      * @param t Top position, relative to parent
24404      * @param r Right position, relative to parent
24405      * @param b Bottom position, relative to parent
24406      */
24407     @SuppressWarnings({"unchecked"})
layout(int l, int t, int r, int b)24408     public void layout(int l, int t, int r, int b) {
24409         if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
24410             if (isTraversalTracingEnabled()) {
24411                 Trace.beginSection(mTracingStrings.onMeasureBeforeLayout);
24412             }
24413             onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
24414             if (isTraversalTracingEnabled()) {
24415                 Trace.endSection();
24416             }
24417             mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
24418         }
24419 
24420         int oldL = mLeft;
24421         int oldT = mTop;
24422         int oldB = mBottom;
24423         int oldR = mRight;
24424 
24425         boolean changed = isLayoutModeOptical(mParent) ?
24426                 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
24427 
24428         if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
24429             if (isTraversalTracingEnabled()) {
24430                 Trace.beginSection(mTracingStrings.onLayout);
24431             }
24432             onLayout(changed, l, t, r, b);
24433             if (isTraversalTracingEnabled()) {
24434                 Trace.endSection();
24435             }
24436 
24437             if (shouldDrawRoundScrollbar()) {
24438                 if(mRoundScrollbarRenderer == null) {
24439                     mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
24440                 }
24441             } else {
24442                 mRoundScrollbarRenderer = null;
24443             }
24444 
24445             mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
24446 
24447             ListenerInfo li = mListenerInfo;
24448             if (li != null && li.mOnLayoutChangeListeners != null) {
24449                 ArrayList<OnLayoutChangeListener> listenersCopy =
24450                         (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
24451                 int numListeners = listenersCopy.size();
24452                 for (int i = 0; i < numListeners; ++i) {
24453                     listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
24454                 }
24455             }
24456         }
24457 
24458         final boolean wasLayoutValid = isLayoutValid();
24459 
24460         mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
24461         mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
24462 
24463         if (!wasLayoutValid && isFocused()) {
24464             mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
24465             if (canTakeFocus()) {
24466                 // We have a robust focus, so parents should no longer be wanting focus.
24467                 clearParentsWantFocus();
24468             } else if (getViewRootImpl() == null || !getViewRootImpl().isInLayout()) {
24469                 // This is a weird case. Most-likely the user, rather than ViewRootImpl, called
24470                 // layout. In this case, there's no guarantee that parent layouts will be evaluated
24471                 // and thus the safest action is to clear focus here.
24472                 clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
24473                 clearParentsWantFocus();
24474             } else if (!hasParentWantsFocus()) {
24475                 // original requestFocus was likely on this view directly, so just clear focus
24476                 clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
24477             }
24478             // otherwise, we let parents handle re-assigning focus during their layout passes.
24479         } else if ((mPrivateFlags & PFLAG_WANTS_FOCUS) != 0) {
24480             mPrivateFlags &= ~PFLAG_WANTS_FOCUS;
24481             View focused = findFocus();
24482             if (focused != null) {
24483                 // Try to restore focus as close as possible to our starting focus.
24484                 if (!restoreDefaultFocus() && !hasParentWantsFocus()) {
24485                     // Give up and clear focus once we've reached the top-most parent which wants
24486                     // focus.
24487                     focused.clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
24488                 }
24489             }
24490         }
24491 
24492         if ((mPrivateFlags3 & PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT) != 0) {
24493             mPrivateFlags3 &= ~PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
24494             notifyEnterOrExitForAutoFillIfNeeded(true);
24495         }
24496 
24497         notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
24498     }
24499 
hasParentWantsFocus()24500     private boolean hasParentWantsFocus() {
24501         ViewParent parent = mParent;
24502         while (parent instanceof ViewGroup) {
24503             ViewGroup pv = (ViewGroup) parent;
24504             if ((pv.mPrivateFlags & PFLAG_WANTS_FOCUS) != 0) {
24505                 return true;
24506             }
24507             parent = pv.mParent;
24508         }
24509         return false;
24510     }
24511 
24512     /**
24513      * Called from layout when this view should
24514      * assign a size and position to each of its children.
24515      *
24516      * Derived classes with children should override
24517      * this method and call layout on each of
24518      * their children.
24519      * @param changed This is a new size or position for this view
24520      * @param left Left position, relative to parent
24521      * @param top Top position, relative to parent
24522      * @param right Right position, relative to parent
24523      * @param bottom Bottom position, relative to parent
24524      */
onLayout(boolean changed, int left, int top, int right, int bottom)24525     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
24526     }
24527 
24528     /**
24529      * Assign a size and position to this view.
24530      *
24531      * This is called from layout.
24532      *
24533      * @param left Left position, relative to parent
24534      * @param top Top position, relative to parent
24535      * @param right Right position, relative to parent
24536      * @param bottom Bottom position, relative to parent
24537      * @return true if the new size and position are different than the
24538      *         previous ones
24539      * {@hide}
24540      */
24541     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
setFrame(int left, int top, int right, int bottom)24542     protected boolean setFrame(int left, int top, int right, int bottom) {
24543         boolean changed = false;
24544 
24545         if (DBG) {
24546             Log.d(VIEW_LOG_TAG, this + " View.setFrame(" + left + "," + top + ","
24547                     + right + "," + bottom + ")");
24548         }
24549 
24550         if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
24551             changed = true;
24552 
24553             // Remember our drawn bit
24554             int drawn = mPrivateFlags & PFLAG_DRAWN;
24555 
24556             int oldWidth = mRight - mLeft;
24557             int oldHeight = mBottom - mTop;
24558             int newWidth = right - left;
24559             int newHeight = bottom - top;
24560             boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
24561 
24562             // Invalidate our old position
24563             invalidate(sizeChanged);
24564 
24565             mLeft = left;
24566             mTop = top;
24567             mRight = right;
24568             mBottom = bottom;
24569             mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
24570 
24571             mPrivateFlags |= PFLAG_HAS_BOUNDS;
24572 
24573 
24574             if (sizeChanged) {
24575                 sizeChange(newWidth, newHeight, oldWidth, oldHeight);
24576             }
24577 
24578             if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
24579                 // If we are visible, force the DRAWN bit to on so that
24580                 // this invalidate will go through (at least to our parent).
24581                 // This is because someone may have invalidated this view
24582                 // before this call to setFrame came in, thereby clearing
24583                 // the DRAWN bit.
24584                 mPrivateFlags |= PFLAG_DRAWN;
24585                 invalidate(sizeChanged);
24586                 // parent display list may need to be recreated based on a change in the bounds
24587                 // of any child
24588                 invalidateParentCaches();
24589             }
24590 
24591             // Reset drawn bit to original value (invalidate turns it off)
24592             mPrivateFlags |= drawn;
24593 
24594             mBackgroundSizeChanged = true;
24595             mDefaultFocusHighlightSizeChanged = true;
24596             if (mForegroundInfo != null) {
24597                 mForegroundInfo.mBoundsChanged = true;
24598             }
24599 
24600             notifySubtreeAccessibilityStateChangedIfNeeded();
24601         }
24602         return changed;
24603     }
24604 
24605     /**
24606      * Assign a size and position to this view.
24607      *
24608      * This method is meant to be used in animations only as it applies this position and size
24609      * for the view only temporary and it can be changed back at any time by the layout.
24610      *
24611      * @param left Left position, relative to parent
24612      * @param top Top position, relative to parent
24613      * @param right Right position, relative to parent
24614      * @param bottom Bottom position, relative to parent
24615      *
24616      * @see #setLeft(int), #setRight(int), #setTop(int), #setBottom(int)
24617      */
setLeftTopRightBottom(int left, int top, int right, int bottom)24618     public final void setLeftTopRightBottom(int left, int top, int right, int bottom) {
24619         setFrame(left, top, right, bottom);
24620     }
24621 
sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight)24622     private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
24623         onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
24624         if (mOverlay != null) {
24625             mOverlay.getOverlayView().setRight(newWidth);
24626             mOverlay.getOverlayView().setBottom(newHeight);
24627         }
24628         // If this isn't laid out yet, focus assignment will be handled during the "deferment/
24629         // backtracking" of requestFocus during layout, so don't touch focus here.
24630         if (!sCanFocusZeroSized && isLayoutValid()
24631                 // Don't touch focus if animating
24632                 && !(mParent instanceof ViewGroup && ((ViewGroup) mParent).isLayoutSuppressed())) {
24633             if (newWidth <= 0 || newHeight <= 0) {
24634                 if (hasFocus()) {
24635                     clearFocus();
24636                     if (mParent instanceof ViewGroup) {
24637                         ((ViewGroup) mParent).clearFocusedInCluster();
24638                     }
24639                 }
24640                 clearAccessibilityFocus();
24641             } else if (oldWidth <= 0 || oldHeight <= 0) {
24642                 if (mParent != null && canTakeFocus()) {
24643                     mParent.focusableViewAvailable(this);
24644                 }
24645             }
24646         }
24647         rebuildOutline();
24648         if (onCheckIsTextEditor() || mHandwritingDelegatorCallback != null) {
24649             setHandwritingArea(new Rect(0, 0, newWidth, newHeight));
24650         }
24651     }
24652 
24653     /**
24654      * Finalize inflating a view from XML.  This is called as the last phase
24655      * of inflation, after all child views have been added.
24656      *
24657      * <p>Even if the subclass overrides onFinishInflate, they should always be
24658      * sure to call the super method, so that we get called.
24659      */
24660     @CallSuper
onFinishInflate()24661     protected void onFinishInflate() {
24662     }
24663 
24664     /**
24665      * Returns the resources associated with this view.
24666      *
24667      * @return Resources object.
24668      */
getResources()24669     public Resources getResources() {
24670         return mResources;
24671     }
24672 
24673     /**
24674      * Invalidates the specified Drawable.
24675      *
24676      * @param drawable the drawable to invalidate
24677      */
24678     @Override
invalidateDrawable(@onNull Drawable drawable)24679     public void invalidateDrawable(@NonNull Drawable drawable) {
24680         if (verifyDrawable(drawable)) {
24681             final Rect dirty = drawable.getDirtyBounds();
24682             final int scrollX = mScrollX;
24683             final int scrollY = mScrollY;
24684 
24685             invalidate(dirty.left + scrollX, dirty.top + scrollY,
24686                     dirty.right + scrollX, dirty.bottom + scrollY);
24687             rebuildOutline();
24688         }
24689     }
24690 
24691     /**
24692      * Schedules an action on a drawable to occur at a specified time.
24693      *
24694      * @param who the recipient of the action
24695      * @param what the action to run on the drawable
24696      * @param when the time at which the action must occur. Uses the
24697      *        {@link SystemClock#uptimeMillis} timebase.
24698      */
24699     @Override
scheduleDrawable(@onNull Drawable who, @NonNull Runnable what, long when)24700     public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
24701         if (verifyDrawable(who) && what != null) {
24702             final long delay = when - SystemClock.uptimeMillis();
24703             if (mAttachInfo != null) {
24704                 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
24705                         Choreographer.CALLBACK_ANIMATION, what, who,
24706                         Choreographer.subtractFrameDelay(delay));
24707             } else {
24708                 // Postpone the runnable until we know
24709                 // on which thread it needs to run.
24710                 getRunQueue().postDelayed(what, delay);
24711             }
24712         }
24713     }
24714 
24715     /**
24716      * Cancels a scheduled action on a drawable.
24717      *
24718      * @param who the recipient of the action
24719      * @param what the action to cancel
24720      */
24721     @Override
unscheduleDrawable(@onNull Drawable who, @NonNull Runnable what)24722     public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
24723         if (verifyDrawable(who) && what != null) {
24724             if (mAttachInfo != null) {
24725                 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
24726                         Choreographer.CALLBACK_ANIMATION, what, who);
24727             }
24728             getRunQueue().removeCallbacks(what);
24729         }
24730     }
24731 
24732     /**
24733      * Unschedule any events associated with the given Drawable.  This can be
24734      * used when selecting a new Drawable into a view, so that the previous
24735      * one is completely unscheduled.
24736      *
24737      * @param who The Drawable to unschedule.
24738      *
24739      * @see #drawableStateChanged
24740      */
unscheduleDrawable(Drawable who)24741     public void unscheduleDrawable(Drawable who) {
24742         if (mAttachInfo != null && who != null) {
24743             mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
24744                     Choreographer.CALLBACK_ANIMATION, null, who);
24745         }
24746     }
24747 
24748     /**
24749      * Resolve the Drawables depending on the layout direction. This is implicitly supposing
24750      * that the View directionality can and will be resolved before its Drawables.
24751      *
24752      * Will call {@link View#onResolveDrawables} when resolution is done.
24753      *
24754      * @hide
24755      */
resolveDrawables()24756     protected void resolveDrawables() {
24757         // Drawables resolution may need to happen before resolving the layout direction (which is
24758         // done only during the measure() call).
24759         // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
24760         // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
24761         // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
24762         // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
24763         // direction to be resolved as its resolved value will be the same as its raw value.
24764         if (!isLayoutDirectionResolved() &&
24765                 getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
24766             return;
24767         }
24768 
24769         final int layoutDirection = isLayoutDirectionResolved() ?
24770                 getLayoutDirection() : getRawLayoutDirection();
24771 
24772         if (mBackground != null) {
24773             mBackground.setLayoutDirection(layoutDirection);
24774         }
24775         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
24776             mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
24777         }
24778         if (mDefaultFocusHighlight != null) {
24779             mDefaultFocusHighlight.setLayoutDirection(layoutDirection);
24780         }
24781         mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
24782         onResolveDrawables(layoutDirection);
24783     }
24784 
areDrawablesResolved()24785     boolean areDrawablesResolved() {
24786         return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
24787     }
24788 
24789     /**
24790      * Called when layout direction has been resolved.
24791      *
24792      * The default implementation does nothing.
24793      *
24794      * @param layoutDirection The resolved layout direction.
24795      *
24796      * @see #LAYOUT_DIRECTION_LTR
24797      * @see #LAYOUT_DIRECTION_RTL
24798      *
24799      * @hide
24800      */
onResolveDrawables(@esolvedLayoutDir int layoutDirection)24801     public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
24802     }
24803 
24804     /**
24805      * @hide
24806      */
24807     @TestApi
resetResolvedDrawables()24808     protected void resetResolvedDrawables() {
24809         resetResolvedDrawablesInternal();
24810     }
24811 
resetResolvedDrawablesInternal()24812     void resetResolvedDrawablesInternal() {
24813         mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
24814     }
24815 
24816     /**
24817      * If your view subclass is displaying its own Drawable objects, it should
24818      * override this function and return true for any Drawable it is
24819      * displaying.  This allows animations for those drawables to be
24820      * scheduled.
24821      *
24822      * <p>Be sure to call through to the super class when overriding this
24823      * function.
24824      *
24825      * @param who The Drawable to verify.  Return true if it is one you are
24826      *            displaying, else return the result of calling through to the
24827      *            super class.
24828      *
24829      * @return boolean If true then the Drawable is being displayed in the
24830      *         view; else false and it is not allowed to animate.
24831      *
24832      * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
24833      * @see #drawableStateChanged()
24834      */
24835     @CallSuper
verifyDrawable(@onNull Drawable who)24836     protected boolean verifyDrawable(@NonNull Drawable who) {
24837         // Avoid verifying the scroll bar drawable so that we don't end up in
24838         // an invalidation loop. This effectively prevents the scroll bar
24839         // drawable from triggering invalidations and scheduling runnables.
24840         return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who)
24841                 || (mDefaultFocusHighlight == who);
24842     }
24843 
24844     /**
24845      * This function is called whenever the state of the view changes in such
24846      * a way that it impacts the state of drawables being shown.
24847      * <p>
24848      * If the View has a StateListAnimator, it will also be called to run necessary state
24849      * change animations.
24850      * <p>
24851      * Be sure to call through to the superclass when overriding this function.
24852      *
24853      * @see Drawable#setState(int[])
24854      */
24855     @CallSuper
drawableStateChanged()24856     protected void drawableStateChanged() {
24857         final int[] state = getDrawableState();
24858         boolean changed = false;
24859 
24860         final Drawable bg = mBackground;
24861         if (bg != null && bg.isStateful()) {
24862             changed |= bg.setState(state);
24863         }
24864 
24865         final Drawable hl = mDefaultFocusHighlight;
24866         if (hl != null && hl.isStateful()) {
24867             changed |= hl.setState(state);
24868         }
24869 
24870         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
24871         if (fg != null && fg.isStateful()) {
24872             changed |= fg.setState(state);
24873         }
24874 
24875         if (mScrollCache != null) {
24876             final Drawable scrollBar = mScrollCache.scrollBar;
24877             if (scrollBar != null && scrollBar.isStateful()) {
24878                 changed |= scrollBar.setState(state)
24879                         && mScrollCache.state != ScrollabilityCache.OFF;
24880             }
24881         }
24882 
24883         if (mStateListAnimator != null) {
24884             mStateListAnimator.setState(state);
24885         }
24886 
24887         if (!isAggregatedVisible()) {
24888             // If we're not visible, skip any animated changes
24889             jumpDrawablesToCurrentState();
24890         }
24891 
24892         if (changed) {
24893             invalidate();
24894         }
24895     }
24896 
24897     /**
24898      * This function is called whenever the view hotspot changes and needs to
24899      * be propagated to drawables or child views managed by the view.
24900      * <p>
24901      * Dispatching to child views is handled by
24902      * {@link #dispatchDrawableHotspotChanged(float, float)}.
24903      * <p>
24904      * Be sure to call through to the superclass when overriding this function.
24905      *
24906      * @param x hotspot x coordinate
24907      * @param y hotspot y coordinate
24908      */
24909     @CallSuper
drawableHotspotChanged(float x, float y)24910     public void drawableHotspotChanged(float x, float y) {
24911         if (mBackground != null) {
24912             mBackground.setHotspot(x, y);
24913         }
24914         if (mDefaultFocusHighlight != null) {
24915             mDefaultFocusHighlight.setHotspot(x, y);
24916         }
24917         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
24918             mForegroundInfo.mDrawable.setHotspot(x, y);
24919         }
24920 
24921         dispatchDrawableHotspotChanged(x, y);
24922     }
24923 
24924     /**
24925      * Dispatches drawableHotspotChanged to all of this View's children.
24926      *
24927      * @param x hotspot x coordinate
24928      * @param y hotspot y coordinate
24929      * @see #drawableHotspotChanged(float, float)
24930      */
dispatchDrawableHotspotChanged(float x, float y)24931     public void dispatchDrawableHotspotChanged(float x, float y) {
24932     }
24933 
24934     /**
24935      * Call this to force a view to update its drawable state. This will cause
24936      * drawableStateChanged to be called on this view. Views that are interested
24937      * in the new state should call getDrawableState.
24938      *
24939      * @see #drawableStateChanged
24940      * @see #getDrawableState
24941      */
refreshDrawableState()24942     public void refreshDrawableState() {
24943         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
24944         drawableStateChanged();
24945 
24946         ViewParent parent = mParent;
24947         if (parent != null) {
24948             parent.childDrawableStateChanged(this);
24949         }
24950     }
24951 
24952     /**
24953      * Create a default focus highlight if it doesn't exist.
24954      * @return a default focus highlight.
24955      */
getDefaultFocusHighlightDrawable()24956     private Drawable getDefaultFocusHighlightDrawable() {
24957         if (mDefaultFocusHighlightCache == null) {
24958             if (mContext != null) {
24959                 final int[] attrs = new int[] { android.R.attr.selectableItemBackground };
24960                 final TypedArray ta = mContext.obtainStyledAttributes(attrs);
24961                 mDefaultFocusHighlightCache = ta.getDrawable(0);
24962                 ta.recycle();
24963             }
24964         }
24965         return mDefaultFocusHighlightCache;
24966     }
24967 
24968     /**
24969      * Set the current default focus highlight.
24970      * @param highlight the highlight drawable, or {@code null} if it's no longer needed.
24971      */
setDefaultFocusHighlight(Drawable highlight)24972     private void setDefaultFocusHighlight(Drawable highlight) {
24973         mDefaultFocusHighlight = highlight;
24974         mDefaultFocusHighlightSizeChanged = true;
24975         if (highlight != null) {
24976             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
24977                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
24978             }
24979             highlight.setLayoutDirection(getLayoutDirection());
24980             if (highlight.isStateful()) {
24981                 highlight.setState(getDrawableState());
24982             }
24983             if (isAttachedToWindow()) {
24984                 highlight.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
24985             }
24986             // Set callback last, since the view may still be initializing.
24987             highlight.setCallback(this);
24988         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
24989                 && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
24990             mPrivateFlags |= PFLAG_SKIP_DRAW;
24991         }
24992         invalidate();
24993     }
24994 
24995     /**
24996      * Check whether we need to draw a default focus highlight when this view gets focused,
24997      * which requires:
24998      * <ul>
24999      *     <li>In both background and foreground, {@link android.R.attr#state_focused}
25000      *         is not defined.</li>
25001      *     <li>This view is not in touch mode.</li>
25002      *     <li>This view doesn't opt out for a default focus highlight, via
25003      *         {@link #setDefaultFocusHighlightEnabled(boolean)}.</li>
25004      *     <li>This view is attached to window.</li>
25005      * </ul>
25006      * @return {@code true} if a default focus highlight is needed.
25007      * @hide
25008      */
25009     @TestApi
isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground)25010     public boolean isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground) {
25011         final boolean lackFocusState = (background == null || !background.isStateful()
25012                 || !background.hasFocusStateSpecified())
25013                 && (foreground == null || !foreground.isStateful()
25014                 || !foreground.hasFocusStateSpecified());
25015         return !isInTouchMode() && getDefaultFocusHighlightEnabled() && lackFocusState
25016                 && isAttachedToWindow() && sUseDefaultFocusHighlight;
25017     }
25018 
25019     /**
25020      * When this view is focused, switches on/off the default focused highlight.
25021      * <p>
25022      * This always happens when this view is focused, and only at this moment the default focus
25023      * highlight can be visible.
25024      */
switchDefaultFocusHighlight()25025     private void switchDefaultFocusHighlight() {
25026         if (isFocused()) {
25027             final boolean needed = isDefaultFocusHighlightNeeded(mBackground,
25028                     mForegroundInfo == null ? null : mForegroundInfo.mDrawable);
25029             final boolean active = mDefaultFocusHighlight != null;
25030             if (needed && !active) {
25031                 setDefaultFocusHighlight(getDefaultFocusHighlightDrawable());
25032             } else if (!needed && active) {
25033                 // The highlight is no longer needed, so tear it down.
25034                 setDefaultFocusHighlight(null);
25035             }
25036         }
25037     }
25038 
25039     /**
25040      * Draw the default focus highlight onto the canvas if there is one and this view is focused.
25041      * @param canvas the canvas where we're drawing the highlight.
25042      */
drawDefaultFocusHighlight(@onNull Canvas canvas)25043     private void drawDefaultFocusHighlight(@NonNull Canvas canvas) {
25044         if (mDefaultFocusHighlight != null && isFocused()) {
25045             if (mDefaultFocusHighlightSizeChanged) {
25046                 mDefaultFocusHighlightSizeChanged = false;
25047                 final int l = mScrollX;
25048                 final int r = l + mRight - mLeft;
25049                 final int t = mScrollY;
25050                 final int b = t + mBottom - mTop;
25051                 mDefaultFocusHighlight.setBounds(l, t, r, b);
25052             }
25053             mDefaultFocusHighlight.draw(canvas);
25054         }
25055     }
25056 
25057     /**
25058      * Return an array of resource IDs of the drawable states representing the
25059      * current state of the view.
25060      *
25061      * @return The current drawable state
25062      *
25063      * @see Drawable#setState(int[])
25064      * @see #drawableStateChanged()
25065      * @see #onCreateDrawableState(int)
25066      */
getDrawableState()25067     public final int[] getDrawableState() {
25068         if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
25069             return mDrawableState;
25070         } else {
25071             mDrawableState = onCreateDrawableState(0);
25072             mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
25073             return mDrawableState;
25074         }
25075     }
25076 
25077     /**
25078      * Generate the new {@link android.graphics.drawable.Drawable} state for
25079      * this view. This is called by the view
25080      * system when the cached Drawable state is determined to be invalid.  To
25081      * retrieve the current state, you should use {@link #getDrawableState}.
25082      *
25083      * @param extraSpace if non-zero, this is the number of extra entries you
25084      * would like in the returned array in which you can place your own
25085      * states.
25086      *
25087      * @return Returns an array holding the current {@link Drawable} state of
25088      * the view.
25089      *
25090      * @see #mergeDrawableStates(int[], int[])
25091      */
onCreateDrawableState(int extraSpace)25092     protected int[] onCreateDrawableState(int extraSpace) {
25093         if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
25094                 mParent instanceof View) {
25095             return ((View) mParent).onCreateDrawableState(extraSpace);
25096         }
25097 
25098         int[] drawableState;
25099 
25100         int privateFlags = mPrivateFlags;
25101 
25102         int viewStateIndex = 0;
25103         if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
25104         if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
25105         if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
25106         if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
25107         if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
25108         if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
25109         if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested) {
25110             // This is set if HW acceleration is requested, even if the current
25111             // process doesn't allow it.  This is just to allow app preview
25112             // windows to better match their app.
25113             viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
25114         }
25115         if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
25116 
25117         final int privateFlags2 = mPrivateFlags2;
25118         if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
25119             viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
25120         }
25121         if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
25122             viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
25123         }
25124 
25125         drawableState = StateSet.get(viewStateIndex);
25126 
25127         //noinspection ConstantIfStatement
25128         if (false) {
25129             Log.i("View", "drawableStateIndex=" + viewStateIndex);
25130             Log.i("View", toString()
25131                     + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
25132                     + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
25133                     + " fo=" + hasFocus()
25134                     + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
25135                     + " wf=" + hasWindowFocus()
25136                     + ": " + Arrays.toString(drawableState));
25137         }
25138 
25139         if (extraSpace == 0) {
25140             return drawableState;
25141         }
25142 
25143         final int[] fullState;
25144         if (drawableState != null) {
25145             fullState = new int[drawableState.length + extraSpace];
25146             System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
25147         } else {
25148             fullState = new int[extraSpace];
25149         }
25150 
25151         return fullState;
25152     }
25153 
25154     /**
25155      * Merge your own state values in <var>additionalState</var> into the base
25156      * state values <var>baseState</var> that were returned by
25157      * {@link #onCreateDrawableState(int)}.
25158      *
25159      * @param baseState The base state values returned by
25160      * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
25161      * own additional state values.
25162      *
25163      * @param additionalState The additional state values you would like
25164      * added to <var>baseState</var>; this array is not modified.
25165      *
25166      * @return As a convenience, the <var>baseState</var> array you originally
25167      * passed into the function is returned.
25168      *
25169      * @see #onCreateDrawableState(int)
25170      */
mergeDrawableStates(int[] baseState, int[] additionalState)25171     protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
25172         final int N = baseState.length;
25173         int i = N - 1;
25174         while (i >= 0 && baseState[i] == 0) {
25175             i--;
25176         }
25177         System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
25178         return baseState;
25179     }
25180 
25181     /**
25182      * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
25183      * on all Drawable objects associated with this view.
25184      * <p>
25185      * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
25186      * attached to this view.
25187      */
25188     @CallSuper
jumpDrawablesToCurrentState()25189     public void jumpDrawablesToCurrentState() {
25190         if (mBackground != null) {
25191             mBackground.jumpToCurrentState();
25192         }
25193         if (mStateListAnimator != null) {
25194             mStateListAnimator.jumpToCurrentState();
25195         }
25196         if (mDefaultFocusHighlight != null) {
25197             mDefaultFocusHighlight.jumpToCurrentState();
25198         }
25199         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
25200             mForegroundInfo.mDrawable.jumpToCurrentState();
25201         }
25202     }
25203 
25204     /**
25205      * Sets the background color for this view.
25206      * @param color the color of the background
25207      */
25208     @RemotableViewMethod
setBackgroundColor(@olorInt int color)25209     public void setBackgroundColor(@ColorInt int color) {
25210         if (mBackground instanceof ColorDrawable) {
25211             ((ColorDrawable) mBackground.mutate()).setColor(color);
25212             computeOpaqueFlags();
25213             mBackgroundResource = 0;
25214         } else {
25215             setBackground(new ColorDrawable(color));
25216         }
25217     }
25218 
25219     /**
25220      * Set the background to a given resource. The resource should refer to
25221      * a Drawable object or 0 to remove the background.
25222      * @param resid The identifier of the resource.
25223      *
25224      * @attr ref android.R.styleable#View_background
25225      */
25226     @RemotableViewMethod
setBackgroundResource(@rawableRes int resid)25227     public void setBackgroundResource(@DrawableRes int resid) {
25228         if (resid != 0 && resid == mBackgroundResource) {
25229             return;
25230         }
25231 
25232         Drawable d = null;
25233         if (resid != 0) {
25234             d = mContext.getDrawable(resid);
25235         }
25236         setBackground(d);
25237 
25238         mBackgroundResource = resid;
25239     }
25240 
25241     /**
25242      * Set the background to a given Drawable, or remove the background. If the
25243      * background has padding, this View's padding is set to the background's
25244      * padding. However, when a background is removed, this View's padding isn't
25245      * touched. If setting the padding is desired, please use
25246      * {@link #setPadding(int, int, int, int)}.
25247      *
25248      * @param background The Drawable to use as the background, or null to remove the
25249      *        background
25250      */
setBackground(Drawable background)25251     public void setBackground(Drawable background) {
25252         //noinspection deprecation
25253         setBackgroundDrawable(background);
25254     }
25255 
25256     /**
25257      * @deprecated use {@link #setBackground(Drawable)} instead
25258      */
25259     @Deprecated
setBackgroundDrawable(Drawable background)25260     public void setBackgroundDrawable(Drawable background) {
25261         computeOpaqueFlags();
25262 
25263         if (background == mBackground) {
25264             return;
25265         }
25266 
25267         boolean requestLayout = false;
25268 
25269         mBackgroundResource = 0;
25270 
25271         /*
25272          * Regardless of whether we're setting a new background or not, we want
25273          * to clear the previous drawable. setVisible first while we still have the callback set.
25274          */
25275         if (mBackground != null) {
25276             if (isAttachedToWindow()) {
25277                 mBackground.setVisible(false, false);
25278             }
25279             mBackground.setCallback(null);
25280             unscheduleDrawable(mBackground);
25281         }
25282 
25283         if (background != null) {
25284             Rect padding = sThreadLocal.get();
25285             if (padding == null) {
25286                 padding = new Rect();
25287                 sThreadLocal.set(padding);
25288             }
25289             resetResolvedDrawablesInternal();
25290             background.setLayoutDirection(getLayoutDirection());
25291             if (background.getPadding(padding)) {
25292                 resetResolvedPaddingInternal();
25293                 switch (background.getLayoutDirection()) {
25294                     case LAYOUT_DIRECTION_RTL:
25295                         mUserPaddingLeftInitial = padding.right;
25296                         mUserPaddingRightInitial = padding.left;
25297                         internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
25298                         break;
25299                     case LAYOUT_DIRECTION_LTR:
25300                     default:
25301                         mUserPaddingLeftInitial = padding.left;
25302                         mUserPaddingRightInitial = padding.right;
25303                         internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
25304                 }
25305                 mLeftPaddingDefined = false;
25306                 mRightPaddingDefined = false;
25307             }
25308 
25309             // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
25310             // if it has a different minimum size, we should layout again
25311             if (mBackground == null
25312                     || mBackground.getMinimumHeight() != background.getMinimumHeight()
25313                     || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
25314                 requestLayout = true;
25315             }
25316 
25317             // Set mBackground before we set this as the callback and start making other
25318             // background drawable state change calls. In particular, the setVisible call below
25319             // can result in drawables attempting to start animations or otherwise invalidate,
25320             // which requires the view set as the callback (us) to recognize the drawable as
25321             // belonging to it as per verifyDrawable.
25322             mBackground = background;
25323             if (background.isStateful()) {
25324                 background.setState(getDrawableState());
25325             }
25326             if (isAttachedToWindow()) {
25327                 background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
25328             }
25329 
25330             applyBackgroundTint();
25331 
25332             // Set callback last, since the view may still be initializing.
25333             background.setCallback(this);
25334 
25335             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
25336                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
25337                 requestLayout = true;
25338             }
25339         } else {
25340             /* Remove the background */
25341             mBackground = null;
25342             if ((mViewFlags & WILL_NOT_DRAW) != 0
25343                     && (mDefaultFocusHighlight == null)
25344                     && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
25345                 mPrivateFlags |= PFLAG_SKIP_DRAW;
25346             }
25347 
25348             /*
25349              * When the background is set, we try to apply its padding to this
25350              * View. When the background is removed, we don't touch this View's
25351              * padding. This is noted in the Javadocs. Hence, we don't need to
25352              * requestLayout(), the invalidate() below is sufficient.
25353              */
25354 
25355             // The old background's minimum size could have affected this
25356             // View's layout, so let's requestLayout
25357             requestLayout = true;
25358         }
25359 
25360         computeOpaqueFlags();
25361 
25362         if (requestLayout) {
25363             requestLayout();
25364         }
25365 
25366         mBackgroundSizeChanged = true;
25367         invalidate(true);
25368         invalidateOutline();
25369     }
25370 
25371     /**
25372      * Gets the background drawable
25373      *
25374      * @return The drawable used as the background for this view, if any.
25375      *
25376      * @see #setBackground(Drawable)
25377      *
25378      * @attr ref android.R.styleable#View_background
25379      */
25380     @InspectableProperty
getBackground()25381     public Drawable getBackground() {
25382         return mBackground;
25383     }
25384 
25385     /**
25386      * Applies a tint to the background drawable. Does not modify the current tint
25387      * mode, which is {@link BlendMode#SRC_IN} by default.
25388      * <p>
25389      * Subsequent calls to {@link #setBackground(Drawable)} will automatically
25390      * mutate the drawable and apply the specified tint and tint mode using
25391      * {@link Drawable#setTintList(ColorStateList)}.
25392      *
25393      * @param tint the tint to apply, may be {@code null} to clear tint
25394      *
25395      * @attr ref android.R.styleable#View_backgroundTint
25396      * @see #getBackgroundTintList()
25397      * @see Drawable#setTintList(ColorStateList)
25398      */
25399     @RemotableViewMethod
setBackgroundTintList(@ullable ColorStateList tint)25400     public void setBackgroundTintList(@Nullable ColorStateList tint) {
25401         if (mBackgroundTint == null) {
25402             mBackgroundTint = new TintInfo();
25403         }
25404         mBackgroundTint.mTintList = tint;
25405         mBackgroundTint.mHasTintList = true;
25406 
25407         applyBackgroundTint();
25408     }
25409 
25410     /**
25411      * Return the tint applied to the background drawable, if specified.
25412      *
25413      * @return the tint applied to the background drawable
25414      * @attr ref android.R.styleable#View_backgroundTint
25415      * @see #setBackgroundTintList(ColorStateList)
25416      */
25417     @InspectableProperty(name = "backgroundTint")
25418     @Nullable
getBackgroundTintList()25419     public ColorStateList getBackgroundTintList() {
25420         return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
25421     }
25422 
25423     /**
25424      * Specifies the blending mode used to apply the tint specified by
25425      * {@link #setBackgroundTintList(ColorStateList)}} to the background
25426      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
25427      *
25428      * @param tintMode the blending mode used to apply the tint, may be
25429      *                 {@code null} to clear tint
25430      * @attr ref android.R.styleable#View_backgroundTintMode
25431      * @see #getBackgroundTintMode()
25432      * @see Drawable#setTintMode(PorterDuff.Mode)
25433      */
setBackgroundTintMode(@ullable PorterDuff.Mode tintMode)25434     public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
25435         BlendMode mode = null;
25436         if (tintMode != null) {
25437             mode = BlendMode.fromValue(tintMode.nativeInt);
25438         }
25439 
25440         setBackgroundTintBlendMode(mode);
25441     }
25442 
25443     /**
25444      * Specifies the blending mode used to apply the tint specified by
25445      * {@link #setBackgroundTintList(ColorStateList)}} to the background
25446      * drawable. The default mode is {@link BlendMode#SRC_IN}.
25447      *
25448      * @param blendMode the blending mode used to apply the tint, may be
25449      *                 {@code null} to clear tint
25450      * @attr ref android.R.styleable#View_backgroundTintMode
25451      * @see #getBackgroundTintMode()
25452      * @see Drawable#setTintBlendMode(BlendMode)
25453      */
25454     @RemotableViewMethod
setBackgroundTintBlendMode(@ullable BlendMode blendMode)25455     public void setBackgroundTintBlendMode(@Nullable BlendMode blendMode) {
25456         if (mBackgroundTint == null) {
25457             mBackgroundTint = new TintInfo();
25458         }
25459 
25460         mBackgroundTint.mBlendMode = blendMode;
25461         mBackgroundTint.mHasTintMode = true;
25462 
25463         applyBackgroundTint();
25464     }
25465 
25466     /**
25467      * Return the blending mode used to apply the tint to the background
25468      * drawable, if specified.
25469      *
25470      * @return the blending mode used to apply the tint to the background
25471      *         drawable
25472      * @attr ref android.R.styleable#View_backgroundTintMode
25473      * @see #setBackgroundTintBlendMode(BlendMode)
25474      *
25475      */
25476     @Nullable
25477     @InspectableProperty
getBackgroundTintMode()25478     public PorterDuff.Mode getBackgroundTintMode() {
25479         PorterDuff.Mode porterDuffMode;
25480         if (mBackgroundTint != null && mBackgroundTint.mBlendMode != null) {
25481             porterDuffMode = BlendMode.blendModeToPorterDuffMode(mBackgroundTint.mBlendMode);
25482         } else {
25483             porterDuffMode = null;
25484         }
25485         return porterDuffMode;
25486     }
25487 
25488     /**
25489      * Return the blending mode used to apply the tint to the background
25490      * drawable, if specified.
25491      *
25492      * @return the blending mode used to apply the tint to the background
25493      *         drawable, null if no blend has previously been configured
25494      * @attr ref android.R.styleable#View_backgroundTintMode
25495      * @see #setBackgroundTintBlendMode(BlendMode)
25496      */
getBackgroundTintBlendMode()25497     public @Nullable BlendMode getBackgroundTintBlendMode() {
25498         return mBackgroundTint != null ? mBackgroundTint.mBlendMode : null;
25499     }
25500 
applyBackgroundTint()25501     private void applyBackgroundTint() {
25502         if (mBackground != null && mBackgroundTint != null) {
25503             final TintInfo tintInfo = mBackgroundTint;
25504             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
25505                 mBackground = mBackground.mutate();
25506 
25507                 if (tintInfo.mHasTintList) {
25508                     mBackground.setTintList(tintInfo.mTintList);
25509                 }
25510 
25511                 if (tintInfo.mHasTintMode) {
25512                     mBackground.setTintBlendMode(tintInfo.mBlendMode);
25513                 }
25514 
25515                 // The drawable (or one of its children) may not have been
25516                 // stateful before applying the tint, so let's try again.
25517                 if (mBackground.isStateful()) {
25518                     mBackground.setState(getDrawableState());
25519                 }
25520             }
25521         }
25522     }
25523 
25524     /**
25525      * Returns the drawable used as the foreground of this View. The
25526      * foreground drawable, if non-null, is always drawn on top of the view's content.
25527      *
25528      * @return a Drawable or null if no foreground was set
25529      *
25530      * @see #onDrawForeground(Canvas)
25531      */
25532     @InspectableProperty
getForeground()25533     public Drawable getForeground() {
25534         return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
25535     }
25536 
25537     /**
25538      * Supply a Drawable that is to be rendered on top of all of the content in the view.
25539      *
25540      * @param foreground the Drawable to be drawn on top of the children
25541      *
25542      * @attr ref android.R.styleable#View_foreground
25543      */
setForeground(Drawable foreground)25544     public void setForeground(Drawable foreground) {
25545         if (mForegroundInfo == null) {
25546             if (foreground == null) {
25547                 // Nothing to do.
25548                 return;
25549             }
25550             mForegroundInfo = new ForegroundInfo();
25551         }
25552 
25553         if (foreground == mForegroundInfo.mDrawable) {
25554             // Nothing to do
25555             return;
25556         }
25557 
25558         if (mForegroundInfo.mDrawable != null) {
25559             if (isAttachedToWindow()) {
25560                 mForegroundInfo.mDrawable.setVisible(false, false);
25561             }
25562             mForegroundInfo.mDrawable.setCallback(null);
25563             unscheduleDrawable(mForegroundInfo.mDrawable);
25564         }
25565 
25566         mForegroundInfo.mDrawable = foreground;
25567         mForegroundInfo.mBoundsChanged = true;
25568         if (foreground != null) {
25569             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
25570                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
25571             }
25572             foreground.setLayoutDirection(getLayoutDirection());
25573             if (foreground.isStateful()) {
25574                 foreground.setState(getDrawableState());
25575             }
25576             applyForegroundTint();
25577             if (isAttachedToWindow()) {
25578                 foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
25579             }
25580             // Set callback last, since the view may still be initializing.
25581             foreground.setCallback(this);
25582         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
25583                 && (mDefaultFocusHighlight == null)) {
25584             mPrivateFlags |= PFLAG_SKIP_DRAW;
25585         }
25586         requestLayout();
25587         invalidate();
25588     }
25589 
25590     /**
25591      * Magic bit used to support features of framework-internal window decor implementation details.
25592      * This used to live exclusively in FrameLayout.
25593      *
25594      * @return true if the foreground should draw inside the padding region or false
25595      *         if it should draw inset by the view's padding
25596      * @hide internal use only; only used by FrameLayout and internal screen layouts.
25597      */
isForegroundInsidePadding()25598     public boolean isForegroundInsidePadding() {
25599         return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
25600     }
25601 
25602     /**
25603      * Describes how the foreground is positioned.
25604      *
25605      * @return foreground gravity.
25606      *
25607      * @see #setForegroundGravity(int)
25608      *
25609      * @attr ref android.R.styleable#View_foregroundGravity
25610      */
25611     @InspectableProperty(valueType = InspectableProperty.ValueType.GRAVITY)
getForegroundGravity()25612     public int getForegroundGravity() {
25613         return mForegroundInfo != null ? mForegroundInfo.mGravity
25614                 : Gravity.START | Gravity.TOP;
25615     }
25616 
25617     /**
25618      * Describes how the foreground is positioned. Defaults to START and TOP.
25619      *
25620      * @param gravity see {@link android.view.Gravity}
25621      *
25622      * @see #getForegroundGravity()
25623      *
25624      * @attr ref android.R.styleable#View_foregroundGravity
25625      */
setForegroundGravity(int gravity)25626     public void setForegroundGravity(int gravity) {
25627         if (mForegroundInfo == null) {
25628             mForegroundInfo = new ForegroundInfo();
25629         }
25630 
25631         if (mForegroundInfo.mGravity != gravity) {
25632             if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
25633                 gravity |= Gravity.START;
25634             }
25635 
25636             if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
25637                 gravity |= Gravity.TOP;
25638             }
25639 
25640             mForegroundInfo.mGravity = gravity;
25641             requestLayout();
25642         }
25643     }
25644 
25645     /**
25646      * Applies a tint to the foreground drawable. Does not modify the current tint
25647      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
25648      * <p>
25649      * Subsequent calls to {@link #setForeground(Drawable)} will automatically
25650      * mutate the drawable and apply the specified tint and tint mode using
25651      * {@link Drawable#setTintList(ColorStateList)}.
25652      *
25653      * @param tint the tint to apply, may be {@code null} to clear tint
25654      *
25655      * @attr ref android.R.styleable#View_foregroundTint
25656      * @see #getForegroundTintList()
25657      * @see Drawable#setTintList(ColorStateList)
25658      */
25659     @RemotableViewMethod
setForegroundTintList(@ullable ColorStateList tint)25660     public void setForegroundTintList(@Nullable ColorStateList tint) {
25661         if (mForegroundInfo == null) {
25662             mForegroundInfo = new ForegroundInfo();
25663         }
25664         if (mForegroundInfo.mTintInfo == null) {
25665             mForegroundInfo.mTintInfo = new TintInfo();
25666         }
25667         mForegroundInfo.mTintInfo.mTintList = tint;
25668         mForegroundInfo.mTintInfo.mHasTintList = true;
25669 
25670         applyForegroundTint();
25671     }
25672 
25673     /**
25674      * Return the tint applied to the foreground drawable, if specified.
25675      *
25676      * @return the tint applied to the foreground drawable
25677      * @attr ref android.R.styleable#View_foregroundTint
25678      * @see #setForegroundTintList(ColorStateList)
25679      */
25680     @InspectableProperty(name = "foregroundTint")
25681     @Nullable
getForegroundTintList()25682     public ColorStateList getForegroundTintList() {
25683         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
25684                 ? mForegroundInfo.mTintInfo.mTintList : null;
25685     }
25686 
25687     /**
25688      * Specifies the blending mode used to apply the tint specified by
25689      * {@link #setForegroundTintList(ColorStateList)}} to the background
25690      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
25691      *
25692      * @param tintMode the blending mode used to apply the tint, may be
25693      *                 {@code null} to clear tint
25694      * @attr ref android.R.styleable#View_foregroundTintMode
25695      * @see #getForegroundTintMode()
25696      * @see Drawable#setTintMode(PorterDuff.Mode)
25697      *
25698      */
setForegroundTintMode(@ullable PorterDuff.Mode tintMode)25699     public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
25700         BlendMode mode = null;
25701         if (tintMode != null) {
25702             mode = BlendMode.fromValue(tintMode.nativeInt);
25703         }
25704         setForegroundTintBlendMode(mode);
25705     }
25706 
25707     /**
25708      * Specifies the blending mode used to apply the tint specified by
25709      * {@link #setForegroundTintList(ColorStateList)}} to the background
25710      * drawable. The default mode is {@link BlendMode#SRC_IN}.
25711      *
25712      * @param blendMode the blending mode used to apply the tint, may be
25713      *                 {@code null} to clear tint
25714      * @attr ref android.R.styleable#View_foregroundTintMode
25715      * @see #getForegroundTintMode()
25716      * @see Drawable#setTintBlendMode(BlendMode)
25717      */
25718     @RemotableViewMethod
setForegroundTintBlendMode(@ullable BlendMode blendMode)25719     public void setForegroundTintBlendMode(@Nullable BlendMode blendMode) {
25720         if (mForegroundInfo == null) {
25721             mForegroundInfo = new ForegroundInfo();
25722         }
25723         if (mForegroundInfo.mTintInfo == null) {
25724             mForegroundInfo.mTintInfo = new TintInfo();
25725         }
25726         mForegroundInfo.mTintInfo.mBlendMode = blendMode;
25727         mForegroundInfo.mTintInfo.mHasTintMode = true;
25728 
25729         applyForegroundTint();
25730     }
25731 
25732     /**
25733      * Return the blending mode used to apply the tint to the foreground
25734      * drawable, if specified.
25735      *
25736      * @return the blending mode used to apply the tint to the foreground
25737      *         drawable
25738      * @attr ref android.R.styleable#View_foregroundTintMode
25739      * @see #setForegroundTintMode(PorterDuff.Mode)
25740      */
25741     @InspectableProperty
25742     @Nullable
getForegroundTintMode()25743     public PorterDuff.Mode getForegroundTintMode() {
25744         BlendMode blendMode = mForegroundInfo != null && mForegroundInfo.mTintInfo != null
25745                 ? mForegroundInfo.mTintInfo.mBlendMode : null;
25746         if (blendMode != null) {
25747             return BlendMode.blendModeToPorterDuffMode(blendMode);
25748         } else {
25749             return null;
25750         }
25751     }
25752 
25753     /**
25754      * Return the blending mode used to apply the tint to the foreground
25755      * drawable, if specified.
25756      *
25757      * @return the blending mode used to apply the tint to the foreground
25758      *         drawable
25759      * @attr ref android.R.styleable#View_foregroundTintMode
25760      * @see #setForegroundTintBlendMode(BlendMode)
25761      *
25762      */
getForegroundTintBlendMode()25763     public @Nullable BlendMode getForegroundTintBlendMode() {
25764         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
25765                 ? mForegroundInfo.mTintInfo.mBlendMode : null;
25766     }
25767 
applyForegroundTint()25768     private void applyForegroundTint() {
25769         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
25770                 && mForegroundInfo.mTintInfo != null) {
25771             final TintInfo tintInfo = mForegroundInfo.mTintInfo;
25772             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
25773                 mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
25774 
25775                 if (tintInfo.mHasTintList) {
25776                     mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
25777                 }
25778 
25779                 if (tintInfo.mHasTintMode) {
25780                     mForegroundInfo.mDrawable.setTintBlendMode(tintInfo.mBlendMode);
25781                 }
25782 
25783                 // The drawable (or one of its children) may not have been
25784                 // stateful before applying the tint, so let's try again.
25785                 if (mForegroundInfo.mDrawable.isStateful()) {
25786                     mForegroundInfo.mDrawable.setState(getDrawableState());
25787                 }
25788             }
25789         }
25790     }
25791 
25792     /**
25793      * Get the drawable to be overlayed when a view is autofilled
25794      *
25795      * @return The drawable
25796      *
25797      * @throws IllegalStateException if the drawable could not be found.
25798      */
getAutofilledDrawable()25799     @Nullable private Drawable getAutofilledDrawable() {
25800         if (mAttachInfo == null) {
25801             return null;
25802         }
25803         // Lazily load the isAutofilled drawable.
25804         if (mAttachInfo.mAutofilledDrawable == null) {
25805             Context rootContext = getRootView().getContext();
25806             TypedArray a = rootContext.getTheme().obtainStyledAttributes(AUTOFILL_HIGHLIGHT_ATTR);
25807             int attributeResourceId = a.getResourceId(0, 0);
25808             mAttachInfo.mAutofilledDrawable = rootContext.getDrawable(attributeResourceId);
25809             a.recycle();
25810         }
25811 
25812         return mAttachInfo.mAutofilledDrawable;
25813     }
25814 
25815     /**
25816      * Draw {@link View#isAutofilled()} highlight over view if the view is autofilled, unless
25817      * {@link #PFLAG4_AUTOFILL_HIDE_HIGHLIGHT} is enabled.
25818      *
25819      * @param canvas The canvas to draw on
25820      */
drawAutofilledHighlight(@onNull Canvas canvas)25821     private void drawAutofilledHighlight(@NonNull Canvas canvas) {
25822         if (isAutofilled() && !hideAutofillHighlight()) {
25823             Drawable autofilledHighlight = getAutofilledDrawable();
25824 
25825             if (autofilledHighlight != null) {
25826                 autofilledHighlight.setBounds(0, 0, getWidth(), getHeight());
25827                 autofilledHighlight.draw(canvas);
25828             }
25829         }
25830     }
25831 
25832     /**
25833      * Draw any foreground content for this view.
25834      *
25835      * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
25836      * drawable or other view-specific decorations. The foreground is drawn on top of the
25837      * primary view content.</p>
25838      *
25839      * @param canvas canvas to draw into
25840      */
onDrawForeground(@onNull Canvas canvas)25841     public void onDrawForeground(@NonNull Canvas canvas) {
25842         onDrawScrollIndicators(canvas);
25843         onDrawScrollBars(canvas);
25844 
25845         final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
25846         if (foreground != null) {
25847             if (mForegroundInfo.mBoundsChanged) {
25848                 mForegroundInfo.mBoundsChanged = false;
25849                 final Rect selfBounds = mForegroundInfo.mSelfBounds;
25850                 final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
25851 
25852                 if (mForegroundInfo.mInsidePadding) {
25853                     selfBounds.set(0, 0, getWidth(), getHeight());
25854                 } else {
25855                     selfBounds.set(getPaddingLeft(), getPaddingTop(),
25856                             getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
25857                 }
25858 
25859                 final int ld = getLayoutDirection();
25860                 Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
25861                         foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
25862                 foreground.setBounds(overlayBounds);
25863             }
25864 
25865             foreground.draw(canvas);
25866         }
25867     }
25868 
25869     /**
25870      * Sets the padding. The view may add on the space required to display
25871      * the scrollbars, depending on the style and visibility of the scrollbars.
25872      * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
25873      * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
25874      * from the values set in this call.
25875      *
25876      * @attr ref android.R.styleable#View_padding
25877      * @attr ref android.R.styleable#View_paddingBottom
25878      * @attr ref android.R.styleable#View_paddingLeft
25879      * @attr ref android.R.styleable#View_paddingRight
25880      * @attr ref android.R.styleable#View_paddingTop
25881      * @param left the left padding in pixels
25882      * @param top the top padding in pixels
25883      * @param right the right padding in pixels
25884      * @param bottom the bottom padding in pixels
25885      */
setPadding(int left, int top, int right, int bottom)25886     public void setPadding(int left, int top, int right, int bottom) {
25887         resetResolvedPaddingInternal();
25888 
25889         mUserPaddingStart = UNDEFINED_PADDING;
25890         mUserPaddingEnd = UNDEFINED_PADDING;
25891 
25892         mUserPaddingLeftInitial = left;
25893         mUserPaddingRightInitial = right;
25894 
25895         mLeftPaddingDefined = true;
25896         mRightPaddingDefined = true;
25897 
25898         internalSetPadding(left, top, right, bottom);
25899     }
25900 
25901     /**
25902      * @hide
25903      */
25904     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768420)
internalSetPadding(int left, int top, int right, int bottom)25905     protected void internalSetPadding(int left, int top, int right, int bottom) {
25906         mUserPaddingLeft = left;
25907         mUserPaddingRight = right;
25908         mUserPaddingBottom = bottom;
25909 
25910         final int viewFlags = mViewFlags;
25911         boolean changed = false;
25912 
25913         // Common case is there are no scroll bars.
25914         if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
25915             if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
25916                 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
25917                         ? 0 : getVerticalScrollbarWidth();
25918                 switch (mVerticalScrollbarPosition) {
25919                     case SCROLLBAR_POSITION_DEFAULT:
25920                         if (isLayoutRtl()) {
25921                             left += offset;
25922                         } else {
25923                             right += offset;
25924                         }
25925                         break;
25926                     case SCROLLBAR_POSITION_RIGHT:
25927                         right += offset;
25928                         break;
25929                     case SCROLLBAR_POSITION_LEFT:
25930                         left += offset;
25931                         break;
25932                 }
25933             }
25934             if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
25935                 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
25936                         ? 0 : getHorizontalScrollbarHeight();
25937             }
25938         }
25939 
25940         if (mPaddingLeft != left) {
25941             changed = true;
25942             mPaddingLeft = left;
25943         }
25944         if (mPaddingTop != top) {
25945             changed = true;
25946             mPaddingTop = top;
25947         }
25948         if (mPaddingRight != right) {
25949             changed = true;
25950             mPaddingRight = right;
25951         }
25952         if (mPaddingBottom != bottom) {
25953             changed = true;
25954             mPaddingBottom = bottom;
25955         }
25956 
25957         if (changed) {
25958             requestLayout();
25959             invalidateOutline();
25960         }
25961     }
25962 
25963     /**
25964      * Sets the relative padding. The view may add on the space required to display
25965      * the scrollbars, depending on the style and visibility of the scrollbars.
25966      * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
25967      * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
25968      * from the values set in this call.
25969      *
25970      * @attr ref android.R.styleable#View_padding
25971      * @attr ref android.R.styleable#View_paddingBottom
25972      * @attr ref android.R.styleable#View_paddingStart
25973      * @attr ref android.R.styleable#View_paddingEnd
25974      * @attr ref android.R.styleable#View_paddingTop
25975      * @param start the start padding in pixels
25976      * @param top the top padding in pixels
25977      * @param end the end padding in pixels
25978      * @param bottom the bottom padding in pixels
25979      */
setPaddingRelative(int start, int top, int end, int bottom)25980     public void setPaddingRelative(int start, int top, int end, int bottom) {
25981         resetResolvedPaddingInternal();
25982 
25983         mUserPaddingStart = start;
25984         mUserPaddingEnd = end;
25985         mLeftPaddingDefined = true;
25986         mRightPaddingDefined = true;
25987 
25988         switch(getLayoutDirection()) {
25989             case LAYOUT_DIRECTION_RTL:
25990                 mUserPaddingLeftInitial = end;
25991                 mUserPaddingRightInitial = start;
25992                 internalSetPadding(end, top, start, bottom);
25993                 break;
25994             case LAYOUT_DIRECTION_LTR:
25995             default:
25996                 mUserPaddingLeftInitial = start;
25997                 mUserPaddingRightInitial = end;
25998                 internalSetPadding(start, top, end, bottom);
25999         }
26000     }
26001 
26002     /**
26003      * A {@link View} can be inflated from an XML layout. For such Views this method returns the
26004      * resource ID of the source layout.
26005      *
26006      * @return The layout resource id if this view was inflated from XML, otherwise
26007      * {@link Resources#ID_NULL}.
26008      */
26009     @LayoutRes
getSourceLayoutResId()26010     public int getSourceLayoutResId() {
26011         return mSourceLayoutId;
26012     }
26013 
26014     /**
26015      * Returns the top padding of this view.
26016      *
26017      * @return the top padding in pixels
26018      */
26019     @InspectableProperty
getPaddingTop()26020     public int getPaddingTop() {
26021         return mPaddingTop;
26022     }
26023 
26024     /**
26025      * Returns the bottom padding of this view. If there are inset and enabled
26026      * scrollbars, this value may include the space required to display the
26027      * scrollbars as well.
26028      *
26029      * @return the bottom padding in pixels
26030      */
26031     @InspectableProperty
getPaddingBottom()26032     public int getPaddingBottom() {
26033         return mPaddingBottom;
26034     }
26035 
26036     /**
26037      * Returns the left padding of this view. If there are inset and enabled
26038      * scrollbars, this value may include the space required to display the
26039      * scrollbars as well.
26040      *
26041      * @return the left padding in pixels
26042      */
26043     @InspectableProperty
getPaddingLeft()26044     public int getPaddingLeft() {
26045         if (!isPaddingResolved()) {
26046             resolvePadding();
26047         }
26048         return mPaddingLeft;
26049     }
26050 
26051     /**
26052      * Returns the start padding of this view depending on its resolved layout direction.
26053      * If there are inset and enabled scrollbars, this value may include the space
26054      * required to display the scrollbars as well.
26055      *
26056      * @return the start padding in pixels
26057      */
getPaddingStart()26058     public int getPaddingStart() {
26059         if (!isPaddingResolved()) {
26060             resolvePadding();
26061         }
26062         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
26063                 mPaddingRight : mPaddingLeft;
26064     }
26065 
26066     /**
26067      * Returns the right padding of this view. If there are inset and enabled
26068      * scrollbars, this value may include the space required to display the
26069      * scrollbars as well.
26070      *
26071      * @return the right padding in pixels
26072      */
26073     @InspectableProperty
getPaddingRight()26074     public int getPaddingRight() {
26075         if (!isPaddingResolved()) {
26076             resolvePadding();
26077         }
26078         return mPaddingRight;
26079     }
26080 
26081     /**
26082      * Returns the end padding of this view depending on its resolved layout direction.
26083      * If there are inset and enabled scrollbars, this value may include the space
26084      * required to display the scrollbars as well.
26085      *
26086      * @return the end padding in pixels
26087      */
getPaddingEnd()26088     public int getPaddingEnd() {
26089         if (!isPaddingResolved()) {
26090             resolvePadding();
26091         }
26092         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
26093                 mPaddingLeft : mPaddingRight;
26094     }
26095 
26096     /**
26097      * Return if the padding has been set through relative values
26098      * {@link #setPaddingRelative(int, int, int, int)} or through
26099      * @attr ref android.R.styleable#View_paddingStart or
26100      * @attr ref android.R.styleable#View_paddingEnd
26101      *
26102      * @return true if the padding is relative or false if it is not.
26103      */
isPaddingRelative()26104     public boolean isPaddingRelative() {
26105         return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
26106     }
26107 
computeOpticalInsets()26108     Insets computeOpticalInsets() {
26109         return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
26110     }
26111 
26112     /**
26113      * @hide
26114      */
26115     @UnsupportedAppUsage
resetPaddingToInitialValues()26116     public void resetPaddingToInitialValues() {
26117         if (isRtlCompatibilityMode()) {
26118             mPaddingLeft = mUserPaddingLeftInitial;
26119             mPaddingRight = mUserPaddingRightInitial;
26120             return;
26121         }
26122         if (isLayoutRtl()) {
26123             mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
26124             mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
26125         } else {
26126             mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
26127             mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
26128         }
26129     }
26130 
26131     /**
26132      * @hide
26133      */
getOpticalInsets()26134     public Insets getOpticalInsets() {
26135         if (mLayoutInsets == null) {
26136             mLayoutInsets = computeOpticalInsets();
26137         }
26138         return mLayoutInsets;
26139     }
26140 
26141     /**
26142      * Set this view's optical insets.
26143      *
26144      * <p>This method should be treated similarly to setMeasuredDimension and not as a general
26145      * property. Views that compute their own optical insets should call it as part of measurement.
26146      * This method does not request layout. If you are setting optical insets outside of
26147      * measure/layout itself you will want to call requestLayout() yourself.
26148      * </p>
26149      * @hide
26150      */
setOpticalInsets(Insets insets)26151     public void setOpticalInsets(Insets insets) {
26152         mLayoutInsets = insets;
26153     }
26154 
26155     /**
26156      * Changes the selection state of this view. A view can be selected or not.
26157      * Note that selection is not the same as focus. Views are typically
26158      * selected in the context of an AdapterView like ListView or GridView;
26159      * the selected view is the view that is highlighted.
26160      *
26161      * @param selected true if the view must be selected, false otherwise
26162      */
setSelected(boolean selected)26163     public void setSelected(boolean selected) {
26164         //noinspection DoubleNegation
26165         if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
26166             mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
26167             if (!selected) resetPressedState();
26168             invalidate(true);
26169             refreshDrawableState();
26170             dispatchSetSelected(selected);
26171             if (selected) {
26172                 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
26173             } else {
26174                 notifyViewAccessibilityStateChangedIfNeeded(
26175                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
26176             }
26177         }
26178     }
26179 
26180     /**
26181      * Dispatch setSelected to all of this View's children.
26182      *
26183      * @see #setSelected(boolean)
26184      *
26185      * @param selected The new selected state
26186      */
dispatchSetSelected(boolean selected)26187     protected void dispatchSetSelected(boolean selected) {
26188     }
26189 
26190     /**
26191      * Indicates the selection state of this view.
26192      *
26193      * @return true if the view is selected, false otherwise
26194      */
26195     @ViewDebug.ExportedProperty
26196     @InspectableProperty(hasAttributeId = false)
isSelected()26197     public boolean isSelected() {
26198         return (mPrivateFlags & PFLAG_SELECTED) != 0;
26199     }
26200 
26201     /**
26202      * Changes the activated state of this view. A view can be activated or not.
26203      * Note that activation is not the same as selection.  Selection is
26204      * a transient property, representing the view (hierarchy) the user is
26205      * currently interacting with.  Activation is a longer-term state that the
26206      * user can move views in and out of.  For example, in a list view with
26207      * single or multiple selection enabled, the views in the current selection
26208      * set are activated.  (Um, yeah, we are deeply sorry about the terminology
26209      * here.)  The activated state is propagated down to children of the view it
26210      * is set on.
26211      *
26212      * @param activated true if the view must be activated, false otherwise
26213      */
setActivated(boolean activated)26214     public void setActivated(boolean activated) {
26215         //noinspection DoubleNegation
26216         if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
26217             mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
26218             invalidate(true);
26219             refreshDrawableState();
26220             dispatchSetActivated(activated);
26221         }
26222     }
26223 
26224     /**
26225      * Dispatch setActivated to all of this View's children.
26226      *
26227      * @see #setActivated(boolean)
26228      *
26229      * @param activated The new activated state
26230      */
dispatchSetActivated(boolean activated)26231     protected void dispatchSetActivated(boolean activated) {
26232     }
26233 
26234     /**
26235      * Indicates the activation state of this view.
26236      *
26237      * @return true if the view is activated, false otherwise
26238      */
26239     @ViewDebug.ExportedProperty
26240     @InspectableProperty(hasAttributeId = false)
isActivated()26241     public boolean isActivated() {
26242         return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
26243     }
26244 
26245     /**
26246      * Returns the ViewTreeObserver for this view's hierarchy. The view tree
26247      * observer can be used to get notifications when global events, like
26248      * layout, happen.
26249      *
26250      * The returned ViewTreeObserver observer is not guaranteed to remain
26251      * valid for the lifetime of this View. If the caller of this method keeps
26252      * a long-lived reference to ViewTreeObserver, it should always check for
26253      * the return value of {@link ViewTreeObserver#isAlive()}.
26254      *
26255      * @return The ViewTreeObserver for this view's hierarchy.
26256      */
getViewTreeObserver()26257     public ViewTreeObserver getViewTreeObserver() {
26258         if (mAttachInfo != null) {
26259             return mAttachInfo.mTreeObserver;
26260         }
26261         if (mFloatingTreeObserver == null) {
26262             mFloatingTreeObserver = new ViewTreeObserver(mContext);
26263         }
26264         return mFloatingTreeObserver;
26265     }
26266 
26267     /**
26268      * <p>Finds the topmost view in the current view hierarchy.</p>
26269      *
26270      * @return the topmost view containing this view
26271      */
getRootView()26272     public View getRootView() {
26273         if (mAttachInfo != null) {
26274             final View v = mAttachInfo.mRootView;
26275             if (v != null) {
26276                 return v;
26277             }
26278         }
26279 
26280         View parent = this;
26281 
26282         while (parent.mParent instanceof View) {
26283             parent = (View) parent.mParent;
26284         }
26285 
26286         return parent;
26287     }
26288 
26289     /**
26290      * Transforms a motion event from view-local coordinates to on-screen
26291      * coordinates.
26292      *
26293      * @param ev the view-local motion event
26294      * @return false if the transformation could not be applied
26295      * @hide
26296      */
26297     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
toGlobalMotionEvent(MotionEvent ev)26298     public boolean toGlobalMotionEvent(MotionEvent ev) {
26299         final AttachInfo info = mAttachInfo;
26300         if (info == null) {
26301             return false;
26302         }
26303 
26304         final Matrix m = info.mTmpMatrix;
26305         m.set(Matrix.IDENTITY_MATRIX);
26306         transformMatrixToGlobal(m);
26307         ev.transform(m);
26308         return true;
26309     }
26310 
26311     /**
26312      * Transforms a motion event from on-screen coordinates to view-local
26313      * coordinates.
26314      *
26315      * @param ev the on-screen motion event
26316      * @return false if the transformation could not be applied
26317      * @hide
26318      */
26319     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
toLocalMotionEvent(MotionEvent ev)26320     public boolean toLocalMotionEvent(MotionEvent ev) {
26321         final AttachInfo info = mAttachInfo;
26322         if (info == null) {
26323             return false;
26324         }
26325 
26326         final Matrix m = info.mTmpMatrix;
26327         m.set(Matrix.IDENTITY_MATRIX);
26328         transformMatrixToLocal(m);
26329         ev.transform(m);
26330         return true;
26331     }
26332 
26333     /**
26334      * Modifies the input matrix such that it maps view-local coordinates to
26335      * on-screen coordinates.
26336      *
26337      * @param matrix input matrix to modify
26338      */
transformMatrixToGlobal(@onNull Matrix matrix)26339     public void transformMatrixToGlobal(@NonNull Matrix matrix) {
26340         final ViewParent parent = mParent;
26341         if (parent instanceof View) {
26342             final View vp = (View) parent;
26343             vp.transformMatrixToGlobal(matrix);
26344             matrix.preTranslate(-vp.mScrollX, -vp.mScrollY);
26345         } else if (parent instanceof ViewRootImpl) {
26346             final ViewRootImpl vr = (ViewRootImpl) parent;
26347             vr.transformMatrixToGlobal(matrix);
26348             matrix.preTranslate(0, -vr.mCurScrollY);
26349         }
26350 
26351         matrix.preTranslate(mLeft, mTop);
26352 
26353         if (!hasIdentityMatrix()) {
26354             matrix.preConcat(getMatrix());
26355         }
26356     }
26357 
26358     /**
26359      * Modifies the input matrix such that it maps on-screen coordinates to
26360      * view-local coordinates.
26361      *
26362      * @param matrix input matrix to modify
26363      */
transformMatrixToLocal(@onNull Matrix matrix)26364     public void transformMatrixToLocal(@NonNull Matrix matrix) {
26365         final ViewParent parent = mParent;
26366         if (parent instanceof View) {
26367             final View vp = (View) parent;
26368             vp.transformMatrixToLocal(matrix);
26369             matrix.postTranslate(vp.mScrollX, vp.mScrollY);
26370         } else if (parent instanceof ViewRootImpl) {
26371             final ViewRootImpl vr = (ViewRootImpl) parent;
26372             vr.transformMatrixToLocal(matrix);
26373             matrix.postTranslate(0, vr.mCurScrollY);
26374         }
26375 
26376         matrix.postTranslate(-mLeft, -mTop);
26377 
26378         if (!hasIdentityMatrix()) {
26379             matrix.postConcat(getInverseMatrix());
26380         }
26381     }
26382 
26383     /**
26384      * @hide
26385      */
26386     @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
26387             @ViewDebug.IntToString(from = 0, to = "x"),
26388             @ViewDebug.IntToString(from = 1, to = "y")
26389     })
26390     @UnsupportedAppUsage
getLocationOnScreen()26391     public int[] getLocationOnScreen() {
26392         int[] location = new int[2];
26393         getLocationOnScreen(location);
26394         return location;
26395     }
26396 
26397     /**
26398      * Gets the coordinates of this view in the coordinate space of the device
26399      * screen, irrespective of system decorations and whether the system is in
26400      * multi-window mode.
26401      *
26402      * <p>In multi-window mode, the coordinate space encompasses the entire
26403      * device screen, ignoring the bounds of the app window. For example, if the
26404      * view is in the bottom portion of a horizontal split screen, the top edge
26405      * of the screen&mdash;not the top edge of the window&mdash;is the origin
26406      * from which the y-coordinate is calculated.
26407      *
26408      * <p>In multiple-screen scenarios, the coordinate space can span screens.
26409      * For example, if the app is spanning both screens of a dual-screen device
26410      * and the view is located on the right-hand screen, the x-coordinate is
26411      * calculated from the left edge of the left-hand screen to the left edge of
26412      * the view. When the app is restricted to a single screen in a
26413      * multiple-screen environment, the coordinate space includes only the
26414      * screen on which the app is running.
26415      *
26416      * <p>After the method returns, the argument array contains the x and y
26417      * coordinates of the view relative to the view's left and top edges,
26418      * respectively.
26419      *
26420      * @param outLocation A two-element integer array in which the view
26421      *      coordinates are stored. The x-coordinate is at index 0; the
26422      *      y-coordinate, at index 1.
26423      */
getLocationOnScreen(@ize2) int[] outLocation)26424     public void getLocationOnScreen(@Size(2) int[] outLocation) {
26425         getLocationInWindow(outLocation);
26426 
26427         final AttachInfo info = mAttachInfo;
26428         if (info != null) {
26429             outLocation[0] += info.mWindowLeft;
26430             outLocation[1] += info.mWindowTop;
26431             // If OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS override is enabled,
26432             // applyViewLocationSandboxingIfNeeded sandboxes outLocation within window bounds.
26433             info.mViewRootImpl.applyViewLocationSandboxingIfNeeded(outLocation);
26434         }
26435     }
26436 
26437     /**
26438      * Gets the coordinates of this view in the coordinate space of the window
26439      * that contains the view, irrespective of system decorations.
26440      *
26441      * <p>In multi-window mode, the origin of the coordinate space is the
26442      * top left corner of the window that contains the view. In full screen
26443      * mode, the origin is the top left corner of the device screen.
26444      *
26445      * <p>In multiple-screen scenarios, if the app spans multiple screens, the
26446      * coordinate space also spans multiple screens. But if the app is
26447      * restricted to a single screen, the coordinate space includes only the
26448      * screen on which the app is running.
26449      *
26450      * <p>After the method returns, the argument array contains the x and y
26451      * coordinates of the view relative to the view's left and top edges,
26452      * respectively.
26453      *
26454      * @param outLocation A two-element integer array in which the view
26455      *      coordinates are stored. The x-coordinate is at index 0; the
26456      *      y-coordinate, at index 1.
26457      */
getLocationInWindow(@ize2) int[] outLocation)26458     public void getLocationInWindow(@Size(2) int[] outLocation) {
26459         if (outLocation == null || outLocation.length < 2) {
26460             throw new IllegalArgumentException("outLocation must be an array of two integers");
26461         }
26462 
26463         outLocation[0] = 0;
26464         outLocation[1] = 0;
26465 
26466         transformFromViewToWindowSpace(outLocation);
26467     }
26468 
26469     /** @hide */
transformFromViewToWindowSpace(@ize2) int[] inOutLocation)26470     public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
26471         if (inOutLocation == null || inOutLocation.length < 2) {
26472             throw new IllegalArgumentException("inOutLocation must be an array of two integers");
26473         }
26474 
26475         if (mAttachInfo == null) {
26476             // When the view is not attached to a window, this method does not make sense
26477             inOutLocation[0] = inOutLocation[1] = 0;
26478             return;
26479         }
26480 
26481         float position[] = mAttachInfo.mTmpTransformLocation;
26482         position[0] = inOutLocation[0];
26483         position[1] = inOutLocation[1];
26484 
26485         if (!hasIdentityMatrix()) {
26486             getMatrix().mapPoints(position);
26487         }
26488 
26489         position[0] += mLeft;
26490         position[1] += mTop;
26491 
26492         ViewParent viewParent = mParent;
26493         while (viewParent instanceof View) {
26494             final View view = (View) viewParent;
26495 
26496             position[0] -= view.mScrollX;
26497             position[1] -= view.mScrollY;
26498 
26499             if (!view.hasIdentityMatrix()) {
26500                 view.getMatrix().mapPoints(position);
26501             }
26502 
26503             position[0] += view.mLeft;
26504             position[1] += view.mTop;
26505 
26506             viewParent = view.mParent;
26507          }
26508 
26509         if (viewParent instanceof ViewRootImpl) {
26510             // *cough*
26511             final ViewRootImpl vr = (ViewRootImpl) viewParent;
26512             position[1] -= vr.mCurScrollY;
26513         }
26514 
26515         inOutLocation[0] = Math.round(position[0]);
26516         inOutLocation[1] = Math.round(position[1]);
26517     }
26518 
26519     /**
26520      * @param id the id of the view to be found
26521      * @return the view of the specified id, null if cannot be found
26522      * @hide
26523      */
findViewTraversal(@dRes int id)26524     protected <T extends View> T findViewTraversal(@IdRes int id) {
26525         if (id == mID) {
26526             return (T) this;
26527         }
26528         return null;
26529     }
26530 
26531     /**
26532      * @param tag the tag of the view to be found
26533      * @return the view of specified tag, null if cannot be found
26534      * @hide
26535      */
findViewWithTagTraversal(Object tag)26536     protected <T extends View> T findViewWithTagTraversal(Object tag) {
26537         if (tag != null && tag.equals(mTag)) {
26538             return (T) this;
26539         }
26540         return null;
26541     }
26542 
26543     /**
26544      * @param predicate The predicate to evaluate.
26545      * @param childToSkip If not null, ignores this child during the recursive traversal.
26546      * @return The first view that matches the predicate or null.
26547      * @hide
26548      */
findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip)26549     protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
26550             View childToSkip) {
26551         if (predicate.test(this)) {
26552             return (T) this;
26553         }
26554         return null;
26555     }
26556 
26557     /**
26558      * Finds the first descendant view with the given ID, the view itself if
26559      * the ID matches {@link #getId()}, or {@code null} if the ID is invalid
26560      * (< 0) or there is no matching view in the hierarchy.
26561      * <p>
26562      * <strong>Note:</strong> In most cases -- depending on compiler support --
26563      * the resulting view is automatically cast to the target class type. If
26564      * the target class type is unconstrained, an explicit cast may be
26565      * necessary.
26566      *
26567      * @param id the ID to search for
26568      * @return a view with given ID if found, or {@code null} otherwise
26569      * @see View#requireViewById(int)
26570      */
26571     @Nullable
findViewById(@dRes int id)26572     public final <T extends View> T findViewById(@IdRes int id) {
26573         if (id == NO_ID) {
26574             return null;
26575         }
26576         return findViewTraversal(id);
26577     }
26578 
26579     /**
26580      * Finds the first descendant view with the given ID, the view itself if the ID matches
26581      * {@link #getId()}, or throws an IllegalArgumentException if the ID is invalid or there is no
26582      * matching view in the hierarchy.
26583      * <p>
26584      * <strong>Note:</strong> In most cases -- depending on compiler support --
26585      * the resulting view is automatically cast to the target class type. If
26586      * the target class type is unconstrained, an explicit cast may be
26587      * necessary.
26588      *
26589      * @param id the ID to search for
26590      * @return a view with given ID
26591      * @see View#findViewById(int)
26592      */
26593     @NonNull
requireViewById(@dRes int id)26594     public final <T extends View> T requireViewById(@IdRes int id) {
26595         T view = findViewById(id);
26596         if (view == null) {
26597             throw new IllegalArgumentException("ID does not reference a View inside this View");
26598         }
26599         return view;
26600     }
26601 
26602     /**
26603      * Performs the traversal to find a view by its unique and stable accessibility id.
26604      *
26605      * <strong>Note:</strong>This method does not stop at the root namespace
26606      * boundary since the user can touch the screen at an arbitrary location
26607      * potentially crossing the root namespace boundary which will send an
26608      * accessibility event to accessibility services and they should be able
26609      * to obtain the event source. Also accessibility ids are guaranteed to be
26610      * unique in the window.
26611      *
26612      * @param accessibilityId The accessibility id.
26613      * @return The found view.
26614      * @hide
26615      */
findViewByAccessibilityIdTraversal(int accessibilityId)26616     public <T extends View> T findViewByAccessibilityIdTraversal(int accessibilityId) {
26617         if (getAccessibilityViewId() == accessibilityId) {
26618             return (T) this;
26619         }
26620         return null;
26621     }
26622 
26623     /**
26624      * Performs the traversal to find a view by its autofill id.
26625      *
26626      * <strong>Note:</strong>This method does not stop at the root namespace
26627      * boundary.
26628      *
26629      * @param autofillId The autofill id.
26630      * @return The found view.
26631      * @hide
26632      */
findViewByAutofillIdTraversal(int autofillId)26633     public <T extends View> T findViewByAutofillIdTraversal(int autofillId) {
26634         if (getAutofillViewId() == autofillId) {
26635             return (T) this;
26636         }
26637         return null;
26638     }
26639 
26640     /**
26641      * Look for a child view with the given tag.  If this view has the given
26642      * tag, return this view.
26643      *
26644      * @param tag The tag to search for, using "tag.equals(getTag())".
26645      * @return The View that has the given tag in the hierarchy or null
26646      */
findViewWithTag(Object tag)26647     public final <T extends View> T findViewWithTag(Object tag) {
26648         if (tag == null) {
26649             return null;
26650         }
26651         return findViewWithTagTraversal(tag);
26652     }
26653 
26654     /**
26655      * Look for a child view that matches the specified predicate.
26656      * If this view matches the predicate, return this view.
26657      *
26658      * @param predicate The predicate to evaluate.
26659      * @return The first view that matches the predicate or null.
26660      * @hide
26661      */
findViewByPredicate(Predicate<View> predicate)26662     public final <T extends View> T findViewByPredicate(Predicate<View> predicate) {
26663         return findViewByPredicateTraversal(predicate, null);
26664     }
26665 
26666     /**
26667      * Look for a child view that matches the specified predicate,
26668      * starting with the specified view and its descendents and then
26669      * recusively searching the ancestors and siblings of that view
26670      * until this view is reached.
26671      *
26672      * This method is useful in cases where the predicate does not match
26673      * a single unique view (perhaps multiple views use the same id)
26674      * and we are trying to find the view that is "closest" in scope to the
26675      * starting view.
26676      *
26677      * @param start The view to start from.
26678      * @param predicate The predicate to evaluate.
26679      * @return The first view that matches the predicate or null.
26680      * @hide
26681      */
findViewByPredicateInsideOut( View start, Predicate<View> predicate)26682     public final <T extends View> T findViewByPredicateInsideOut(
26683             View start, Predicate<View> predicate) {
26684         View childToSkip = null;
26685         for (;;) {
26686             T view = start.findViewByPredicateTraversal(predicate, childToSkip);
26687             if (view != null || start == this) {
26688                 return view;
26689             }
26690 
26691             ViewParent parent = start.getParent();
26692             if (parent == null || !(parent instanceof View)) {
26693                 return null;
26694             }
26695 
26696             childToSkip = start;
26697             start = (View) parent;
26698         }
26699     }
26700 
26701     /**
26702      * Sets the identifier for this view. The identifier does not have to be
26703      * unique in this view's hierarchy. The identifier should be a positive
26704      * number.
26705      *
26706      * @see #NO_ID
26707      * @see #getId()
26708      * @see #findViewById(int)
26709      *
26710      * @param id a number used to identify the view
26711      *
26712      * @attr ref android.R.styleable#View_id
26713      */
setId(@dRes int id)26714     public void setId(@IdRes int id) {
26715         mID = id;
26716         if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
26717             mID = generateViewId();
26718         }
26719     }
26720 
26721     /**
26722      * {@hide}
26723      *
26724      * @param isRoot true if the view belongs to the root namespace, false
26725      *        otherwise
26726      */
26727     @UnsupportedAppUsage
26728     @TestApi
setIsRootNamespace(boolean isRoot)26729     public void setIsRootNamespace(boolean isRoot) {
26730         if (isRoot) {
26731             mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
26732         } else {
26733             mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
26734         }
26735     }
26736 
26737     /**
26738      * {@hide}
26739      *
26740      * @return true if the view belongs to the root namespace, false otherwise
26741      */
26742     @UnsupportedAppUsage
isRootNamespace()26743     public boolean isRootNamespace() {
26744         return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
26745     }
26746 
26747     /**
26748      * Returns this view's identifier.
26749      *
26750      * @return a positive integer used to identify the view or {@link #NO_ID}
26751      *         if the view has no ID
26752      *
26753      * @see #setId(int)
26754      * @see #findViewById(int)
26755      * @attr ref android.R.styleable#View_id
26756      */
26757     @IdRes
26758     @ViewDebug.CapturedViewProperty
26759     @InspectableProperty
getId()26760     public int getId() {
26761         return mID;
26762     }
26763 
26764     /**
26765      * Get the identifier used for this view by the drawing system.
26766      *
26767      * @see RenderNode#getUniqueId()
26768      * @return A long that uniquely identifies this view's drawing component
26769      */
getUniqueDrawingId()26770     public long getUniqueDrawingId() {
26771         return mRenderNode.getUniqueId();
26772     }
26773 
26774     /**
26775      * Returns this view's tag.
26776      *
26777      * @return the Object stored in this view as a tag, or {@code null} if not
26778      *         set
26779      *
26780      * @see #setTag(Object)
26781      * @see #getTag(int)
26782      */
26783     @ViewDebug.ExportedProperty
26784     @InspectableProperty
getTag()26785     public Object getTag() {
26786         return mTag;
26787     }
26788 
26789     /**
26790      * Sets the tag associated with this view. A tag can be used to mark
26791      * a view in its hierarchy and does not have to be unique within the
26792      * hierarchy. Tags can also be used to store data within a view without
26793      * resorting to another data structure.
26794      *
26795      * @param tag an Object to tag the view with
26796      *
26797      * @see #getTag()
26798      * @see #setTag(int, Object)
26799      */
setTag(final Object tag)26800     public void setTag(final Object tag) {
26801         mTag = tag;
26802     }
26803 
26804     /**
26805      * Returns the tag associated with this view and the specified key.
26806      *
26807      * @param key The key identifying the tag
26808      *
26809      * @return the Object stored in this view as a tag, or {@code null} if not
26810      *         set
26811      *
26812      * @see #setTag(int, Object)
26813      * @see #getTag()
26814      */
getTag(int key)26815     public Object getTag(int key) {
26816         if (mKeyedTags != null) return mKeyedTags.get(key);
26817         return null;
26818     }
26819 
26820     /**
26821      * Sets a tag associated with this view and a key. A tag can be used
26822      * to mark a view in its hierarchy and does not have to be unique within
26823      * the hierarchy. Tags can also be used to store data within a view
26824      * without resorting to another data structure.
26825      *
26826      * The specified key should be an id declared in the resources of the
26827      * application to ensure it is unique (see the <a
26828      * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
26829      * Keys identified as belonging to
26830      * the Android framework or not associated with any package will cause
26831      * an {@link IllegalArgumentException} to be thrown.
26832      *
26833      * @param key The key identifying the tag
26834      * @param tag An Object to tag the view with
26835      *
26836      * @throws IllegalArgumentException If they specified key is not valid
26837      *
26838      * @see #setTag(Object)
26839      * @see #getTag(int)
26840      */
setTag(int key, final Object tag)26841     public void setTag(int key, final Object tag) {
26842         // If the package id is 0x00 or 0x01, it's either an undefined package
26843         // or a framework id
26844         if ((key >>> 24) < 2) {
26845             throw new IllegalArgumentException("The key must be an application-specific "
26846                     + "resource id.");
26847         }
26848 
26849         setKeyedTag(key, tag);
26850     }
26851 
26852     /**
26853      * Variation of {@link #setTag(int, Object)} that enforces the key to be a
26854      * framework id.
26855      *
26856      * @hide
26857      */
26858     @UnsupportedAppUsage
setTagInternal(int key, Object tag)26859     public void setTagInternal(int key, Object tag) {
26860         if ((key >>> 24) != 0x1) {
26861             throw new IllegalArgumentException("The key must be a framework-specific "
26862                     + "resource id.");
26863         }
26864 
26865         setKeyedTag(key, tag);
26866     }
26867 
setKeyedTag(int key, Object tag)26868     private void setKeyedTag(int key, Object tag) {
26869         if (mKeyedTags == null) {
26870             mKeyedTags = new SparseArray<Object>(2);
26871         }
26872 
26873         mKeyedTags.put(key, tag);
26874     }
26875 
26876     /**
26877      * Prints information about this view in the log output, with the tag
26878      * {@link #VIEW_LOG_TAG}.
26879      *
26880      * @hide
26881      */
26882     @UnsupportedAppUsage
debug()26883     public void debug() {
26884         debug(0);
26885     }
26886 
26887     /**
26888      * Prints information about this view in the log output, with the tag
26889      * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
26890      * indentation defined by the <code>depth</code>.
26891      *
26892      * @param depth the indentation level
26893      *
26894      * @hide
26895      */
26896     @UnsupportedAppUsage
debug(int depth)26897     protected void debug(int depth) {
26898         String output = debugIndent(depth - 1);
26899 
26900         output += "+ " + this;
26901         int id = getId();
26902         if (id != -1) {
26903             output += " (id=" + id + ")";
26904         }
26905         Object tag = getTag();
26906         if (tag != null) {
26907             output += " (tag=" + tag + ")";
26908         }
26909         Log.d(VIEW_LOG_TAG, output);
26910 
26911         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
26912             output = debugIndent(depth) + " FOCUSED";
26913             Log.d(VIEW_LOG_TAG, output);
26914         }
26915 
26916         output = debugIndent(depth);
26917         output += "frame={" + mLeft + ", " + mTop + ", " + mRight
26918                 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
26919                 + "} ";
26920         Log.d(VIEW_LOG_TAG, output);
26921 
26922         if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
26923                 || mPaddingBottom != 0) {
26924             output = debugIndent(depth);
26925             output += "padding={" + mPaddingLeft + ", " + mPaddingTop
26926                     + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
26927             Log.d(VIEW_LOG_TAG, output);
26928         }
26929 
26930         output = debugIndent(depth);
26931         output += "mMeasureWidth=" + mMeasuredWidth +
26932                 " mMeasureHeight=" + mMeasuredHeight;
26933         Log.d(VIEW_LOG_TAG, output);
26934 
26935         output = debugIndent(depth);
26936         if (mLayoutParams == null) {
26937             output += "BAD! no layout params";
26938         } else {
26939             output = mLayoutParams.debug(output);
26940         }
26941         Log.d(VIEW_LOG_TAG, output);
26942 
26943         output = debugIndent(depth);
26944         output += "flags={";
26945         output += View.printFlags(mViewFlags);
26946         output += "}";
26947         Log.d(VIEW_LOG_TAG, output);
26948 
26949         output = debugIndent(depth);
26950         output += "privateFlags={";
26951         output += View.printPrivateFlags(mPrivateFlags);
26952         output += "}";
26953         Log.d(VIEW_LOG_TAG, output);
26954     }
26955 
26956     /**
26957      * Creates a string of whitespaces used for indentation.
26958      *
26959      * @param depth the indentation level
26960      * @return a String containing (depth * 2 + 3) * 2 white spaces
26961      *
26962      * @hide
26963      */
debugIndent(int depth)26964     protected static String debugIndent(int depth) {
26965         StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
26966         for (int i = 0; i < (depth * 2) + 3; i++) {
26967             spaces.append(' ').append(' ');
26968         }
26969         return spaces.toString();
26970     }
26971 
26972     /**
26973      * <p>Return the offset of the widget's text baseline from the widget's top
26974      * boundary. If this widget does not support baseline alignment, this
26975      * method returns -1. </p>
26976      *
26977      * @return the offset of the baseline within the widget's bounds or -1
26978      *         if baseline alignment is not supported
26979      */
26980     @ViewDebug.ExportedProperty(category = "layout")
26981     @InspectableProperty
getBaseline()26982     public int getBaseline() {
26983         return -1;
26984     }
26985 
26986     /**
26987      * Returns whether the view hierarchy is currently undergoing a layout pass. This
26988      * information is useful to avoid situations such as calling {@link #requestLayout()} during
26989      * a layout pass.
26990      *
26991      * @return whether the view hierarchy is currently undergoing a layout pass
26992      */
isInLayout()26993     public boolean isInLayout() {
26994         ViewRootImpl viewRoot = getViewRootImpl();
26995         return (viewRoot != null && viewRoot.isInLayout());
26996     }
26997 
26998     /** To be used only for debugging purposes. */
printStackStrace(String name)26999     private void printStackStrace(String name) {
27000         Log.d(VIEW_LOG_TAG, "---- ST:" + name);
27001 
27002         StringBuilder sb = new StringBuilder();
27003         StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
27004         int startIndex = 1;
27005         int endIndex = Math.min(stackTraceElements.length, startIndex + 20); // max 20 entries.
27006         for (int i = startIndex; i < endIndex; i++) {
27007             StackTraceElement s = stackTraceElements[i];
27008             sb.append(s.getMethodName())
27009                     .append("(")
27010                     .append(s.getFileName())
27011                     .append(":")
27012                     .append(s.getLineNumber())
27013                     .append(") <- ");
27014         }
27015         Log.d(VIEW_LOG_TAG, name + ": " + sb);
27016     }
27017     /**
27018      * Call this when something has changed which has invalidated the
27019      * layout of this view. This will schedule a layout pass of the view
27020      * tree. This should not be called while the view hierarchy is currently in a layout
27021      * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
27022      * end of the current layout pass (and then layout will run again) or after the current
27023      * frame is drawn and the next layout occurs.
27024      *
27025      * <p>Subclasses which override this method should call the superclass method to
27026      * handle possible request-during-layout errors correctly.</p>
27027      */
27028     @CallSuper
requestLayout()27029     public void requestLayout() {
27030         if (isRelayoutTracingEnabled()) {
27031             Trace.instantForTrack(TRACE_TAG_APP, "requestLayoutTracing",
27032                     mTracingStrings.classSimpleName);
27033             printStackStrace(mTracingStrings.requestLayoutStacktracePrefix);
27034         }
27035 
27036         if (mMeasureCache != null) mMeasureCache.clear();
27037 
27038         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
27039             // Only trigger request-during-layout logic if this is the view requesting it,
27040             // not the views in its parent hierarchy
27041             ViewRootImpl viewRoot = getViewRootImpl();
27042             if (viewRoot != null && viewRoot.isInLayout()) {
27043                 if (!viewRoot.requestLayoutDuringLayout(this)) {
27044                     return;
27045                 }
27046             }
27047             mAttachInfo.mViewRequestingLayout = this;
27048         }
27049 
27050         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
27051         mPrivateFlags |= PFLAG_INVALIDATED;
27052 
27053         if (mParent != null && !mParent.isLayoutRequested()) {
27054             mParent.requestLayout();
27055         }
27056         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
27057             mAttachInfo.mViewRequestingLayout = null;
27058         }
27059     }
27060 
27061     /**
27062      * Forces this view to be laid out during the next layout pass.
27063      * This method does not call requestLayout() or forceLayout()
27064      * on the parent.
27065      */
forceLayout()27066     public void forceLayout() {
27067         if (mMeasureCache != null) mMeasureCache.clear();
27068 
27069         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
27070         mPrivateFlags |= PFLAG_INVALIDATED;
27071     }
27072 
27073     /**
27074      * <p>
27075      * This is called to find out how big a view should be. The parent
27076      * supplies constraint information in the width and height parameters.
27077      * </p>
27078      *
27079      * <p>
27080      * The actual measurement work of a view is performed in
27081      * {@link #onMeasure(int, int)}, called by this method. Therefore, only
27082      * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
27083      * </p>
27084      *
27085      *
27086      * @param widthMeasureSpec Horizontal space requirements as imposed by the
27087      *        parent
27088      * @param heightMeasureSpec Vertical space requirements as imposed by the
27089      *        parent
27090      *
27091      * @see #onMeasure(int, int)
27092      */
measure(int widthMeasureSpec, int heightMeasureSpec)27093     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
27094         boolean optical = isLayoutModeOptical(this);
27095         if (optical != isLayoutModeOptical(mParent)) {
27096             Insets insets = getOpticalInsets();
27097             int oWidth  = insets.left + insets.right;
27098             int oHeight = insets.top  + insets.bottom;
27099             widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
27100             heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
27101         }
27102 
27103         // Suppress sign extension for the low bytes
27104         long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
27105         if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
27106 
27107         final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
27108 
27109         // Optimize layout by avoiding an extra EXACTLY pass when the view is
27110         // already measured as the correct size. In API 23 and below, this
27111         // extra pass is required to make LinearLayout re-distribute weight.
27112         final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
27113                 || heightMeasureSpec != mOldHeightMeasureSpec;
27114         final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
27115                 && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
27116         final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
27117                 && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
27118         final boolean needsLayout = specChanged
27119                 && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
27120 
27121         if (forceLayout || needsLayout) {
27122             // first clears the measured dimension flag
27123             mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
27124 
27125             resolveRtlPropertiesIfNeeded();
27126 
27127             int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
27128             if (cacheIndex < 0 || sIgnoreMeasureCache) {
27129                 if (isTraversalTracingEnabled()) {
27130                     Trace.beginSection(mTracingStrings.onMeasure);
27131                 }
27132                 // measure ourselves, this should set the measured dimension flag back
27133                 onMeasure(widthMeasureSpec, heightMeasureSpec);
27134                 if (isTraversalTracingEnabled()) {
27135                     Trace.endSection();
27136                 }
27137                 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
27138             } else {
27139                 long value = mMeasureCache.valueAt(cacheIndex);
27140                 // Casting a long to int drops the high 32 bits, no mask needed
27141                 setMeasuredDimensionRaw((int) (value >> 32), (int) value);
27142                 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
27143             }
27144 
27145             // flag not set, setMeasuredDimension() was not invoked, we raise
27146             // an exception to warn the developer
27147             if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
27148                 throw new IllegalStateException("View with id " + getId() + ": "
27149                         + getClass().getName() + "#onMeasure() did not set the"
27150                         + " measured dimension by calling"
27151                         + " setMeasuredDimension()");
27152             }
27153 
27154             mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
27155         }
27156 
27157         mOldWidthMeasureSpec = widthMeasureSpec;
27158         mOldHeightMeasureSpec = heightMeasureSpec;
27159 
27160         mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
27161                 (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
27162     }
27163 
27164     /**
27165      * <p>
27166      * Measure the view and its content to determine the measured width and the
27167      * measured height. This method is invoked by {@link #measure(int, int)} and
27168      * should be overridden by subclasses to provide accurate and efficient
27169      * measurement of their contents.
27170      * </p>
27171      *
27172      * <p>
27173      * <strong>CONTRACT:</strong> When overriding this method, you
27174      * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
27175      * measured width and height of this view. Failure to do so will trigger an
27176      * <code>IllegalStateException</code>, thrown by
27177      * {@link #measure(int, int)}. Calling the superclass'
27178      * {@link #onMeasure(int, int)} is a valid use.
27179      * </p>
27180      *
27181      * <p>
27182      * The base class implementation of measure defaults to the background size,
27183      * unless a larger size is allowed by the MeasureSpec. Subclasses should
27184      * override {@link #onMeasure(int, int)} to provide better measurements of
27185      * their content.
27186      * </p>
27187      *
27188      * <p>
27189      * If this method is overridden, it is the subclass's responsibility to make
27190      * sure the measured height and width are at least the view's minimum height
27191      * and width ({@link #getSuggestedMinimumHeight()} and
27192      * {@link #getSuggestedMinimumWidth()}).
27193      * </p>
27194      *
27195      * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
27196      *                         The requirements are encoded with
27197      *                         {@link android.view.View.MeasureSpec}.
27198      * @param heightMeasureSpec vertical space requirements as imposed by the parent.
27199      *                         The requirements are encoded with
27200      *                         {@link android.view.View.MeasureSpec}.
27201      *
27202      * @see #getMeasuredWidth()
27203      * @see #getMeasuredHeight()
27204      * @see #setMeasuredDimension(int, int)
27205      * @see #getSuggestedMinimumHeight()
27206      * @see #getSuggestedMinimumWidth()
27207      * @see android.view.View.MeasureSpec#getMode(int)
27208      * @see android.view.View.MeasureSpec#getSize(int)
27209      */
onMeasure(int widthMeasureSpec, int heightMeasureSpec)27210     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
27211         setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
27212                 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
27213     }
27214 
27215     /**
27216      * <p>This method must be called by {@link #onMeasure(int, int)} to store the
27217      * measured width and measured height. Failing to do so will trigger an
27218      * exception at measurement time.</p>
27219      *
27220      * @param measuredWidth The measured width of this view.  May be a complex
27221      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
27222      * {@link #MEASURED_STATE_TOO_SMALL}.
27223      * @param measuredHeight The measured height of this view.  May be a complex
27224      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
27225      * {@link #MEASURED_STATE_TOO_SMALL}.
27226      */
setMeasuredDimension(int measuredWidth, int measuredHeight)27227     protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
27228         boolean optical = isLayoutModeOptical(this);
27229         if (optical != isLayoutModeOptical(mParent)) {
27230             Insets insets = getOpticalInsets();
27231             int opticalWidth  = insets.left + insets.right;
27232             int opticalHeight = insets.top  + insets.bottom;
27233 
27234             measuredWidth  += optical ? opticalWidth  : -opticalWidth;
27235             measuredHeight += optical ? opticalHeight : -opticalHeight;
27236         }
27237         setMeasuredDimensionRaw(measuredWidth, measuredHeight);
27238     }
27239 
27240     /**
27241      * Sets the measured dimension without extra processing for things like optical bounds.
27242      * Useful for reapplying consistent values that have already been cooked with adjustments
27243      * for optical bounds, etc. such as those from the measurement cache.
27244      *
27245      * @param measuredWidth The measured width of this view.  May be a complex
27246      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
27247      * {@link #MEASURED_STATE_TOO_SMALL}.
27248      * @param measuredHeight The measured height of this view.  May be a complex
27249      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
27250      * {@link #MEASURED_STATE_TOO_SMALL}.
27251      */
setMeasuredDimensionRaw(int measuredWidth, int measuredHeight)27252     private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
27253         mMeasuredWidth = measuredWidth;
27254         mMeasuredHeight = measuredHeight;
27255 
27256         mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
27257     }
27258 
27259     /**
27260      * Merge two states as returned by {@link #getMeasuredState()}.
27261      * @param curState The current state as returned from a view or the result
27262      * of combining multiple views.
27263      * @param newState The new view state to combine.
27264      * @return Returns a new integer reflecting the combination of the two
27265      * states.
27266      */
combineMeasuredStates(int curState, int newState)27267     public static int combineMeasuredStates(int curState, int newState) {
27268         return curState | newState;
27269     }
27270 
27271     /**
27272      * Version of {@link #resolveSizeAndState(int, int, int)}
27273      * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
27274      */
resolveSize(int size, int measureSpec)27275     public static int resolveSize(int size, int measureSpec) {
27276         return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
27277     }
27278 
27279     /**
27280      * Utility to reconcile a desired size and state, with constraints imposed
27281      * by a MeasureSpec. Will take the desired size, unless a different size
27282      * is imposed by the constraints. The returned value is a compound integer,
27283      * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
27284      * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
27285      * resulting size is smaller than the size the view wants to be.
27286      *
27287      * @param size How big the view wants to be.
27288      * @param measureSpec Constraints imposed by the parent.
27289      * @param childMeasuredState Size information bit mask for the view's
27290      *                           children.
27291      * @return Size information bit mask as defined by
27292      *         {@link #MEASURED_SIZE_MASK} and
27293      *         {@link #MEASURED_STATE_TOO_SMALL}.
27294      */
resolveSizeAndState(int size, int measureSpec, int childMeasuredState)27295     public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
27296         final int specMode = MeasureSpec.getMode(measureSpec);
27297         final int specSize = MeasureSpec.getSize(measureSpec);
27298         final int result;
27299         switch (specMode) {
27300             case MeasureSpec.AT_MOST:
27301                 if (specSize < size) {
27302                     result = specSize | MEASURED_STATE_TOO_SMALL;
27303                 } else {
27304                     result = size;
27305                 }
27306                 break;
27307             case MeasureSpec.EXACTLY:
27308                 result = specSize;
27309                 break;
27310             case MeasureSpec.UNSPECIFIED:
27311             default:
27312                 result = size;
27313         }
27314         return result | (childMeasuredState & MEASURED_STATE_MASK);
27315     }
27316 
27317     /**
27318      * Utility to return a default size. Uses the supplied size if the
27319      * MeasureSpec imposed no constraints. Will get larger if allowed
27320      * by the MeasureSpec.
27321      *
27322      * @param size Default size for this view
27323      * @param measureSpec Constraints imposed by the parent
27324      * @return The size this view should be.
27325      */
getDefaultSize(int size, int measureSpec)27326     public static int getDefaultSize(int size, int measureSpec) {
27327         int result = size;
27328         int specMode = MeasureSpec.getMode(measureSpec);
27329         int specSize = MeasureSpec.getSize(measureSpec);
27330 
27331         switch (specMode) {
27332         case MeasureSpec.UNSPECIFIED:
27333             result = size;
27334             break;
27335         case MeasureSpec.AT_MOST:
27336         case MeasureSpec.EXACTLY:
27337             result = specSize;
27338             break;
27339         }
27340         return result;
27341     }
27342 
27343     /**
27344      * Returns the suggested minimum height that the view should use. This
27345      * returns the maximum of the view's minimum height
27346      * and the background's minimum height
27347      * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
27348      * <p>
27349      * When being used in {@link #onMeasure(int, int)}, the caller should still
27350      * ensure the returned height is within the requirements of the parent.
27351      *
27352      * @return The suggested minimum height of the view.
27353      */
getSuggestedMinimumHeight()27354     protected int getSuggestedMinimumHeight() {
27355         return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
27356 
27357     }
27358 
27359     /**
27360      * Returns the suggested minimum width that the view should use. This
27361      * returns the maximum of the view's minimum width
27362      * and the background's minimum width
27363      *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
27364      * <p>
27365      * When being used in {@link #onMeasure(int, int)}, the caller should still
27366      * ensure the returned width is within the requirements of the parent.
27367      *
27368      * @return The suggested minimum width of the view.
27369      */
getSuggestedMinimumWidth()27370     protected int getSuggestedMinimumWidth() {
27371         return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
27372     }
27373 
27374     /**
27375      * Returns the minimum height of the view.
27376      *
27377      * @return the minimum height the view will try to be, in pixels
27378      *
27379      * @see #setMinimumHeight(int)
27380      *
27381      * @attr ref android.R.styleable#View_minHeight
27382      */
27383     @InspectableProperty(name = "minHeight")
getMinimumHeight()27384     public int getMinimumHeight() {
27385         return mMinHeight;
27386     }
27387 
27388     /**
27389      * Sets the minimum height of the view. It is not guaranteed the view will
27390      * be able to achieve this minimum height (for example, if its parent layout
27391      * constrains it with less available height).
27392      *
27393      * @param minHeight The minimum height the view will try to be, in pixels
27394      *
27395      * @see #getMinimumHeight()
27396      *
27397      * @attr ref android.R.styleable#View_minHeight
27398      */
27399     @RemotableViewMethod
setMinimumHeight(int minHeight)27400     public void setMinimumHeight(int minHeight) {
27401         mMinHeight = minHeight;
27402         requestLayout();
27403     }
27404 
27405     /**
27406      * Returns the minimum width of the view.
27407      *
27408      * @return the minimum width the view will try to be, in pixels
27409      *
27410      * @see #setMinimumWidth(int)
27411      *
27412      * @attr ref android.R.styleable#View_minWidth
27413      */
27414     @InspectableProperty(name = "minWidth")
getMinimumWidth()27415     public int getMinimumWidth() {
27416         return mMinWidth;
27417     }
27418 
27419     /**
27420      * Sets the minimum width of the view. It is not guaranteed the view will
27421      * be able to achieve this minimum width (for example, if its parent layout
27422      * constrains it with less available width).
27423      *
27424      * @param minWidth The minimum width the view will try to be, in pixels
27425      *
27426      * @see #getMinimumWidth()
27427      *
27428      * @attr ref android.R.styleable#View_minWidth
27429      */
27430     @RemotableViewMethod
setMinimumWidth(int minWidth)27431     public void setMinimumWidth(int minWidth) {
27432         mMinWidth = minWidth;
27433         requestLayout();
27434 
27435     }
27436 
27437     /**
27438      * Get the animation currently associated with this view.
27439      *
27440      * @return The animation that is currently playing or
27441      *         scheduled to play for this view.
27442      */
getAnimation()27443     public Animation getAnimation() {
27444         return mCurrentAnimation;
27445     }
27446 
27447     /**
27448      * Start the specified animation now.
27449      *
27450      * @param animation the animation to start now
27451      */
startAnimation(Animation animation)27452     public void startAnimation(Animation animation) {
27453         animation.setStartTime(Animation.START_ON_FIRST_FRAME);
27454         setAnimation(animation);
27455         invalidateParentCaches();
27456         invalidate(true);
27457     }
27458 
27459     /**
27460      * Cancels any animations for this view.
27461      */
clearAnimation()27462     public void clearAnimation() {
27463         if (mCurrentAnimation != null) {
27464             mCurrentAnimation.detach();
27465         }
27466         mCurrentAnimation = null;
27467         invalidateParentIfNeeded();
27468     }
27469 
27470     /**
27471      * Sets the next animation to play for this view.
27472      * If you want the animation to play immediately, use
27473      * {@link #startAnimation(android.view.animation.Animation)} instead.
27474      * This method provides allows fine-grained
27475      * control over the start time and invalidation, but you
27476      * must make sure that 1) the animation has a start time set, and
27477      * 2) the view's parent (which controls animations on its children)
27478      * will be invalidated when the animation is supposed to
27479      * start.
27480      *
27481      * @param animation The next animation, or null.
27482      */
setAnimation(Animation animation)27483     public void setAnimation(Animation animation) {
27484         mCurrentAnimation = animation;
27485 
27486         if (animation != null) {
27487             // If the screen is off assume the animation start time is now instead of
27488             // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
27489             // would cause the animation to start when the screen turns back on
27490             if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
27491                     && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
27492                 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
27493             }
27494             animation.reset();
27495         }
27496     }
27497 
27498     /**
27499      * Invoked by a parent ViewGroup to notify the start of the animation
27500      * currently associated with this view. If you override this method,
27501      * always call super.onAnimationStart();
27502      *
27503      * @see #setAnimation(android.view.animation.Animation)
27504      * @see #getAnimation()
27505      */
27506     @CallSuper
onAnimationStart()27507     protected void onAnimationStart() {
27508         mPrivateFlags |= PFLAG_ANIMATION_STARTED;
27509     }
27510 
27511     /**
27512      * Invoked by a parent ViewGroup to notify the end of the animation
27513      * currently associated with this view. If you override this method,
27514      * always call super.onAnimationEnd();
27515      *
27516      * @see #setAnimation(android.view.animation.Animation)
27517      * @see #getAnimation()
27518      */
27519     @CallSuper
onAnimationEnd()27520     protected void onAnimationEnd() {
27521         mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
27522     }
27523 
27524     /**
27525      * Invoked if there is a Transform that involves alpha. Subclass that can
27526      * draw themselves with the specified alpha should return true, and then
27527      * respect that alpha when their onDraw() is called. If this returns false
27528      * then the view may be redirected to draw into an offscreen buffer to
27529      * fulfill the request, which will look fine, but may be slower than if the
27530      * subclass handles it internally. The default implementation returns false.
27531      *
27532      * @param alpha The alpha (0..255) to apply to the view's drawing
27533      * @return true if the view can draw with the specified alpha.
27534      */
onSetAlpha(int alpha)27535     protected boolean onSetAlpha(int alpha) {
27536         return false;
27537     }
27538 
27539     /**
27540      * This is used by the ViewRoot to perform an optimization when
27541      * the view hierarchy contains one or several SurfaceView.
27542      * SurfaceView is always considered transparent, but its children are not,
27543      * therefore all View objects remove themselves from the global transparent
27544      * region (passed as a parameter to this function).
27545      *
27546      * @param region The transparent region for this ViewAncestor (window).
27547      *
27548      * @return Returns true if the effective visibility of the view at this
27549      * point is opaque, regardless of the transparent region; returns false
27550      * if it is possible for underlying windows to be seen behind the view.
27551      *
27552      */
gatherTransparentRegion(@ullable Region region)27553     public boolean gatherTransparentRegion(@Nullable Region region) {
27554         final AttachInfo attachInfo = mAttachInfo;
27555         if (region != null && attachInfo != null) {
27556             final int pflags = mPrivateFlags;
27557             if ((pflags & PFLAG_SKIP_DRAW) == 0) {
27558                 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
27559                 // remove it from the transparent region.
27560                 final int[] location = attachInfo.mTransparentLocation;
27561                 getLocationInWindow(location);
27562                 // When a view has Z value, then it will be better to leave some area below the view
27563                 // for drawing shadow. The shadow outset is proportional to the Z value. Note that
27564                 // the bottom part needs more offset than the left, top and right parts due to the
27565                 // spot light effects.
27566                 int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
27567                 region.op(location[0] - shadowOffset, location[1] - shadowOffset,
27568                         location[0] + mRight - mLeft + shadowOffset,
27569                         location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
27570             } else {
27571                 if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
27572                     // The SKIP_DRAW flag IS set and the background drawable exists, we remove
27573                     // the background drawable's non-transparent parts from this transparent region.
27574                     applyDrawableToTransparentRegion(mBackground, region);
27575                 }
27576                 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
27577                         && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
27578                     // Similarly, we remove the foreground drawable's non-transparent parts.
27579                     applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
27580                 }
27581                 if (mDefaultFocusHighlight != null
27582                         && mDefaultFocusHighlight.getOpacity() != PixelFormat.TRANSPARENT) {
27583                     // Similarly, we remove the default focus highlight's non-transparent parts.
27584                     applyDrawableToTransparentRegion(mDefaultFocusHighlight, region);
27585                 }
27586             }
27587         }
27588         return true;
27589     }
27590 
27591     /**
27592      * Play a sound effect for this view.
27593      *
27594      * <p>The framework will play sound effects for some built in actions, such as
27595      * clicking, but you may wish to play these effects in your widget,
27596      * for instance, for internal navigation.
27597      *
27598      * <p>The sound effect will only be played if sound effects are enabled by the user, and
27599      * {@link #isSoundEffectsEnabled()} is true.
27600      *
27601      * @param soundConstant One of the constants defined in {@link SoundEffectConstants}.
27602      */
playSoundEffect(@oundEffectConstants.SoundEffect int soundConstant)27603     public void playSoundEffect(@SoundEffectConstants.SoundEffect int soundConstant) {
27604         if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
27605             return;
27606         }
27607         mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
27608     }
27609 
27610     /**
27611      * BZZZTT!!1!
27612      *
27613      * <p>Provide haptic feedback to the user for this view.
27614      *
27615      * <p>The framework will provide haptic feedback for some built in actions,
27616      * such as long presses, but you may wish to provide feedback for your
27617      * own widget.
27618      *
27619      * <p>The feedback will only be performed if
27620      * {@link #isHapticFeedbackEnabled()} is true.
27621      *
27622      * @param feedbackConstant One of the constants defined in
27623      * {@link HapticFeedbackConstants}
27624      */
performHapticFeedback(int feedbackConstant)27625     public boolean performHapticFeedback(int feedbackConstant) {
27626         return performHapticFeedback(feedbackConstant, 0);
27627     }
27628 
27629     /**
27630      * BZZZTT!!1!
27631      *
27632      * <p>Like {@link #performHapticFeedback(int)}, with additional options.
27633      *
27634      * @param feedbackConstant One of the constants defined in
27635      * {@link HapticFeedbackConstants}
27636      * @param flags Additional flags as per {@link HapticFeedbackConstants}.
27637      */
performHapticFeedback(int feedbackConstant, int flags)27638     public boolean performHapticFeedback(int feedbackConstant, int flags) {
27639         if (feedbackConstant == HapticFeedbackConstants.NO_HAPTICS
27640                 || mAttachInfo == null) {
27641             return false;
27642         }
27643         //noinspection SimplifiableIfStatement
27644         if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
27645                 && !isHapticFeedbackEnabled()) {
27646             return false;
27647         }
27648         return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
27649                 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
27650     }
27651 
27652     /**
27653      * Request that the visibility of the status bar or other screen/window
27654      * decorations be changed.
27655      *
27656      * <p>This method is used to put the over device UI into temporary modes
27657      * where the user's attention is focused more on the application content,
27658      * by dimming or hiding surrounding system affordances.  This is typically
27659      * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
27660      * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
27661      * to be placed behind the action bar (and with these flags other system
27662      * affordances) so that smooth transitions between hiding and showing them
27663      * can be done.
27664      *
27665      * <p>Two representative examples of the use of system UI visibility is
27666      * implementing a content browsing application (like a magazine reader)
27667      * and a video playing application.
27668      *
27669      * <p>The first code shows a typical implementation of a View in a content
27670      * browsing application.  In this implementation, the application goes
27671      * into a content-oriented mode by hiding the status bar and action bar,
27672      * and putting the navigation elements into lights out mode.  The user can
27673      * then interact with content while in this mode.  Such an application should
27674      * provide an easy way for the user to toggle out of the mode (such as to
27675      * check information in the status bar or access notifications).  In the
27676      * implementation here, this is done simply by tapping on the content.
27677      *
27678      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
27679      *      content}
27680      *
27681      * <p>This second code sample shows a typical implementation of a View
27682      * in a video playing application.  In this situation, while the video is
27683      * playing the application would like to go into a complete full-screen mode,
27684      * to use as much of the display as possible for the video.  When in this state
27685      * the user can not interact with the application; the system intercepts
27686      * touching on the screen to pop the UI out of full screen mode.  See
27687      * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
27688      *
27689      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
27690      *      content}
27691      *
27692      * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
27693      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
27694      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
27695      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
27696      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
27697      *
27698      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
27699      * instead.
27700      */
27701     @Deprecated
setSystemUiVisibility(int visibility)27702     public void setSystemUiVisibility(int visibility) {
27703         if (visibility != mSystemUiVisibility) {
27704             mSystemUiVisibility = visibility;
27705             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
27706                 mParent.recomputeViewAttributes(this);
27707             }
27708         }
27709     }
27710 
27711     /**
27712      * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
27713      * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
27714      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
27715      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
27716      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
27717      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
27718      *
27719      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
27720      * instead.
27721      */
27722     @Deprecated
getSystemUiVisibility()27723     public int getSystemUiVisibility() {
27724         return mSystemUiVisibility;
27725     }
27726 
27727     /**
27728      * Returns the current system UI visibility that is currently set for
27729      * the entire window.  This is the combination of the
27730      * {@link #setSystemUiVisibility(int)} values supplied by all of the
27731      * views in the window.
27732      *
27733      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
27734      * instead.
27735      */
27736     @Deprecated
getWindowSystemUiVisibility()27737     public int getWindowSystemUiVisibility() {
27738         return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
27739     }
27740 
27741     /**
27742      * Override to find out when the window's requested system UI visibility
27743      * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
27744      * This is different from the callbacks received through
27745      * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
27746      * in that this is only telling you about the local request of the window,
27747      * not the actual values applied by the system.
27748      *
27749      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
27750      * instead.
27751      */
27752     @Deprecated
onWindowSystemUiVisibilityChanged(int visible)27753     public void onWindowSystemUiVisibilityChanged(int visible) {
27754     }
27755 
27756     /**
27757      * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
27758      * the view hierarchy.
27759      *
27760      * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
27761      * instead.
27762      */
27763     @Deprecated
dispatchWindowSystemUiVisiblityChanged(int visible)27764     public void dispatchWindowSystemUiVisiblityChanged(int visible) {
27765         onWindowSystemUiVisibilityChanged(visible);
27766     }
27767 
27768     /**
27769      * Set a listener to receive callbacks when the visibility of the system bar changes.
27770      * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
27771      *
27772      * @deprecated Use {@link WindowInsets#isVisible(int)} to find out about system bar visibilities
27773      * by setting a {@link OnApplyWindowInsetsListener} on this view.
27774      */
27775     @Deprecated
setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l)27776     public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
27777         getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
27778         if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
27779             mParent.recomputeViewAttributes(this);
27780         }
27781     }
27782 
27783     /**
27784      * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
27785      * the view hierarchy.
27786      *
27787      * @deprecated Use {@link WindowInsets#isVisible(int)} to find out about system bar visibilities
27788      * by setting a {@link OnApplyWindowInsetsListener} on this view.
27789      */
27790     @Deprecated
dispatchSystemUiVisibilityChanged(int visibility)27791     public void dispatchSystemUiVisibilityChanged(int visibility) {
27792         ListenerInfo li = mListenerInfo;
27793         if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
27794             li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
27795                     visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
27796         }
27797     }
27798 
updateLocalSystemUiVisibility(int localValue, int localChanges)27799     boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
27800         int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
27801         if (val != mSystemUiVisibility) {
27802             setSystemUiVisibility(val);
27803             return true;
27804         }
27805         return false;
27806     }
27807 
27808     /** @hide */
27809     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
setDisabledSystemUiVisibility(int flags)27810     public void setDisabledSystemUiVisibility(int flags) {
27811         if (mAttachInfo != null) {
27812             if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
27813                 mAttachInfo.mDisabledSystemUiVisibility = flags;
27814                 if (mParent != null) {
27815                     mParent.recomputeViewAttributes(this);
27816                 }
27817             }
27818         }
27819     }
27820 
27821     /**
27822      * This needs to be a better API before it is exposed. For now, only the root view will get
27823      * notified.
27824      * @hide
27825      */
onSystemBarAppearanceChanged(@indowInsetsController.Appearance int appearance)27826     public void onSystemBarAppearanceChanged(@WindowInsetsController.Appearance int appearance) {
27827     }
27828 
27829     /**
27830      * Creates an image that the system displays during the drag and drop
27831      * operation. This is called a &quot;drag shadow&quot;. The default implementation
27832      * for a DragShadowBuilder based on a View returns an image that has exactly the same
27833      * appearance as the given View. The default also positions the center of the drag shadow
27834      * directly under the touch point. If no View is provided (the constructor with no parameters
27835      * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
27836      * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
27837      * default is an invisible drag shadow.
27838      * <p>
27839      * You are not required to use the View you provide to the constructor as the basis of the
27840      * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
27841      * anything you want as the drag shadow.
27842      * </p>
27843      * <p>
27844      *  You pass a DragShadowBuilder object to the system when you start the drag. The system
27845      *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
27846      *  size and position of the drag shadow. It uses this data to construct a
27847      *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
27848      *  so that your application can draw the shadow image in the Canvas.
27849      * </p>
27850      *
27851      * <div class="special reference">
27852      * <h3>Developer Guides</h3>
27853      * <p>For a guide to implementing drag and drop features, read the
27854      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
27855      * </div>
27856      */
27857     public static class DragShadowBuilder {
27858         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
27859         private final WeakReference<View> mView;
27860 
27861         /**
27862          * Constructs a shadow image builder based on a View. By default, the resulting drag
27863          * shadow will have the same appearance and dimensions as the View, with the touch point
27864          * over the center of the View.
27865          * @param view A View. Any View in scope can be used.
27866          */
DragShadowBuilder(View view)27867         public DragShadowBuilder(View view) {
27868             mView = new WeakReference<View>(view);
27869         }
27870 
27871         /**
27872          * Construct a shadow builder object with no associated View.  This
27873          * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
27874          * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
27875          * to supply the drag shadow's dimensions and appearance without
27876          * reference to any View object.
27877          */
DragShadowBuilder()27878         public DragShadowBuilder() {
27879             mView = new WeakReference<View>(null);
27880         }
27881 
27882         /**
27883          * Returns the View object that had been passed to the
27884          * {@link #DragShadowBuilder(View)}
27885          * constructor.  If that View parameter was {@code null} or if the
27886          * {@link #DragShadowBuilder()}
27887          * constructor was used to instantiate the builder object, this method will return
27888          * null.
27889          *
27890          * @return The View object associate with this builder object.
27891          */
27892         @SuppressWarnings({"JavadocReference"})
getView()27893         final public View getView() {
27894             return mView.get();
27895         }
27896 
27897         /**
27898          * Provides the metrics for the shadow image. These include the dimensions of
27899          * the shadow image, and the point within that shadow that should
27900          * be centered under the touch location while dragging.
27901          * <p>
27902          * The default implementation sets the dimensions of the shadow to be the
27903          * same as the dimensions of the View itself and centers the shadow under
27904          * the touch point.
27905          * </p>
27906          *
27907          * @param outShadowSize A {@link android.graphics.Point} containing the width and height
27908          * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
27909          * desired width and must set {@link android.graphics.Point#y} to the desired height of the
27910          * image. Since Android P, the width and height must be positive values.
27911          *
27912          * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
27913          * shadow image that should be underneath the touch point during the drag and drop
27914          * operation. Your application must set {@link android.graphics.Point#x} to the
27915          * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
27916          */
onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint)27917         public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
27918             final View view = mView.get();
27919             if (view != null) {
27920                 outShadowSize.set(view.getWidth(), view.getHeight());
27921                 outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
27922             } else {
27923                 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
27924             }
27925         }
27926 
27927         /**
27928          * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
27929          * based on the dimensions it received from the
27930          * {@link #onProvideShadowMetrics(Point, Point)} callback.
27931          *
27932          * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
27933          */
onDrawShadow(@onNull Canvas canvas)27934         public void onDrawShadow(@NonNull Canvas canvas) {
27935             final View view = mView.get();
27936             if (view != null) {
27937                 view.draw(canvas);
27938             } else {
27939                 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
27940             }
27941         }
27942     }
27943 
27944     /**
27945      * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
27946      * startDragAndDrop()} for newer platform versions.
27947      */
27948     @Deprecated
startDrag(ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flags)27949     public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
27950                                    Object myLocalState, int flags) {
27951         return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
27952     }
27953 
27954     /**
27955      * Starts a drag and drop operation. When your application calls this method, it passes a
27956      * {@link android.view.View.DragShadowBuilder} object to the system. The
27957      * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
27958      * to get metrics for the drag shadow, and then calls the object's
27959      * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
27960      * <p>
27961      *  Once the system has the drag shadow, it begins the drag and drop operation by sending
27962      *  drag events to all the View objects in your application that are currently visible. It does
27963      *  this either by calling the View object's drag listener (an implementation of
27964      *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
27965      *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
27966      *  Both are passed a {@link android.view.DragEvent} object that has a
27967      *  {@link android.view.DragEvent#getAction()} value of
27968      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
27969      * </p>
27970      * <p>
27971      * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
27972      * int) startDragAndDrop()} on any attached View object. The View object does not need to be
27973      * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
27974      * to the View the user selected for dragging.
27975      * </p>
27976      * @param data A {@link android.content.ClipData} object pointing to the data to be
27977      * transferred by the drag and drop operation.
27978      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
27979      * drag shadow.
27980      * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
27981      * drop operation. When dispatching drag events to views in the same activity this object
27982      * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other
27983      * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()}
27984      * will return null).
27985      * <p>
27986      * myLocalState is a lightweight mechanism for the sending information from the dragged View
27987      * to the target Views. For example, it can contain flags that differentiate between a
27988      * a copy operation and a move operation.
27989      * </p>
27990      * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
27991      * flags, or any combination of the following:
27992      *     <ul>
27993      *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
27994      *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
27995      *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
27996      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
27997      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
27998      *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
27999      *         <li>{@link #DRAG_FLAG_ACCESSIBILITY_ACTION}</li>
28000      *     </ul>
28001      * @return {@code true} if the method completes successfully, or
28002      * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
28003      * do a drag because of another ongoing operation or some other reasons.
28004      */
startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flags)28005     public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
28006             Object myLocalState, int flags) {
28007         if (ViewDebug.DEBUG_DRAG) {
28008             Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
28009         }
28010         if (mAttachInfo == null) {
28011             Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
28012             return false;
28013         }
28014         if (!mAttachInfo.mViewRootImpl.mSurface.isValid()) {
28015             Log.w(VIEW_LOG_TAG, "startDragAndDrop called with an invalid surface.");
28016             return false;
28017         }
28018 
28019         if (data != null) {
28020             data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0);
28021         }
28022 
28023         Rect bounds = new Rect();
28024         getBoundsOnScreen(bounds, true);
28025 
28026         Point lastTouchPoint = new Point();
28027         mAttachInfo.mViewRootImpl.getLastTouchPoint(lastTouchPoint);
28028         final ViewRootImpl root = mAttachInfo.mViewRootImpl;
28029 
28030         // Skip surface logic since shadows and animation are not required during the a11y drag
28031         final boolean a11yEnabled = AccessibilityManager.getInstance(mContext).isEnabled();
28032         if (a11yEnabled && (flags & View.DRAG_FLAG_ACCESSIBILITY_ACTION) != 0) {
28033             try {
28034                 IBinder token = mAttachInfo.mSession.performDrag(
28035                         mAttachInfo.mWindow, flags, null,
28036                         mAttachInfo.mViewRootImpl.getLastTouchSource(),
28037                         0f, 0f, 0f, 0f, data);
28038                 if (ViewDebug.DEBUG_DRAG) {
28039                     Log.d(VIEW_LOG_TAG, "startDragAndDrop via a11y action returned " + token);
28040                 }
28041                 if (token != null) {
28042                     root.setLocalDragState(myLocalState);
28043                     mAttachInfo.mDragToken = token;
28044                     mAttachInfo.mViewRootImpl.setDragStartedViewForAccessibility(this);
28045                     setAccessibilityDragStarted(true);
28046                 }
28047                 return token != null;
28048             } catch (Exception e) {
28049                 Log.e(VIEW_LOG_TAG, "Unable to initiate a11y drag", e);
28050                 return false;
28051             }
28052         }
28053 
28054         Point shadowSize = new Point();
28055         Point shadowTouchPoint = new Point();
28056         shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
28057 
28058         if ((shadowSize.x < 0) || (shadowSize.y < 0)
28059                 || (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
28060             throw new IllegalStateException("Drag shadow dimensions must not be negative");
28061         }
28062         final float overrideInvScale = CompatibilityInfo.getOverrideInvertedScale();
28063         if (overrideInvScale != 1f) {
28064             shadowTouchPoint.x = (int) (shadowTouchPoint.x / overrideInvScale);
28065             shadowTouchPoint.y = (int) (shadowTouchPoint.y / overrideInvScale);
28066         }
28067 
28068         // Create 1x1 surface when zero surface size is specified because SurfaceControl.Builder
28069         // does not accept zero size surface.
28070         if (shadowSize.x == 0  || shadowSize.y == 0) {
28071             if (!sAcceptZeroSizeDragShadow) {
28072                 throw new IllegalStateException("Drag shadow dimensions must be positive");
28073             }
28074             shadowSize.x = 1;
28075             shadowSize.y = 1;
28076         }
28077 
28078         if (ViewDebug.DEBUG_DRAG) {
28079             Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
28080                     + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
28081         }
28082 
28083         final SurfaceSession session = new SurfaceSession();
28084         final SurfaceControl surfaceControl = new SurfaceControl.Builder(session)
28085                 .setName("drag surface")
28086                 .setParent(root.getSurfaceControl())
28087                 .setBufferSize(shadowSize.x, shadowSize.y)
28088                 .setFormat(PixelFormat.TRANSLUCENT)
28089                 .setCallsite("View.startDragAndDrop")
28090                 .build();
28091         if (overrideInvScale != 1f) {
28092             final SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
28093             transaction.setMatrix(surfaceControl, 1 / overrideInvScale, 0, 0, 1 / overrideInvScale)
28094                     .apply();
28095         }
28096         final Surface surface = new Surface();
28097         surface.copyFrom(surfaceControl);
28098         IBinder token = null;
28099         try {
28100             final Canvas canvas = isHardwareAccelerated()
28101                     ? surface.lockHardwareCanvas()
28102                     : surface.lockCanvas(null);
28103             try {
28104                 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
28105                 shadowBuilder.onDrawShadow(canvas);
28106             } finally {
28107                 surface.unlockCanvasAndPost(canvas);
28108             }
28109 
28110             token = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, flags, surfaceControl,
28111                     root.getLastTouchSource(), lastTouchPoint.x, lastTouchPoint.y,
28112                     shadowTouchPoint.x, shadowTouchPoint.y, data);
28113             if (ViewDebug.DEBUG_DRAG) {
28114                 Log.d(VIEW_LOG_TAG, "performDrag returned " + token);
28115             }
28116             if (token != null) {
28117                 if (mAttachInfo.mDragSurface != null) {
28118                     mAttachInfo.mDragSurface.release();
28119                 }
28120                 mAttachInfo.mDragSurface = surface;
28121                 mAttachInfo.mDragToken = token;
28122                 // Cache the local state object for delivery with DragEvents
28123                 root.setLocalDragState(myLocalState);
28124                 if (a11yEnabled) {
28125                     // Set for AccessibilityEvents
28126                     mAttachInfo.mViewRootImpl.setDragStartedViewForAccessibility(this);
28127                 }
28128             }
28129             return token != null;
28130         } catch (Exception e) {
28131             Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
28132             return false;
28133         } finally {
28134             if (token == null) {
28135                 surface.destroy();
28136             }
28137             session.kill();
28138         }
28139     }
28140 
setAccessibilityDragStarted(boolean started)28141     void setAccessibilityDragStarted(boolean started) {
28142         int pflags4 = mPrivateFlags4;
28143         if (started) {
28144             pflags4 |= PFLAG4_DRAG_A11Y_STARTED;
28145         } else {
28146             pflags4 &= ~PFLAG4_DRAG_A11Y_STARTED;
28147         }
28148 
28149         if (pflags4 != mPrivateFlags4) {
28150             mPrivateFlags4 = pflags4;
28151             sendWindowContentChangedAccessibilityEvent(CONTENT_CHANGE_TYPE_UNDEFINED);
28152         }
28153     }
28154 
startedSystemDragForAccessibility()28155     private boolean startedSystemDragForAccessibility() {
28156         return (mPrivateFlags4 & PFLAG4_DRAG_A11Y_STARTED) != 0;
28157     }
28158 
28159     /**
28160      * Cancels an ongoing drag and drop operation.
28161      * <p>
28162      * A {@link android.view.DragEvent} object with
28163      * {@link android.view.DragEvent#getAction()} value of
28164      * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
28165      * {@link android.view.DragEvent#getResult()} value of {@code false}
28166      * will be sent to every
28167      * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
28168      * even if they are not currently visible.
28169      * </p>
28170      * <p>
28171      * This method can be called on any View in the same window as the View on which
28172      * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
28173      * was called.
28174      * </p>
28175      */
cancelDragAndDrop()28176     public final void cancelDragAndDrop() {
28177         if (ViewDebug.DEBUG_DRAG) {
28178             Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
28179         }
28180         if (mAttachInfo == null) {
28181             Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
28182             return;
28183         }
28184         if (mAttachInfo.mDragToken != null) {
28185             try {
28186                 mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken, false);
28187             } catch (Exception e) {
28188                 Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
28189             }
28190             mAttachInfo.mDragToken = null;
28191         } else {
28192             Log.e(VIEW_LOG_TAG, "No active drag to cancel");
28193         }
28194     }
28195 
28196     /**
28197      * Updates the drag shadow for the ongoing drag and drop operation.
28198      *
28199      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
28200      * new drag shadow.
28201      */
updateDragShadow(DragShadowBuilder shadowBuilder)28202     public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
28203         if (ViewDebug.DEBUG_DRAG) {
28204             Log.d(VIEW_LOG_TAG, "updateDragShadow");
28205         }
28206         if (mAttachInfo == null) {
28207             Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
28208             return;
28209         }
28210         if (mAttachInfo.mDragToken != null) {
28211             try {
28212                 Canvas canvas = isHardwareAccelerated()
28213                         ? mAttachInfo.mDragSurface.lockHardwareCanvas()
28214                         : mAttachInfo.mDragSurface.lockCanvas(null);
28215                 try {
28216                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
28217                     shadowBuilder.onDrawShadow(canvas);
28218                 } finally {
28219                     mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
28220                 }
28221             } catch (Exception e) {
28222                 Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
28223             }
28224         } else {
28225             Log.e(VIEW_LOG_TAG, "No active drag");
28226         }
28227     }
28228 
28229     /**
28230      * Starts a move from {startX, startY}, the amount of the movement will be the offset
28231      * between {startX, startY} and the new cursor positon.
28232      * @param startX horizontal coordinate where the move started.
28233      * @param startY vertical coordinate where the move started.
28234      * @return whether moving was started successfully.
28235      * @hide
28236      */
startMovingTask(float startX, float startY)28237     public final boolean startMovingTask(float startX, float startY) {
28238         if (ViewDebug.DEBUG_POSITIONING) {
28239             Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
28240         }
28241         try {
28242             return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
28243         } catch (RemoteException e) {
28244             Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
28245         }
28246         return false;
28247     }
28248 
28249     /**
28250      * Finish a window move task.
28251      * @hide
28252      */
finishMovingTask()28253     public void finishMovingTask() {
28254         if (ViewDebug.DEBUG_POSITIONING) {
28255             Log.d(VIEW_LOG_TAG, "finishMovingTask");
28256         }
28257         try {
28258             mAttachInfo.mSession.finishMovingTask(mAttachInfo.mWindow);
28259         } catch (RemoteException e) {
28260             Log.e(VIEW_LOG_TAG, "Unable to finish moving", e);
28261         }
28262     }
28263 
28264     /**
28265      * Handles drag events sent by the system following a call to
28266      * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
28267      * startDragAndDrop()}.
28268      * <p>
28269      * The system calls this method and passes a {@link DragEvent} object in response to drag and
28270      * drop events. This method can then call {@link DragEvent#getAction()} to determine the state
28271      * of the drag and drop operation.
28272      * <p>
28273      * The default implementation returns {@code false} unless an {@link OnReceiveContentListener}
28274      * has been set for this view (see {@link #setOnReceiveContentListener}), in which case
28275      * the default implementation does the following:
28276      * <ul>
28277      *   <li>Returns {@code true} for an
28278      *     {@link DragEvent#ACTION_DRAG_STARTED ACTION_DRAG_STARTED} event
28279      *   <li>Calls {@link #performReceiveContent} for an
28280      *     {@link DragEvent#ACTION_DROP ACTION_DROP} event
28281      *   <li>Returns {@code true} for an {@link DragEvent#ACTION_DROP ACTION_DROP} event if the
28282      *     {@code OnReceiveContentListener} consumed some or all of the content
28283      * </ul>
28284      *
28285      * @param event The {@link DragEvent} object sent by the system. The
28286      *   {@link DragEvent#getAction()} method returns an action type constant that indicates the
28287      *   type of drag event represented by this object.
28288      * @return {@code true} if the method successfully handled the drag event, otherwise
28289      *   {@code false}.
28290      *   <p>
28291      *     The method must return {@code true} in response to an
28292      *     {@link DragEvent#ACTION_DRAG_STARTED ACTION_DRAG_STARTED} action type to continue to
28293      *     receive drag events for the current drag and drop operation.
28294      *   <p>
28295      *     The method should return {@code true} in response to an
28296      *     {@link DragEvent#ACTION_DROP ACTION_DROP} action type if the dropped data was consumed
28297      *     (at least partially); {@code false}, if none of the data was consumed.
28298      *   <p>
28299      *     For all other events, the return value is {@code false}.
28300      */
onDragEvent(DragEvent event)28301     public boolean onDragEvent(DragEvent event) {
28302         if (mListenerInfo == null || mListenerInfo.mOnReceiveContentListener == null) {
28303             return false;
28304         }
28305         // Accept drag events by default if there's an OnReceiveContentListener set.
28306         if (event.getAction() == DragEvent.ACTION_DRAG_STARTED) {
28307             return true;
28308         }
28309         if (event.getAction() == DragEvent.ACTION_DROP) {
28310             final DragAndDropPermissions permissions = DragAndDropPermissions.obtain(event);
28311             if (permissions != null) {
28312                 permissions.takeTransient();
28313             }
28314             final ContentInfo payload =
28315                     new ContentInfo.Builder(event.getClipData(), SOURCE_DRAG_AND_DROP)
28316                             .setDragAndDropPermissions(permissions)
28317                             .build();
28318             ContentInfo remainingPayload = performReceiveContent(payload);
28319             // Return true unless none of the payload was consumed.
28320             return remainingPayload != payload;
28321         }
28322         return false;
28323     }
28324 
28325     // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps.
dispatchDragEnterExitInPreN(DragEvent event)28326     boolean dispatchDragEnterExitInPreN(DragEvent event) {
28327         return callDragEventHandler(event);
28328     }
28329 
28330     /**
28331      * Detects if this View is enabled and has a drag event listener.
28332      * If both are true, then it calls the drag event listener with the
28333      * {@link android.view.DragEvent} it received. If the drag event listener returns
28334      * {@code true}, then dispatchDragEvent() returns {@code true}.
28335      * <p>
28336      * For all other cases, the method calls the
28337      * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
28338      * method and returns its result.
28339      * </p>
28340      * <p>
28341      * This ensures that a drag event is always consumed, even if the View does not have a drag
28342      * event listener. However, if the View has a listener and the listener returns true, then
28343      * onDragEvent() is not called.
28344      * </p>
28345      */
dispatchDragEvent(DragEvent event)28346     public boolean dispatchDragEvent(DragEvent event) {
28347         event.mEventHandlerWasCalled = true;
28348         if (event.mAction == DragEvent.ACTION_DRAG_LOCATION ||
28349             event.mAction == DragEvent.ACTION_DROP) {
28350             // About to deliver an event with coordinates to this view. Notify that now this view
28351             // has drag focus. This will send exit/enter events as needed.
28352             getViewRootImpl().setDragFocus(this, event);
28353         }
28354         return callDragEventHandler(event);
28355     }
28356 
callDragEventHandler(DragEvent event)28357     final boolean callDragEventHandler(DragEvent event) {
28358         final boolean result;
28359 
28360         ListenerInfo li = mListenerInfo;
28361         //noinspection SimplifiableIfStatement
28362         if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
28363                 && li.mOnDragListener.onDrag(this, event)) {
28364             result = true;
28365         } else {
28366             result = onDragEvent(event);
28367         }
28368 
28369         switch (event.mAction) {
28370             case DragEvent.ACTION_DRAG_STARTED: {
28371                 if (result && li != null && li.mOnDragListener != null) {
28372                     sendWindowContentChangedAccessibilityEvent(
28373                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
28374                 }
28375             } break;
28376             case DragEvent.ACTION_DRAG_ENTERED: {
28377                 mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
28378                 refreshDrawableState();
28379             } break;
28380             case DragEvent.ACTION_DRAG_EXITED: {
28381                 mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
28382                 refreshDrawableState();
28383             } break;
28384             case DragEvent.ACTION_DROP: {
28385                 if (result && li != null && (li.mOnDragListener != null
28386                         || li.mOnReceiveContentListener != null)) {
28387                     sendWindowContentChangedAccessibilityEvent(
28388                             AccessibilityEvent.CONTENT_CHANGE_TYPE_DRAG_DROPPED);
28389                 }
28390             } break;
28391             case DragEvent.ACTION_DRAG_ENDED: {
28392                 sendWindowContentChangedAccessibilityEvent(
28393                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
28394                 mPrivateFlags2 &= ~View.DRAG_MASK;
28395                 refreshDrawableState();
28396             } break;
28397         }
28398 
28399         return result;
28400     }
28401 
canAcceptDrag()28402     boolean canAcceptDrag() {
28403         return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
28404     }
28405 
sendWindowContentChangedAccessibilityEvent(int changeType)28406     void sendWindowContentChangedAccessibilityEvent(int changeType) {
28407         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
28408             AccessibilityEvent event = AccessibilityEvent.obtain();
28409             event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
28410             event.setContentChangeTypes(changeType);
28411             sendAccessibilityEventUnchecked(event);
28412         }
28413     }
28414 
28415     /**
28416      * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
28417      * it is ever exposed at all.
28418      * @hide
28419      */
28420     @UnsupportedAppUsage
onCloseSystemDialogs(String reason)28421     public void onCloseSystemDialogs(String reason) {
28422     }
28423 
28424     /**
28425      * Given a Drawable whose bounds have been set to draw into this view,
28426      * update a Region being computed for
28427      * {@link #gatherTransparentRegion(android.graphics.Region)} so
28428      * that any non-transparent parts of the Drawable are removed from the
28429      * given transparent region.
28430      *
28431      * @param dr The Drawable whose transparency is to be applied to the region.
28432      * @param region A Region holding the current transparency information,
28433      * where any parts of the region that are set are considered to be
28434      * transparent.  On return, this region will be modified to have the
28435      * transparency information reduced by the corresponding parts of the
28436      * Drawable that are not transparent.
28437      * {@hide}
28438      */
28439     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
applyDrawableToTransparentRegion(Drawable dr, Region region)28440     public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
28441         if (DBG) {
28442             Log.i("View", "Getting transparent region for: " + this);
28443         }
28444         final Region r = dr.getTransparentRegion();
28445         final Rect db = dr.getBounds();
28446         final AttachInfo attachInfo = mAttachInfo;
28447         if (r != null && attachInfo != null) {
28448             final int w = getRight()-getLeft();
28449             final int h = getBottom()-getTop();
28450             if (db.left > 0) {
28451                 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
28452                 r.op(0, 0, db.left, h, Region.Op.UNION);
28453             }
28454             if (db.right < w) {
28455                 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
28456                 r.op(db.right, 0, w, h, Region.Op.UNION);
28457             }
28458             if (db.top > 0) {
28459                 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
28460                 r.op(0, 0, w, db.top, Region.Op.UNION);
28461             }
28462             if (db.bottom < h) {
28463                 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
28464                 r.op(0, db.bottom, w, h, Region.Op.UNION);
28465             }
28466             final int[] location = attachInfo.mTransparentLocation;
28467             getLocationInWindow(location);
28468             r.translate(location[0], location[1]);
28469             region.op(r, Region.Op.INTERSECT);
28470         } else {
28471             region.op(db, Region.Op.DIFFERENCE);
28472         }
28473     }
28474 
checkForLongClick(long delay, float x, float y, int classification)28475     private void checkForLongClick(long delay, float x, float y, int classification) {
28476         if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
28477             mHasPerformedLongPress = false;
28478 
28479             if (mPendingCheckForLongPress == null) {
28480                 mPendingCheckForLongPress = new CheckForLongPress();
28481             }
28482             mPendingCheckForLongPress.setAnchor(x, y);
28483             mPendingCheckForLongPress.rememberWindowAttachCount();
28484             mPendingCheckForLongPress.rememberPressedState();
28485             mPendingCheckForLongPress.setClassification(classification);
28486             postDelayed(mPendingCheckForLongPress, delay);
28487         }
28488     }
28489 
28490     /**
28491      * Inflate a view from an XML resource.  This convenience method wraps the {@link
28492      * LayoutInflater} class, which provides a full range of options for view inflation.
28493      *
28494      * @param context The Context object for your activity or application.
28495      * @param resource The resource ID to inflate
28496      * @param root A view group that will be the parent.  Used to properly inflate the
28497      * layout_* parameters.
28498      * @see LayoutInflater
28499      */
inflate(Context context, @LayoutRes int resource, ViewGroup root)28500     public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
28501         LayoutInflater factory = LayoutInflater.from(context);
28502         return factory.inflate(resource, root);
28503     }
28504 
28505     /**
28506      * Scroll the view with standard behavior for scrolling beyond the normal
28507      * content boundaries. Views that call this method should override
28508      * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
28509      * results of an over-scroll operation.
28510      *
28511      * Views can use this method to handle any touch or fling-based scrolling.
28512      *
28513      * @param deltaX Change in X in pixels
28514      * @param deltaY Change in Y in pixels
28515      * @param scrollX Current X scroll value in pixels before applying deltaX
28516      * @param scrollY Current Y scroll value in pixels before applying deltaY
28517      * @param scrollRangeX Maximum content scroll range along the X axis
28518      * @param scrollRangeY Maximum content scroll range along the Y axis
28519      * @param maxOverScrollX Number of pixels to overscroll by in either direction
28520      *          along the X axis.
28521      * @param maxOverScrollY Number of pixels to overscroll by in either direction
28522      *          along the Y axis.
28523      * @param isTouchEvent true if this scroll operation is the result of a touch event.
28524      * @return true if scrolling was clamped to an over-scroll boundary along either
28525      *          axis, false otherwise.
28526      */
28527     @SuppressWarnings({"UnusedParameters"})
overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent)28528     protected boolean overScrollBy(int deltaX, int deltaY,
28529             int scrollX, int scrollY,
28530             int scrollRangeX, int scrollRangeY,
28531             int maxOverScrollX, int maxOverScrollY,
28532             boolean isTouchEvent) {
28533         final int overScrollMode = mOverScrollMode;
28534         final boolean canScrollHorizontal =
28535                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
28536         final boolean canScrollVertical =
28537                 computeVerticalScrollRange() > computeVerticalScrollExtent();
28538         final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
28539                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
28540         final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
28541                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
28542 
28543         int newScrollX = scrollX + deltaX;
28544         if (!overScrollHorizontal) {
28545             maxOverScrollX = 0;
28546         }
28547 
28548         int newScrollY = scrollY + deltaY;
28549         if (!overScrollVertical) {
28550             maxOverScrollY = 0;
28551         }
28552 
28553         // Clamp values if at the limits and record
28554         final int left = -maxOverScrollX;
28555         final int right = maxOverScrollX + scrollRangeX;
28556         final int top = -maxOverScrollY;
28557         final int bottom = maxOverScrollY + scrollRangeY;
28558 
28559         boolean clampedX = false;
28560         if (newScrollX > right) {
28561             newScrollX = right;
28562             clampedX = true;
28563         } else if (newScrollX < left) {
28564             newScrollX = left;
28565             clampedX = true;
28566         }
28567 
28568         boolean clampedY = false;
28569         if (newScrollY > bottom) {
28570             newScrollY = bottom;
28571             clampedY = true;
28572         } else if (newScrollY < top) {
28573             newScrollY = top;
28574             clampedY = true;
28575         }
28576 
28577         onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
28578 
28579         return clampedX || clampedY;
28580     }
28581 
28582     /**
28583      * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
28584      * respond to the results of an over-scroll operation.
28585      *
28586      * @param scrollX New X scroll value in pixels
28587      * @param scrollY New Y scroll value in pixels
28588      * @param clampedX True if scrollX was clamped to an over-scroll boundary
28589      * @param clampedY True if scrollY was clamped to an over-scroll boundary
28590      */
onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY)28591     protected void onOverScrolled(int scrollX, int scrollY,
28592             boolean clampedX, boolean clampedY) {
28593         // Intentionally empty.
28594     }
28595 
28596     /**
28597      * Returns the over-scroll mode for this view. The result will be
28598      * one of {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
28599      * (allow over-scrolling only if the view content is larger than the container),
28600      * or {@link #OVER_SCROLL_NEVER}.
28601      *
28602      * @return This view's over-scroll mode.
28603      */
28604     @InspectableProperty(enumMapping = {
28605             @EnumEntry(value = OVER_SCROLL_ALWAYS, name = "always"),
28606             @EnumEntry(value = OVER_SCROLL_IF_CONTENT_SCROLLS, name = "ifContentScrolls"),
28607             @EnumEntry(value = OVER_SCROLL_NEVER, name = "never")
28608     })
getOverScrollMode()28609     public int getOverScrollMode() {
28610         return mOverScrollMode;
28611     }
28612 
28613     /**
28614      * Set the over-scroll mode for this view. Valid over-scroll modes are
28615      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
28616      * (allow over-scrolling only if the view content is larger than the container),
28617      * or {@link #OVER_SCROLL_NEVER}.
28618      *
28619      * Setting the over-scroll mode of a view will have an effect only if the
28620      * view is capable of scrolling.
28621      *
28622      * @param overScrollMode The new over-scroll mode for this view.
28623      */
setOverScrollMode(int overScrollMode)28624     public void setOverScrollMode(int overScrollMode) {
28625         if (overScrollMode != OVER_SCROLL_ALWAYS &&
28626                 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
28627                 overScrollMode != OVER_SCROLL_NEVER) {
28628             throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
28629         }
28630         mOverScrollMode = overScrollMode;
28631     }
28632 
28633     /**
28634      * Enable or disable nested scrolling for this view.
28635      *
28636      * <p>If this property is set to true the view will be permitted to initiate nested
28637      * scrolling operations with a compatible parent view in the current hierarchy. If this
28638      * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
28639      * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
28640      * the nested scroll.</p>
28641      *
28642      * @param enabled true to enable nested scrolling, false to disable
28643      *
28644      * @see #isNestedScrollingEnabled()
28645      */
setNestedScrollingEnabled(boolean enabled)28646     public void setNestedScrollingEnabled(boolean enabled) {
28647         if (enabled) {
28648             mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
28649         } else {
28650             stopNestedScroll();
28651             mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
28652         }
28653     }
28654 
28655     /**
28656      * Returns true if nested scrolling is enabled for this view.
28657      *
28658      * <p>If nested scrolling is enabled and this View class implementation supports it,
28659      * this view will act as a nested scrolling child view when applicable, forwarding data
28660      * about the scroll operation in progress to a compatible and cooperating nested scrolling
28661      * parent.</p>
28662      *
28663      * @return true if nested scrolling is enabled
28664      *
28665      * @see #setNestedScrollingEnabled(boolean)
28666      */
28667     @InspectableProperty
isNestedScrollingEnabled()28668     public boolean isNestedScrollingEnabled() {
28669         return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
28670                 PFLAG3_NESTED_SCROLLING_ENABLED;
28671     }
28672 
28673     /**
28674      * Begin a nestable scroll operation along the given axes.
28675      *
28676      * <p>A view starting a nested scroll promises to abide by the following contract:</p>
28677      *
28678      * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
28679      * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
28680      * In the case of touch scrolling the nested scroll will be terminated automatically in
28681      * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
28682      * In the event of programmatic scrolling the caller must explicitly call
28683      * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
28684      *
28685      * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
28686      * If it returns false the caller may ignore the rest of this contract until the next scroll.
28687      * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
28688      *
28689      * <p>At each incremental step of the scroll the caller should invoke
28690      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
28691      * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
28692      * parent at least partially consumed the scroll and the caller should adjust the amount it
28693      * scrolls by.</p>
28694      *
28695      * <p>After applying the remainder of the scroll delta the caller should invoke
28696      * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
28697      * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
28698      * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
28699      * </p>
28700      *
28701      * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
28702      *             {@link #SCROLL_AXIS_VERTICAL}.
28703      * @return true if a cooperative parent was found and nested scrolling has been enabled for
28704      *         the current gesture.
28705      *
28706      * @see #stopNestedScroll()
28707      * @see #dispatchNestedPreScroll(int, int, int[], int[])
28708      * @see #dispatchNestedScroll(int, int, int, int, int[])
28709      */
startNestedScroll(int axes)28710     public boolean startNestedScroll(int axes) {
28711         if (hasNestedScrollingParent()) {
28712             // Already in progress
28713             return true;
28714         }
28715         if (isNestedScrollingEnabled()) {
28716             ViewParent p = getParent();
28717             View child = this;
28718             while (p != null) {
28719                 try {
28720                     if (p.onStartNestedScroll(child, this, axes)) {
28721                         mNestedScrollingParent = p;
28722                         p.onNestedScrollAccepted(child, this, axes);
28723                         return true;
28724                     }
28725                 } catch (AbstractMethodError e) {
28726                     Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
28727                             "method onStartNestedScroll", e);
28728                     // Allow the search upward to continue
28729                 }
28730                 if (p instanceof View) {
28731                     child = (View) p;
28732                 }
28733                 p = p.getParent();
28734             }
28735         }
28736         return false;
28737     }
28738 
28739     /**
28740      * Stop a nested scroll in progress.
28741      *
28742      * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
28743      *
28744      * @see #startNestedScroll(int)
28745      */
stopNestedScroll()28746     public void stopNestedScroll() {
28747         if (mNestedScrollingParent != null) {
28748             mNestedScrollingParent.onStopNestedScroll(this);
28749             mNestedScrollingParent = null;
28750         }
28751     }
28752 
28753     /**
28754      * Returns true if this view has a nested scrolling parent.
28755      *
28756      * <p>The presence of a nested scrolling parent indicates that this view has initiated
28757      * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
28758      *
28759      * @return whether this view has a nested scrolling parent
28760      */
hasNestedScrollingParent()28761     public boolean hasNestedScrollingParent() {
28762         return mNestedScrollingParent != null;
28763     }
28764 
28765     /**
28766      * Dispatch one step of a nested scroll in progress.
28767      *
28768      * <p>Implementations of views that support nested scrolling should call this to report
28769      * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
28770      * is not currently in progress or nested scrolling is not
28771      * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
28772      *
28773      * <p>Compatible View implementations should also call
28774      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
28775      * consuming a component of the scroll event themselves.</p>
28776      *
28777      * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
28778      * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
28779      * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
28780      * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
28781      * @param offsetInWindow Optional. If not null, on return this will contain the offset
28782      *                       in local view coordinates of this view from before this operation
28783      *                       to after it completes. View implementations may use this to adjust
28784      *                       expected input coordinate tracking.
28785      * @return true if the event was dispatched, false if it could not be dispatched.
28786      * @see #dispatchNestedPreScroll(int, int, int[], int[])
28787      */
dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow)28788     public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
28789             int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
28790         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
28791             if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
28792                 int startX = 0;
28793                 int startY = 0;
28794                 if (offsetInWindow != null) {
28795                     getLocationInWindow(offsetInWindow);
28796                     startX = offsetInWindow[0];
28797                     startY = offsetInWindow[1];
28798                 }
28799 
28800                 mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
28801                         dxUnconsumed, dyUnconsumed);
28802 
28803                 if (offsetInWindow != null) {
28804                     getLocationInWindow(offsetInWindow);
28805                     offsetInWindow[0] -= startX;
28806                     offsetInWindow[1] -= startY;
28807                 }
28808                 return true;
28809             } else if (offsetInWindow != null) {
28810                 // No motion, no dispatch. Keep offsetInWindow up to date.
28811                 offsetInWindow[0] = 0;
28812                 offsetInWindow[1] = 0;
28813             }
28814         }
28815         return false;
28816     }
28817 
28818     /**
28819      * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
28820      *
28821      * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
28822      * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
28823      * scrolling operation to consume some or all of the scroll operation before the child view
28824      * consumes it.</p>
28825      *
28826      * @param dx Horizontal scroll distance in pixels
28827      * @param dy Vertical scroll distance in pixels
28828      * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
28829      *                 and consumed[1] the consumed dy.
28830      * @param offsetInWindow Optional. If not null, on return this will contain the offset
28831      *                       in local view coordinates of this view from before this operation
28832      *                       to after it completes. View implementations may use this to adjust
28833      *                       expected input coordinate tracking.
28834      * @return true if the parent consumed some or all of the scroll delta
28835      * @see #dispatchNestedScroll(int, int, int, int, int[])
28836      */
dispatchNestedPreScroll(int dx, int dy, @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow)28837     public boolean dispatchNestedPreScroll(int dx, int dy,
28838             @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
28839         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
28840             if (dx != 0 || dy != 0) {
28841                 int startX = 0;
28842                 int startY = 0;
28843                 if (offsetInWindow != null) {
28844                     getLocationInWindow(offsetInWindow);
28845                     startX = offsetInWindow[0];
28846                     startY = offsetInWindow[1];
28847                 }
28848 
28849                 if (consumed == null) {
28850                     if (mTempNestedScrollConsumed == null) {
28851                         mTempNestedScrollConsumed = new int[2];
28852                     }
28853                     consumed = mTempNestedScrollConsumed;
28854                 }
28855                 consumed[0] = 0;
28856                 consumed[1] = 0;
28857                 mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
28858 
28859                 if (offsetInWindow != null) {
28860                     getLocationInWindow(offsetInWindow);
28861                     offsetInWindow[0] -= startX;
28862                     offsetInWindow[1] -= startY;
28863                 }
28864                 return consumed[0] != 0 || consumed[1] != 0;
28865             } else if (offsetInWindow != null) {
28866                 offsetInWindow[0] = 0;
28867                 offsetInWindow[1] = 0;
28868             }
28869         }
28870         return false;
28871     }
28872 
28873     /**
28874      * Dispatch a fling to a nested scrolling parent.
28875      *
28876      * <p>This method should be used to indicate that a nested scrolling child has detected
28877      * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
28878      * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
28879      * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
28880      * along a scrollable axis.</p>
28881      *
28882      * <p>If a nested scrolling child view would normally fling but it is at the edge of
28883      * its own content, it can use this method to delegate the fling to its nested scrolling
28884      * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
28885      *
28886      * @param velocityX Horizontal fling velocity in pixels per second
28887      * @param velocityY Vertical fling velocity in pixels per second
28888      * @param consumed true if the child consumed the fling, false otherwise
28889      * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
28890      */
dispatchNestedFling(float velocityX, float velocityY, boolean consumed)28891     public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
28892         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
28893             return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
28894         }
28895         return false;
28896     }
28897 
28898     /**
28899      * Dispatch a fling to a nested scrolling parent before it is processed by this view.
28900      *
28901      * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
28902      * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
28903      * offsets an opportunity for the parent view in a nested fling to fully consume the fling
28904      * before the child view consumes it. If this method returns <code>true</code>, a nested
28905      * parent view consumed the fling and this view should not scroll as a result.</p>
28906      *
28907      * <p>For a better user experience, only one view in a nested scrolling chain should consume
28908      * the fling at a time. If a parent view consumed the fling this method will return false.
28909      * Custom view implementations should account for this in two ways:</p>
28910      *
28911      * <ul>
28912      *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
28913      *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
28914      *     position regardless.</li>
28915      *     <li>If a nested parent does consume the fling, this view should not scroll at all,
28916      *     even to settle back to a valid idle position.</li>
28917      * </ul>
28918      *
28919      * <p>Views should also not offer fling velocities to nested parent views along an axis
28920      * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
28921      * should not offer a horizontal fling velocity to its parents since scrolling along that
28922      * axis is not permitted and carrying velocity along that motion does not make sense.</p>
28923      *
28924      * @param velocityX Horizontal fling velocity in pixels per second
28925      * @param velocityY Vertical fling velocity in pixels per second
28926      * @return true if a nested scrolling parent consumed the fling
28927      */
dispatchNestedPreFling(float velocityX, float velocityY)28928     public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
28929         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
28930             return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
28931         }
28932         return false;
28933     }
28934 
28935     /**
28936      * Gets a scale factor that determines the distance the view should scroll
28937      * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
28938      * @return The vertical scroll scale factor.
28939      * @hide
28940      */
28941     @UnsupportedAppUsage
getVerticalScrollFactor()28942     protected float getVerticalScrollFactor() {
28943         if (mVerticalScrollFactor == 0) {
28944             TypedValue outValue = new TypedValue();
28945             if (!mContext.getTheme().resolveAttribute(
28946                     com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
28947                 throw new IllegalStateException(
28948                         "Expected theme to define listPreferredItemHeight.");
28949             }
28950             mVerticalScrollFactor = outValue.getDimension(
28951                     mContext.getResources().getDisplayMetrics());
28952         }
28953         return mVerticalScrollFactor;
28954     }
28955 
28956     /**
28957      * Gets a scale factor that determines the distance the view should scroll
28958      * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
28959      * @return The horizontal scroll scale factor.
28960      * @hide
28961      */
28962     @UnsupportedAppUsage
getHorizontalScrollFactor()28963     protected float getHorizontalScrollFactor() {
28964         // TODO: Should use something else.
28965         return getVerticalScrollFactor();
28966     }
28967 
28968     /**
28969      * Return the value specifying the text direction or policy that was set with
28970      * {@link #setTextDirection(int)}.
28971      *
28972      * @return the defined text direction. It can be one of:
28973      *
28974      * {@link #TEXT_DIRECTION_INHERIT},
28975      * {@link #TEXT_DIRECTION_FIRST_STRONG},
28976      * {@link #TEXT_DIRECTION_ANY_RTL},
28977      * {@link #TEXT_DIRECTION_LTR},
28978      * {@link #TEXT_DIRECTION_RTL},
28979      * {@link #TEXT_DIRECTION_LOCALE},
28980      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
28981      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
28982      *
28983      * @attr ref android.R.styleable#View_textDirection
28984      *
28985      * @hide
28986      */
28987     @ViewDebug.ExportedProperty(category = "text", mapping = {
28988             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
28989             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
28990             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
28991             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
28992             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
28993             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
28994             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
28995             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
28996     })
28997     @InspectableProperty(hasAttributeId = false, enumMapping = {
28998             @EnumEntry(value = TEXT_DIRECTION_INHERIT, name = "inherit"),
28999             @EnumEntry(value = TEXT_DIRECTION_LOCALE, name = "locale"),
29000             @EnumEntry(value = TEXT_DIRECTION_ANY_RTL, name = "anyRtl"),
29001             @EnumEntry(value = TEXT_DIRECTION_LTR, name = "ltr"),
29002             @EnumEntry(value = TEXT_DIRECTION_RTL, name = "rtl"),
29003             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG, name = "firstStrong"),
29004             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_LTR, name = "firstStrongLtr"),
29005             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_RTL, name = "firstStrongRtl"),
29006     })
29007     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getRawTextDirection()29008     public int getRawTextDirection() {
29009         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
29010     }
29011 
29012     /**
29013      * Set the text direction.
29014      *
29015      * @param textDirection the direction to set. Should be one of:
29016      *
29017      * {@link #TEXT_DIRECTION_INHERIT},
29018      * {@link #TEXT_DIRECTION_FIRST_STRONG},
29019      * {@link #TEXT_DIRECTION_ANY_RTL},
29020      * {@link #TEXT_DIRECTION_LTR},
29021      * {@link #TEXT_DIRECTION_RTL},
29022      * {@link #TEXT_DIRECTION_LOCALE}
29023      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
29024      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
29025      *
29026      * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
29027      * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
29028      * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
29029      *
29030      * @attr ref android.R.styleable#View_textDirection
29031      */
setTextDirection(int textDirection)29032     public void setTextDirection(int textDirection) {
29033         if (getRawTextDirection() != textDirection) {
29034             // Reset the current text direction and the resolved one
29035             mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
29036             resetResolvedTextDirection();
29037             // Set the new text direction
29038             mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
29039             // Do resolution
29040             resolveTextDirection();
29041             // Notify change
29042             onRtlPropertiesChanged(getLayoutDirection());
29043             // Refresh
29044             requestLayout();
29045             invalidate(true);
29046         }
29047     }
29048 
29049     /**
29050      * Return the resolved text direction.
29051      *
29052      * @return the resolved text direction. Returns one of:
29053      *
29054      * {@link #TEXT_DIRECTION_FIRST_STRONG},
29055      * {@link #TEXT_DIRECTION_ANY_RTL},
29056      * {@link #TEXT_DIRECTION_LTR},
29057      * {@link #TEXT_DIRECTION_RTL},
29058      * {@link #TEXT_DIRECTION_LOCALE},
29059      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
29060      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
29061      *
29062      * @attr ref android.R.styleable#View_textDirection
29063      */
29064     @ViewDebug.ExportedProperty(category = "text", mapping = {
29065             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
29066             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
29067             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
29068             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
29069             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
29070             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
29071             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
29072             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
29073     })
29074     @InspectableProperty(hasAttributeId = false, enumMapping = {
29075             @EnumEntry(value = TEXT_DIRECTION_LOCALE, name = "locale"),
29076             @EnumEntry(value = TEXT_DIRECTION_ANY_RTL, name = "anyRtl"),
29077             @EnumEntry(value = TEXT_DIRECTION_LTR, name = "ltr"),
29078             @EnumEntry(value = TEXT_DIRECTION_RTL, name = "rtl"),
29079             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG, name = "firstStrong"),
29080             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_LTR, name = "firstStrongLtr"),
29081             @EnumEntry(value = TEXT_DIRECTION_FIRST_STRONG_RTL, name = "firstStrongRtl"),
29082     })
getTextDirection()29083     public int getTextDirection() {
29084         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
29085     }
29086 
29087     /**
29088      * Resolve the text direction.
29089      *
29090      * @return true if resolution has been done, false otherwise.
29091      *
29092      * @hide
29093      */
resolveTextDirection()29094     public boolean resolveTextDirection() {
29095         // Reset any previous text direction resolution
29096         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
29097 
29098         if (hasRtlSupport()) {
29099             // Set resolved text direction flag depending on text direction flag
29100             final int textDirection = getRawTextDirection();
29101             switch(textDirection) {
29102                 case TEXT_DIRECTION_INHERIT:
29103                     if (!canResolveTextDirection()) {
29104                         // We cannot do the resolution if there is no parent, so use the default one
29105                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
29106                         // Resolution will need to happen again later
29107                         return false;
29108                     }
29109 
29110                     // Parent has not yet resolved, so we still return the default
29111                     try {
29112                         if (!mParent.isTextDirectionResolved()) {
29113                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
29114                             // Resolution will need to happen again later
29115                             return false;
29116                         }
29117                     } catch (AbstractMethodError e) {
29118                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
29119                                 " does not fully implement ViewParent", e);
29120                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
29121                                 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
29122                         return true;
29123                     }
29124 
29125                     // Set current resolved direction to the same value as the parent's one
29126                     int parentResolvedDirection;
29127                     try {
29128                         parentResolvedDirection = mParent.getTextDirection();
29129                     } catch (AbstractMethodError e) {
29130                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
29131                                 " does not fully implement ViewParent", e);
29132                         parentResolvedDirection = TEXT_DIRECTION_LTR;
29133                     }
29134                     switch (parentResolvedDirection) {
29135                         case TEXT_DIRECTION_FIRST_STRONG:
29136                         case TEXT_DIRECTION_ANY_RTL:
29137                         case TEXT_DIRECTION_LTR:
29138                         case TEXT_DIRECTION_RTL:
29139                         case TEXT_DIRECTION_LOCALE:
29140                         case TEXT_DIRECTION_FIRST_STRONG_LTR:
29141                         case TEXT_DIRECTION_FIRST_STRONG_RTL:
29142                             mPrivateFlags2 |=
29143                                     (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
29144                             break;
29145                         default:
29146                             // Default resolved direction is "first strong" heuristic
29147                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
29148                     }
29149                     break;
29150                 case TEXT_DIRECTION_FIRST_STRONG:
29151                 case TEXT_DIRECTION_ANY_RTL:
29152                 case TEXT_DIRECTION_LTR:
29153                 case TEXT_DIRECTION_RTL:
29154                 case TEXT_DIRECTION_LOCALE:
29155                 case TEXT_DIRECTION_FIRST_STRONG_LTR:
29156                 case TEXT_DIRECTION_FIRST_STRONG_RTL:
29157                     // Resolved direction is the same as text direction
29158                     mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
29159                     break;
29160                 default:
29161                     // Default resolved direction is "first strong" heuristic
29162                     mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
29163             }
29164         } else {
29165             // Default resolved direction is "first strong" heuristic
29166             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
29167         }
29168 
29169         // Set to resolved
29170         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
29171         return true;
29172     }
29173 
29174     /**
29175      * Check if text direction resolution can be done.
29176      *
29177      * @return true if text direction resolution can be done otherwise return false.
29178      */
canResolveTextDirection()29179     public boolean canResolveTextDirection() {
29180         switch (getRawTextDirection()) {
29181             case TEXT_DIRECTION_INHERIT:
29182                 if (mParent != null) {
29183                     try {
29184                         return mParent.canResolveTextDirection();
29185                     } catch (AbstractMethodError e) {
29186                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
29187                                 " does not fully implement ViewParent", e);
29188                     }
29189                 }
29190                 return false;
29191 
29192             default:
29193                 return true;
29194         }
29195     }
29196 
29197     /**
29198      * Reset resolved text direction. Text direction will be resolved during a call to
29199      * {@link #onMeasure(int, int)}.
29200      *
29201      * @hide
29202      */
29203     @TestApi
resetResolvedTextDirection()29204     public void resetResolvedTextDirection() {
29205         // Reset any previous text direction resolution
29206         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
29207         // Set to default value
29208         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
29209     }
29210 
29211     /**
29212      * @return true if text direction is inherited.
29213      *
29214      * @hide
29215      */
isTextDirectionInherited()29216     public boolean isTextDirectionInherited() {
29217         return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
29218     }
29219 
29220     /**
29221      * @return true if text direction is resolved.
29222      */
isTextDirectionResolved()29223     public boolean isTextDirectionResolved() {
29224         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
29225     }
29226 
29227     /**
29228      * Return the value specifying the text alignment or policy that was set with
29229      * {@link #setTextAlignment(int)}.
29230      *
29231      * @return the defined text alignment. It can be one of:
29232      *
29233      * {@link #TEXT_ALIGNMENT_INHERIT},
29234      * {@link #TEXT_ALIGNMENT_GRAVITY},
29235      * {@link #TEXT_ALIGNMENT_CENTER},
29236      * {@link #TEXT_ALIGNMENT_TEXT_START},
29237      * {@link #TEXT_ALIGNMENT_TEXT_END},
29238      * {@link #TEXT_ALIGNMENT_VIEW_START},
29239      * {@link #TEXT_ALIGNMENT_VIEW_END}
29240      *
29241      * @attr ref android.R.styleable#View_textAlignment
29242      *
29243      * @hide
29244      */
29245     @ViewDebug.ExportedProperty(category = "text", mapping = {
29246             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
29247             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
29248             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
29249             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
29250             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
29251             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
29252             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
29253     })
29254     @InspectableProperty(hasAttributeId = false, enumMapping = {
29255             @EnumEntry(value = TEXT_ALIGNMENT_INHERIT, name = "inherit"),
29256             @EnumEntry(value = TEXT_ALIGNMENT_GRAVITY, name = "gravity"),
29257             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_START, name = "textStart"),
29258             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_END, name = "textEnd"),
29259             @EnumEntry(value = TEXT_ALIGNMENT_CENTER, name = "center"),
29260             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_START, name = "viewStart"),
29261             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_END, name = "viewEnd")
29262     })
29263     @TextAlignment
29264     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getRawTextAlignment()29265     public int getRawTextAlignment() {
29266         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
29267     }
29268 
29269     /**
29270      * Set the text alignment.
29271      *
29272      * @param textAlignment The text alignment to set. Should be one of
29273      *
29274      * {@link #TEXT_ALIGNMENT_INHERIT},
29275      * {@link #TEXT_ALIGNMENT_GRAVITY},
29276      * {@link #TEXT_ALIGNMENT_CENTER},
29277      * {@link #TEXT_ALIGNMENT_TEXT_START},
29278      * {@link #TEXT_ALIGNMENT_TEXT_END},
29279      * {@link #TEXT_ALIGNMENT_VIEW_START},
29280      * {@link #TEXT_ALIGNMENT_VIEW_END}
29281      *
29282      * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
29283      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
29284      * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
29285      *
29286      * @attr ref android.R.styleable#View_textAlignment
29287      */
setTextAlignment(@extAlignment int textAlignment)29288     public void setTextAlignment(@TextAlignment int textAlignment) {
29289         if (textAlignment != getRawTextAlignment()) {
29290             // Reset the current and resolved text alignment
29291             mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
29292             resetResolvedTextAlignment();
29293             // Set the new text alignment
29294             mPrivateFlags2 |=
29295                     ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
29296             // Do resolution
29297             resolveTextAlignment();
29298             // Notify change
29299             onRtlPropertiesChanged(getLayoutDirection());
29300             // Refresh
29301             requestLayout();
29302             invalidate(true);
29303         }
29304     }
29305 
29306     /**
29307      * Return the resolved text alignment.
29308      *
29309      * @return the resolved text alignment. Returns one of:
29310      *
29311      * {@link #TEXT_ALIGNMENT_GRAVITY},
29312      * {@link #TEXT_ALIGNMENT_CENTER},
29313      * {@link #TEXT_ALIGNMENT_TEXT_START},
29314      * {@link #TEXT_ALIGNMENT_TEXT_END},
29315      * {@link #TEXT_ALIGNMENT_VIEW_START},
29316      * {@link #TEXT_ALIGNMENT_VIEW_END}
29317      *
29318      * @attr ref android.R.styleable#View_textAlignment
29319      */
29320     @ViewDebug.ExportedProperty(category = "text", mapping = {
29321             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
29322             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
29323             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
29324             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
29325             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
29326             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
29327             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
29328     })
29329     @InspectableProperty(enumMapping = {
29330             @EnumEntry(value = TEXT_ALIGNMENT_GRAVITY, name = "gravity"),
29331             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_START, name = "textStart"),
29332             @EnumEntry(value = TEXT_ALIGNMENT_TEXT_END, name = "textEnd"),
29333             @EnumEntry(value = TEXT_ALIGNMENT_CENTER, name = "center"),
29334             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_START, name = "viewStart"),
29335             @EnumEntry(value = TEXT_ALIGNMENT_VIEW_END, name = "viewEnd")
29336     })
29337     @TextAlignment
getTextAlignment()29338     public int getTextAlignment() {
29339         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
29340                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
29341     }
29342 
29343     /**
29344      * Resolve the text alignment.
29345      *
29346      * @return true if resolution has been done, false otherwise.
29347      *
29348      * @hide
29349      */
resolveTextAlignment()29350     public boolean resolveTextAlignment() {
29351         // Reset any previous text alignment resolution
29352         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
29353 
29354         if (hasRtlSupport()) {
29355             // Set resolved text alignment flag depending on text alignment flag
29356             final int textAlignment = getRawTextAlignment();
29357             switch (textAlignment) {
29358                 case TEXT_ALIGNMENT_INHERIT:
29359                     // Check if we can resolve the text alignment
29360                     if (!canResolveTextAlignment()) {
29361                         // We cannot do the resolution if there is no parent so use the default
29362                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
29363                         // Resolution will need to happen again later
29364                         return false;
29365                     }
29366 
29367                     // Parent has not yet resolved, so we still return the default
29368                     try {
29369                         if (!mParent.isTextAlignmentResolved()) {
29370                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
29371                             // Resolution will need to happen again later
29372                             return false;
29373                         }
29374                     } catch (AbstractMethodError e) {
29375                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
29376                                 " does not fully implement ViewParent", e);
29377                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
29378                                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
29379                         return true;
29380                     }
29381 
29382                     int parentResolvedTextAlignment;
29383                     try {
29384                         parentResolvedTextAlignment = mParent.getTextAlignment();
29385                     } catch (AbstractMethodError e) {
29386                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
29387                                 " does not fully implement ViewParent", e);
29388                         parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
29389                     }
29390                     switch (parentResolvedTextAlignment) {
29391                         case TEXT_ALIGNMENT_GRAVITY:
29392                         case TEXT_ALIGNMENT_TEXT_START:
29393                         case TEXT_ALIGNMENT_TEXT_END:
29394                         case TEXT_ALIGNMENT_CENTER:
29395                         case TEXT_ALIGNMENT_VIEW_START:
29396                         case TEXT_ALIGNMENT_VIEW_END:
29397                             // Resolved text alignment is the same as the parent resolved
29398                             // text alignment
29399                             mPrivateFlags2 |=
29400                                     (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
29401                             break;
29402                         default:
29403                             // Use default resolved text alignment
29404                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
29405                     }
29406                     break;
29407                 case TEXT_ALIGNMENT_GRAVITY:
29408                 case TEXT_ALIGNMENT_TEXT_START:
29409                 case TEXT_ALIGNMENT_TEXT_END:
29410                 case TEXT_ALIGNMENT_CENTER:
29411                 case TEXT_ALIGNMENT_VIEW_START:
29412                 case TEXT_ALIGNMENT_VIEW_END:
29413                     // Resolved text alignment is the same as text alignment
29414                     mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
29415                     break;
29416                 default:
29417                     // Use default resolved text alignment
29418                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
29419             }
29420         } else {
29421             // Use default resolved text alignment
29422             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
29423         }
29424 
29425         // Set the resolved
29426         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
29427         return true;
29428     }
29429 
29430     /**
29431      * Check if text alignment resolution can be done.
29432      *
29433      * @return true if text alignment resolution can be done otherwise return false.
29434      */
canResolveTextAlignment()29435     public boolean canResolveTextAlignment() {
29436         switch (getRawTextAlignment()) {
29437             case TEXT_DIRECTION_INHERIT:
29438                 if (mParent != null) {
29439                     try {
29440                         return mParent.canResolveTextAlignment();
29441                     } catch (AbstractMethodError e) {
29442                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
29443                                 " does not fully implement ViewParent", e);
29444                     }
29445                 }
29446                 return false;
29447 
29448             default:
29449                 return true;
29450         }
29451     }
29452 
29453     /**
29454      * Reset resolved text alignment. Text alignment will be resolved during a call to
29455      * {@link #onMeasure(int, int)}.
29456      *
29457      * @hide
29458      */
29459     @TestApi
resetResolvedTextAlignment()29460     public void resetResolvedTextAlignment() {
29461         // Reset any previous text alignment resolution
29462         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
29463         // Set to default
29464         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
29465     }
29466 
29467     /**
29468      * @return true if text alignment is inherited.
29469      *
29470      * @hide
29471      */
isTextAlignmentInherited()29472     public boolean isTextAlignmentInherited() {
29473         return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
29474     }
29475 
29476     /**
29477      * @return true if text alignment is resolved.
29478      */
isTextAlignmentResolved()29479     public boolean isTextAlignmentResolved() {
29480         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
29481     }
29482 
29483     /**
29484      * Generate a value suitable for use in {@link #setId(int)}.
29485      * This value will not collide with ID values generated at build time by aapt for R.id.
29486      *
29487      * @return a generated ID value
29488      */
generateViewId()29489     public static int generateViewId() {
29490         for (;;) {
29491             final int result = sNextGeneratedId.get();
29492             // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
29493             int newValue = result + 1;
29494             if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
29495             if (sNextGeneratedId.compareAndSet(result, newValue)) {
29496                 return result;
29497             }
29498         }
29499     }
29500 
isViewIdGenerated(int id)29501     private static boolean isViewIdGenerated(int id) {
29502         return (id & 0xFF000000) == 0 && (id & 0x00FFFFFF) != 0;
29503     }
29504 
29505     /**
29506      * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
29507      * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
29508      *                           a normal View or a ViewGroup with
29509      *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
29510      * @hide
29511      */
captureTransitioningViews(List<View> transitioningViews)29512     public void captureTransitioningViews(List<View> transitioningViews) {
29513         if (getVisibility() == View.VISIBLE) {
29514             transitioningViews.add(this);
29515         }
29516     }
29517 
29518     /**
29519      * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
29520      * @param namedElements Will contain all Views in the hierarchy having a transitionName.
29521      * @hide
29522      */
findNamedViews(Map<String, View> namedElements)29523     public void findNamedViews(Map<String, View> namedElements) {
29524         if (getVisibility() == VISIBLE || mGhostView != null) {
29525             String transitionName = getTransitionName();
29526             if (transitionName != null) {
29527                 namedElements.put(transitionName, this);
29528             }
29529         }
29530     }
29531 
29532     /**
29533      * Resolve the pointer icon that should be used for specified pointer in the motion event.
29534      *
29535      * The default implementation will resolve the pointer icon to one set using
29536      * {@link #setPointerIcon(PointerIcon)} for mouse devices. Subclasses may override this to
29537      * customize the icon for the given pointer.
29538      *
29539      * For example, the pointer icon for a stylus pointer can be resolved in the following way:
29540      * <code><pre>
29541      * &#64;Override
29542      * public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
29543      *     final int toolType = event.getToolType(pointerIndex);
29544      *     if (!event.isFromSource(InputDevice.SOURCE_MOUSE)
29545      *             && event.isFromSource(InputDevice.SOURCE_STYLUS)
29546      *             && (toolType == MotionEvent.TOOL_TYPE_STYLUS
29547      *                     || toolType == MotionEvent.TOOL_TYPE_ERASER)) {
29548      *         // Show this pointer icon only if this pointer is a stylus.
29549      *         return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_WAIT);
29550      *     }
29551      *     // Use the default logic for determining the pointer icon for other non-stylus pointers,
29552      *     // like for the mouse cursor.
29553      *     return super.onResolvePointerIcon(event, pointerIndex);
29554      * }
29555      * </pre></code>
29556      *
29557      * @param event The {@link MotionEvent} that requires a pointer icon to be resolved for one of
29558      *              pointers.
29559      * @param pointerIndex The index of the pointer in {@code event} for which to retrieve the
29560      *     {@link PointerIcon}. This will be between 0 and {@link MotionEvent#getPointerCount()}.
29561      * @return the pointer icon to use for specified pointer, or {@code null} if a pointer icon
29562      *     is not specified and the default icon should be used.
29563      * @see PointerIcon
29564      * @see InputManager#isStylusPointerIconEnabled()
29565      */
onResolvePointerIcon(MotionEvent event, int pointerIndex)29566     public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
29567         final float x = event.getX(pointerIndex);
29568         final float y = event.getY(pointerIndex);
29569         if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
29570             // Use the default pointer icon.
29571             return null;
29572         }
29573 
29574         // Note: A drawing tablet will have both SOURCE_MOUSE and SOURCE_STYLUS, but it would use
29575         // TOOL_TYPE_STYLUS. For now, treat drawing tablets the same way as a mouse or touchpad.
29576         if (event.isFromSource(InputDevice.SOURCE_MOUSE)) {
29577             return mMousePointerIcon;
29578         }
29579 
29580         return null;
29581     }
29582 
29583     /**
29584      * Set the pointer icon to be used for a mouse pointer in the current view.
29585      *
29586      * Passing {@code null} will restore the pointer icon to its default value.
29587      * Note that setting the pointer icon using this method will only set it for events coming from
29588      * a mouse device (i.e. with source {@link InputDevice#SOURCE_MOUSE}). To resolve
29589      * the pointer icon for other device types like styluses, override
29590      * {@link #onResolvePointerIcon(MotionEvent, int)}.
29591      *
29592      * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
29593      * @see #onResolvePointerIcon(MotionEvent, int)
29594      * @see PointerIcon
29595      */
setPointerIcon(PointerIcon pointerIcon)29596     public void setPointerIcon(PointerIcon pointerIcon) {
29597         mMousePointerIcon = pointerIcon;
29598         if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
29599             return;
29600         }
29601         try {
29602             mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
29603         } catch (RemoteException e) {
29604         }
29605     }
29606 
29607     /**
29608      * Gets the mouse pointer icon for the current view.
29609      *
29610      * @see #setPointerIcon(PointerIcon)
29611      */
29612     @InspectableProperty
getPointerIcon()29613     public PointerIcon getPointerIcon() {
29614         return mMousePointerIcon;
29615     }
29616 
29617     /**
29618      * Checks pointer capture status.
29619      *
29620      * @return true if the view has pointer capture.
29621      * @see #requestPointerCapture()
29622      * @see #hasPointerCapture()
29623      */
hasPointerCapture()29624     public boolean hasPointerCapture() {
29625         final ViewRootImpl viewRootImpl = getViewRootImpl();
29626         if (viewRootImpl == null) {
29627             return false;
29628         }
29629         return viewRootImpl.hasPointerCapture();
29630     }
29631 
29632     /**
29633      * Requests pointer capture mode.
29634      * <p>
29635      * When the window has pointer capture, the mouse pointer icon will disappear and will not
29636      * change its position. Enabling pointer capture will change the behavior of input devices in
29637      * the following ways:
29638      * <ul>
29639      *     <li>Events from a mouse will be delivered with the source
29640      *     {@link InputDevice#SOURCE_MOUSE_RELATIVE}, and relative position changes will be
29641      *     available through {@link MotionEvent#getX} and {@link MotionEvent#getY}.</li>
29642      *
29643      *     <li>Events from a touchpad or trackpad will be delivered with the source
29644      *     {@link InputDevice#SOURCE_TOUCHPAD}, where the absolute position of each of the pointers
29645      *     on the touchpad will be available through {@link MotionEvent#getX(int)} and
29646      *     {@link MotionEvent#getY(int)}, and their relative movements are stored in
29647      *     {@link MotionEvent#AXIS_RELATIVE_X} and {@link MotionEvent#AXIS_RELATIVE_Y}.</li>
29648      *
29649      *     <li>Events from other types of devices, such as touchscreens, will not be affected.</li>
29650      * </ul>
29651      * <p>
29652      * When pointer capture changes, connected mouse and trackpad devices may be reconfigured,
29653      * and their properties (such as their sources or motion ranges) may change. Use an
29654      * {@link android.hardware.input.InputManager.InputDeviceListener} to be notified when a device
29655      * changes (which may happen after enabling or disabling pointer capture), and use
29656      * {@link InputDevice#getDevice(int)} to get the updated {@link InputDevice}.
29657      * <p>
29658      * Events captured through pointer capture will be dispatched to
29659      * {@link OnCapturedPointerListener#onCapturedPointer(View, MotionEvent)} if an
29660      * {@link OnCapturedPointerListener} is set, and otherwise to
29661      * {@link #onCapturedPointerEvent(MotionEvent)}.
29662      * <p>
29663      * If the window already has pointer capture, this call does nothing.
29664      * <p>
29665      * The capture may be released through {@link #releasePointerCapture()}, or will be lost
29666      * automatically when the window loses focus.
29667      *
29668      * @see #releasePointerCapture()
29669      * @see #hasPointerCapture()
29670      * @see #onPointerCaptureChange(boolean)
29671      */
requestPointerCapture()29672     public void requestPointerCapture() {
29673         final ViewRootImpl viewRootImpl = getViewRootImpl();
29674         if (viewRootImpl != null) {
29675             viewRootImpl.requestPointerCapture(true);
29676         }
29677     }
29678 
29679 
29680     /**
29681      * Releases the pointer capture.
29682      * <p>
29683      * If the window does not have pointer capture, this call will do nothing.
29684      * @see #requestPointerCapture()
29685      * @see #hasPointerCapture()
29686      * @see #onPointerCaptureChange(boolean)
29687      */
releasePointerCapture()29688     public void releasePointerCapture() {
29689         final ViewRootImpl viewRootImpl = getViewRootImpl();
29690         if (viewRootImpl != null) {
29691             viewRootImpl.requestPointerCapture(false);
29692         }
29693     }
29694 
29695     /**
29696      * Called when the window has just acquired or lost pointer capture.
29697      *
29698      * @param hasCapture True if the view now has pointerCapture, false otherwise.
29699      */
29700     @CallSuper
onPointerCaptureChange(boolean hasCapture)29701     public void onPointerCaptureChange(boolean hasCapture) {
29702     }
29703 
29704     /**
29705      * @see #onPointerCaptureChange
29706      */
dispatchPointerCaptureChanged(boolean hasCapture)29707     public void dispatchPointerCaptureChanged(boolean hasCapture) {
29708         onPointerCaptureChange(hasCapture);
29709     }
29710 
29711     /**
29712      * Implement this method to handle captured pointer events
29713      *
29714      * @param event The captured pointer event.
29715      * @return True if the event was handled, false otherwise.
29716      * @see #requestPointerCapture()
29717      */
onCapturedPointerEvent(MotionEvent event)29718     public boolean onCapturedPointerEvent(MotionEvent event) {
29719         return false;
29720     }
29721 
29722     /**
29723      * Interface definition for a callback to be invoked when a captured pointer event
29724      * is being dispatched this view. The callback will be invoked before the event is
29725      * given to the view.
29726      */
29727     public interface OnCapturedPointerListener {
29728         /**
29729          * Called when a captured pointer event is dispatched to a view.
29730          * @param view The view this event has been dispatched to.
29731          * @param event The captured event.
29732          * @return True if the listener has consumed the event, false otherwise.
29733          */
onCapturedPointer(View view, MotionEvent event)29734         boolean onCapturedPointer(View view, MotionEvent event);
29735     }
29736 
29737     /**
29738      * Set a listener to receive callbacks when the pointer capture state of a view changes.
29739      * @param l  The {@link OnCapturedPointerListener} to receive callbacks.
29740      */
setOnCapturedPointerListener(OnCapturedPointerListener l)29741     public void setOnCapturedPointerListener(OnCapturedPointerListener l) {
29742         getListenerInfo().mOnCapturedPointerListener = l;
29743     }
29744 
29745     // Properties
29746     //
29747     /**
29748      * A Property wrapper around the <code>alpha</code> functionality handled by the
29749      * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
29750      */
29751     public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
29752         @Override
29753         public void setValue(View object, float value) {
29754             object.setAlpha(value);
29755         }
29756 
29757         @Override
29758         public Float get(View object) {
29759             return object.getAlpha();
29760         }
29761     };
29762 
29763     /**
29764      * A Property wrapper around the <code>translationX</code> functionality handled by the
29765      * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
29766      */
29767     public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
29768         @Override
29769         public void setValue(View object, float value) {
29770             object.setTranslationX(value);
29771         }
29772 
29773                 @Override
29774         public Float get(View object) {
29775             return object.getTranslationX();
29776         }
29777     };
29778 
29779     /**
29780      * A Property wrapper around the <code>translationY</code> functionality handled by the
29781      * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
29782      */
29783     public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
29784         @Override
29785         public void setValue(View object, float value) {
29786             object.setTranslationY(value);
29787         }
29788 
29789         @Override
29790         public Float get(View object) {
29791             return object.getTranslationY();
29792         }
29793     };
29794 
29795     /**
29796      * A Property wrapper around the <code>translationZ</code> functionality handled by the
29797      * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
29798      */
29799     public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
29800         @Override
29801         public void setValue(View object, float value) {
29802             object.setTranslationZ(value);
29803         }
29804 
29805         @Override
29806         public Float get(View object) {
29807             return object.getTranslationZ();
29808         }
29809     };
29810 
29811     /**
29812      * A Property wrapper around the <code>x</code> functionality handled by the
29813      * {@link View#setX(float)} and {@link View#getX()} methods.
29814      */
29815     public static final Property<View, Float> X = new FloatProperty<View>("x") {
29816         @Override
29817         public void setValue(View object, float value) {
29818             object.setX(value);
29819         }
29820 
29821         @Override
29822         public Float get(View object) {
29823             return object.getX();
29824         }
29825     };
29826 
29827     /**
29828      * A Property wrapper around the <code>y</code> functionality handled by the
29829      * {@link View#setY(float)} and {@link View#getY()} methods.
29830      */
29831     public static final Property<View, Float> Y = new FloatProperty<View>("y") {
29832         @Override
29833         public void setValue(View object, float value) {
29834             object.setY(value);
29835         }
29836 
29837         @Override
29838         public Float get(View object) {
29839             return object.getY();
29840         }
29841     };
29842 
29843     /**
29844      * A Property wrapper around the <code>z</code> functionality handled by the
29845      * {@link View#setZ(float)} and {@link View#getZ()} methods.
29846      */
29847     public static final Property<View, Float> Z = new FloatProperty<View>("z") {
29848         @Override
29849         public void setValue(View object, float value) {
29850             object.setZ(value);
29851         }
29852 
29853         @Override
29854         public Float get(View object) {
29855             return object.getZ();
29856         }
29857     };
29858 
29859     /**
29860      * A Property wrapper around the <code>rotation</code> functionality handled by the
29861      * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
29862      */
29863     public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
29864         @Override
29865         public void setValue(View object, float value) {
29866             object.setRotation(value);
29867         }
29868 
29869         @Override
29870         public Float get(View object) {
29871             return object.getRotation();
29872         }
29873     };
29874 
29875     /**
29876      * A Property wrapper around the <code>rotationX</code> functionality handled by the
29877      * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
29878      */
29879     public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
29880         @Override
29881         public void setValue(View object, float value) {
29882             object.setRotationX(value);
29883         }
29884 
29885         @Override
29886         public Float get(View object) {
29887             return object.getRotationX();
29888         }
29889     };
29890 
29891     /**
29892      * A Property wrapper around the <code>rotationY</code> functionality handled by the
29893      * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
29894      */
29895     public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
29896         @Override
29897         public void setValue(View object, float value) {
29898             object.setRotationY(value);
29899         }
29900 
29901         @Override
29902         public Float get(View object) {
29903             return object.getRotationY();
29904         }
29905     };
29906 
29907     /**
29908      * A Property wrapper around the <code>scaleX</code> functionality handled by the
29909      * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
29910      */
29911     public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
29912         @Override
29913         public void setValue(View object, float value) {
29914             object.setScaleX(value);
29915         }
29916 
29917         @Override
29918         public Float get(View object) {
29919             return object.getScaleX();
29920         }
29921     };
29922 
29923     /**
29924      * A Property wrapper around the <code>scaleY</code> functionality handled by the
29925      * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
29926      */
29927     public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
29928         @Override
29929         public void setValue(View object, float value) {
29930             object.setScaleY(value);
29931         }
29932 
29933         @Override
29934         public Float get(View object) {
29935             return object.getScaleY();
29936         }
29937     };
29938 
29939     /**
29940      * A MeasureSpec encapsulates the layout requirements passed from parent to child.
29941      * Each MeasureSpec represents a requirement for either the width or the height.
29942      * A MeasureSpec is comprised of a size and a mode. There are three possible
29943      * modes:
29944      * <dl>
29945      * <dt>UNSPECIFIED</dt>
29946      * <dd>
29947      * The parent has not imposed any constraint on the child. It can be whatever size
29948      * it wants.
29949      * </dd>
29950      *
29951      * <dt>EXACTLY</dt>
29952      * <dd>
29953      * The parent has determined an exact size for the child. The child is going to be
29954      * given those bounds regardless of how big it wants to be.
29955      * </dd>
29956      *
29957      * <dt>AT_MOST</dt>
29958      * <dd>
29959      * The child can be as large as it wants up to the specified size.
29960      * </dd>
29961      * </dl>
29962      *
29963      * MeasureSpecs are implemented as ints to reduce object allocation. This class
29964      * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
29965      */
29966     public static class MeasureSpec {
29967         private static final int MODE_SHIFT = 30;
29968         private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
29969 
29970         /** @hide */
29971         @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
29972         @Retention(RetentionPolicy.SOURCE)
29973         public @interface MeasureSpecMode {}
29974 
29975         /**
29976          * Measure specification mode: The parent has not imposed any constraint
29977          * on the child. It can be whatever size it wants.
29978          */
29979         public static final int UNSPECIFIED = 0 << MODE_SHIFT;
29980 
29981         /**
29982          * Measure specification mode: The parent has determined an exact size
29983          * for the child. The child is going to be given those bounds regardless
29984          * of how big it wants to be.
29985          */
29986         public static final int EXACTLY     = 1 << MODE_SHIFT;
29987 
29988         /**
29989          * Measure specification mode: The child can be as large as it wants up
29990          * to the specified size.
29991          */
29992         public static final int AT_MOST     = 2 << MODE_SHIFT;
29993 
29994         /**
29995          * Creates a measure specification based on the supplied size and mode.
29996          *
29997          * The mode must always be one of the following:
29998          * <ul>
29999          *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
30000          *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
30001          *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
30002          * </ul>
30003          *
30004          * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
30005          * implementation was such that the order of arguments did not matter
30006          * and overflow in either value could impact the resulting MeasureSpec.
30007          * {@link android.widget.RelativeLayout} was affected by this bug.
30008          * Apps targeting API levels greater than 17 will get the fixed, more strict
30009          * behavior.</p>
30010          *
30011          * @param size the size of the measure specification
30012          * @param mode the mode of the measure specification
30013          * @return the measure specification based on size and mode
30014          */
makeMeasureSpec(@ntRangefrom = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size, @MeasureSpecMode int mode)30015         public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
30016                                           @MeasureSpecMode int mode) {
30017             if (sUseBrokenMakeMeasureSpec) {
30018                 return size + mode;
30019             } else {
30020                 return (size & ~MODE_MASK) | (mode & MODE_MASK);
30021             }
30022         }
30023 
30024         /**
30025          * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
30026          * will automatically get a size of 0. Older apps expect this.
30027          *
30028          * @hide internal use only for compatibility with system widgets and older apps
30029          */
30030         @UnsupportedAppUsage
makeSafeMeasureSpec(int size, int mode)30031         public static int makeSafeMeasureSpec(int size, int mode) {
30032             if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
30033                 return 0;
30034             }
30035             return makeMeasureSpec(size, mode);
30036         }
30037 
30038         /**
30039          * Extracts the mode from the supplied measure specification.
30040          *
30041          * @param measureSpec the measure specification to extract the mode from
30042          * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
30043          *         {@link android.view.View.MeasureSpec#AT_MOST} or
30044          *         {@link android.view.View.MeasureSpec#EXACTLY}
30045          */
30046         @MeasureSpecMode
getMode(int measureSpec)30047         public static int getMode(int measureSpec) {
30048             //noinspection ResourceType
30049             return (measureSpec & MODE_MASK);
30050         }
30051 
30052         /**
30053          * Extracts the size from the supplied measure specification.
30054          *
30055          * @param measureSpec the measure specification to extract the size from
30056          * @return the size in pixels defined in the supplied measure specification
30057          */
getSize(int measureSpec)30058         public static int getSize(int measureSpec) {
30059             return (measureSpec & ~MODE_MASK);
30060         }
30061 
adjust(int measureSpec, int delta)30062         static int adjust(int measureSpec, int delta) {
30063             final int mode = getMode(measureSpec);
30064             int size = getSize(measureSpec);
30065             if (mode == UNSPECIFIED) {
30066                 // No need to adjust size for UNSPECIFIED mode.
30067                 return makeMeasureSpec(size, UNSPECIFIED);
30068             }
30069             size += delta;
30070             if (size < 0) {
30071                 Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
30072                         ") spec: " + toString(measureSpec) + " delta: " + delta);
30073                 size = 0;
30074             }
30075             return makeMeasureSpec(size, mode);
30076         }
30077 
30078         /**
30079          * Returns a String representation of the specified measure
30080          * specification.
30081          *
30082          * @param measureSpec the measure specification to convert to a String
30083          * @return a String with the following format: "MeasureSpec: MODE SIZE"
30084          */
toString(int measureSpec)30085         public static String toString(int measureSpec) {
30086             int mode = getMode(measureSpec);
30087             int size = getSize(measureSpec);
30088 
30089             StringBuilder sb = new StringBuilder("MeasureSpec: ");
30090 
30091             if (mode == UNSPECIFIED)
30092                 sb.append("UNSPECIFIED ");
30093             else if (mode == EXACTLY)
30094                 sb.append("EXACTLY ");
30095             else if (mode == AT_MOST)
30096                 sb.append("AT_MOST ");
30097             else
30098                 sb.append(mode).append(" ");
30099 
30100             sb.append(size);
30101             return sb.toString();
30102         }
30103     }
30104 
30105     private final class CheckForLongPress implements Runnable {
30106         private int mOriginalWindowAttachCount;
30107         private float mX;
30108         private float mY;
30109         private boolean mOriginalPressedState;
30110         /**
30111          * The classification of the long click being checked: one of the
30112          * FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__* constants.
30113          */
30114         private int mClassification;
30115 
30116         @UnsupportedAppUsage
CheckForLongPress()30117         private CheckForLongPress() {
30118         }
30119 
30120         @Override
run()30121         public void run() {
30122             if ((mOriginalPressedState == isPressed()) && (mParent != null)
30123                     && mOriginalWindowAttachCount == mWindowAttachCount) {
30124                 recordGestureClassification(mClassification);
30125                 if (performLongClick(mX, mY)) {
30126                     mHasPerformedLongPress = true;
30127                 }
30128             }
30129         }
30130 
setAnchor(float x, float y)30131         public void setAnchor(float x, float y) {
30132             mX = x;
30133             mY = y;
30134         }
30135 
rememberWindowAttachCount()30136         public void rememberWindowAttachCount() {
30137             mOriginalWindowAttachCount = mWindowAttachCount;
30138         }
30139 
rememberPressedState()30140         public void rememberPressedState() {
30141             mOriginalPressedState = isPressed();
30142         }
30143 
setClassification(int classification)30144         public void setClassification(int classification) {
30145             mClassification = classification;
30146         }
30147     }
30148 
30149     private final class CheckForTap implements Runnable {
30150         public float x;
30151         public float y;
30152 
30153         @Override
run()30154         public void run() {
30155             mPrivateFlags &= ~PFLAG_PREPRESSED;
30156             setPressed(true, x, y);
30157             final long delay =
30158                     ViewConfiguration.getLongPressTimeout() - ViewConfiguration.getTapTimeout();
30159             checkForLongClick(delay, x, y, TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
30160         }
30161     }
30162 
30163     private final class PerformClick implements Runnable {
30164         @Override
run()30165         public void run() {
30166             recordGestureClassification(TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP);
30167             performClickInternal();
30168         }
30169     }
30170 
30171     /** Records a classification for the current event stream. */
recordGestureClassification(int classification)30172     private void recordGestureClassification(int classification) {
30173         if (classification == TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION) {
30174             return;
30175         }
30176         // To avoid negatively impacting View performance, the latency and displacement metrics
30177         // are omitted.
30178         FrameworkStatsLog.write(FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED, getClass().getName(),
30179                 classification);
30180     }
30181 
30182     /**
30183      * This method returns a ViewPropertyAnimator object, which can be used to animate
30184      * specific properties on this View.
30185      *
30186      * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
30187      */
animate()30188     public ViewPropertyAnimator animate() {
30189         if (mAnimator == null) {
30190             mAnimator = new ViewPropertyAnimator(this);
30191         }
30192         return mAnimator;
30193     }
30194 
30195     /**
30196      * Sets the name of the View to be used to identify Views in Transitions.
30197      * Names should be unique in the View hierarchy.
30198      *
30199      * @param transitionName The name of the View to uniquely identify it for Transitions.
30200      */
setTransitionName(String transitionName)30201     public final void setTransitionName(String transitionName) {
30202         mTransitionName = transitionName;
30203     }
30204 
30205     /**
30206      * Returns the name of the View to be used to identify Views in Transitions.
30207      * Names should be unique in the View hierarchy.
30208      *
30209      * <p>This returns null if the View has not been given a name.</p>
30210      *
30211      * @return The name used of the View to be used to identify Views in Transitions or null
30212      * if no name has been given.
30213      */
30214     @ViewDebug.ExportedProperty
30215     @InspectableProperty
getTransitionName()30216     public String getTransitionName() {
30217         return mTransitionName;
30218     }
30219 
30220     /**
30221      * @hide
30222      */
requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId)30223     public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
30224         // Do nothing.
30225     }
30226 
30227     /**
30228      * Interface definition for a callback to be invoked when a hardware key event is
30229      * dispatched to this view. The callback will be invoked before the key event is
30230      * given to the view. This is only useful for hardware keyboards; a software input
30231      * method has no obligation to trigger this listener.
30232      */
30233     public interface OnKeyListener {
30234         /**
30235          * Called when a hardware key is dispatched to a view. This allows listeners to
30236          * get a chance to respond before the target view.
30237          * <p>Key presses in software keyboards will generally NOT trigger this method,
30238          * although some may elect to do so in some situations. Do not assume a
30239          * software input method has to be key-based; even if it is, it may use key presses
30240          * in a different way than you expect, so there is no way to reliably catch soft
30241          * input key presses.
30242          *
30243          * @param v The view the key has been dispatched to.
30244          * @param keyCode The code for the physical key that was pressed
30245          * @param event The KeyEvent object containing full information about
30246          *        the event.
30247          * @return True if the listener has consumed the event, false otherwise.
30248          */
onKey(View v, int keyCode, KeyEvent event)30249         boolean onKey(View v, int keyCode, KeyEvent event);
30250     }
30251 
30252     /**
30253      * Interface definition for a callback to be invoked when a hardware key event hasn't
30254      * been handled by the view hierarchy.
30255      */
30256     public interface OnUnhandledKeyEventListener {
30257         /**
30258          * Called when a hardware key is dispatched to a view after being unhandled during normal
30259          * {@link KeyEvent} dispatch.
30260          *
30261          * @param v The view the key has been dispatched to.
30262          * @param event The KeyEvent object containing information about the event.
30263          * @return {@code true} if the listener has consumed the event, {@code false} otherwise.
30264          */
onUnhandledKeyEvent(View v, KeyEvent event)30265         boolean onUnhandledKeyEvent(View v, KeyEvent event);
30266     }
30267 
30268     /**
30269      * Interface definition for a callback to be invoked when a touch event is
30270      * dispatched to this view. The callback will be invoked before the touch
30271      * event is given to the view.
30272      */
30273     public interface OnTouchListener {
30274         /**
30275          * Called when a touch event is dispatched to a view. This allows listeners to
30276          * get a chance to respond before the target view.
30277          *
30278          * @param v The view the touch event has been dispatched to.
30279          * @param event The MotionEvent object containing full information about
30280          *        the event.
30281          * @return True if the listener has consumed the event, false otherwise.
30282          */
onTouch(View v, MotionEvent event)30283         boolean onTouch(View v, MotionEvent event);
30284     }
30285 
30286     /**
30287      * Interface definition for a callback to be invoked when a hover event is
30288      * dispatched to this view. The callback will be invoked before the hover
30289      * event is given to the view.
30290      */
30291     public interface OnHoverListener {
30292         /**
30293          * Called when a hover event is dispatched to a view. This allows listeners to
30294          * get a chance to respond before the target view.
30295          *
30296          * @param v The view the hover event has been dispatched to.
30297          * @param event The MotionEvent object containing full information about
30298          *        the event.
30299          * @return True if the listener has consumed the event, false otherwise.
30300          */
onHover(View v, MotionEvent event)30301         boolean onHover(View v, MotionEvent event);
30302     }
30303 
30304     /**
30305      * Interface definition for a callback to be invoked when a generic motion event is
30306      * dispatched to this view. The callback will be invoked before the generic motion
30307      * event is given to the view.
30308      */
30309     public interface OnGenericMotionListener {
30310         /**
30311          * Called when a generic motion event is dispatched to a view. This allows listeners to
30312          * get a chance to respond before the target view.
30313          *
30314          * @param v The view the generic motion event has been dispatched to.
30315          * @param event The MotionEvent object containing full information about
30316          *        the event.
30317          * @return True if the listener has consumed the event, false otherwise.
30318          */
onGenericMotion(View v, MotionEvent event)30319         boolean onGenericMotion(View v, MotionEvent event);
30320     }
30321 
30322     /**
30323      * Interface definition for a callback to be invoked when a view has been clicked and held.
30324      */
30325     public interface OnLongClickListener {
30326         /**
30327          * Called when a view has been clicked and held.
30328          *
30329          * @param v The view that was clicked and held.
30330          *
30331          * @return true if the callback consumed the long click, false otherwise.
30332          */
onLongClick(View v)30333         boolean onLongClick(View v);
30334 
30335         /**
30336          * Returns whether the default {@link HapticFeedbackConstants#LONG_PRESS} haptic feedback
30337          * is performed when this listener has consumed the long click. This method is called
30338          * immediately after {@link #onLongClick} has returned true.
30339          *
30340          * @param v The view that was clicked and held.
30341          * @return true to perform the default {@link HapticFeedbackConstants#LONG_PRESS} haptic
30342          * feedback, or false if the handler manages all haptics itself.
30343          */
onLongClickUseDefaultHapticFeedback(@onNull View v)30344         default boolean onLongClickUseDefaultHapticFeedback(@NonNull View v) {
30345             return true;
30346         }
30347     }
30348 
30349     /**
30350      * Interface definition for a listener that's invoked when a drag event is dispatched to this
30351      * view. The listener is invoked before the view's own
30352      * {@link #onDragEvent(DragEvent)} method. To fall back to the view's
30353      * {@code onDragEvent(DragEvent)} behavior, return {@code false} from the listener method.
30354      *
30355      * <div class="special reference">
30356      *   <h3>Developer Guides</h3>
30357      *   <p>For a guide to implementing drag and drop features, see the
30358      *   <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and drop</a> developer guide.</p>
30359      * </div>
30360      */
30361     public interface OnDragListener {
30362         /**
30363          * Called when a drag event is dispatched to a view. Enables listeners to override the
30364          * base behavior provided by {@link #onDragEvent(DragEvent)}.
30365          *
30366          * @param v The {@code View} that received the drag event.
30367          * @param event The event object for the drag event.
30368          * @return {@code true} if the drag event was handled successfully; {@code false}, if the
30369          *   drag event was not handled. <b>Note:</b> A {@code false} return value triggers the
30370          *   view's {@link #onDragEvent(DragEvent)} handler.
30371          */
onDrag(View v, DragEvent event)30372         boolean onDrag(View v, DragEvent event);
30373     }
30374 
30375     /**
30376      * Interface definition for a callback to be invoked when the focus state of
30377      * a view changed.
30378      */
30379     public interface OnFocusChangeListener {
30380         /**
30381          * Called when the focus state of a view has changed.
30382          *
30383          * @param v The view whose state has changed.
30384          * @param hasFocus The new focus state of v.
30385          */
onFocusChange(View v, boolean hasFocus)30386         void onFocusChange(View v, boolean hasFocus);
30387     }
30388 
30389     /**
30390      * Interface definition for a callback to be invoked when a view is clicked.
30391      */
30392     public interface OnClickListener {
30393         /**
30394          * Called when a view has been clicked.
30395          *
30396          * @param v The view that was clicked.
30397          */
onClick(View v)30398         void onClick(View v);
30399     }
30400 
30401     /**
30402      * Interface definition for a callback to be invoked when a view is context clicked.
30403      */
30404     public interface OnContextClickListener {
30405         /**
30406          * Called when a view is context clicked.
30407          *
30408          * @param v The view that has been context clicked.
30409          * @return true if the callback consumed the context click, false otherwise.
30410          */
onContextClick(View v)30411         boolean onContextClick(View v);
30412     }
30413 
30414     /**
30415      * Interface definition for a callback to be invoked when the context menu
30416      * for this view is being built.
30417      */
30418     public interface OnCreateContextMenuListener {
30419         /**
30420          * Called when the context menu for this view is being built. It is not
30421          * safe to hold onto the menu after this method returns.
30422          *
30423          * @param menu The context menu that is being built
30424          * @param v The view for which the context menu is being built
30425          * @param menuInfo Extra information about the item for which the
30426          *            context menu should be shown. This information will vary
30427          *            depending on the class of v.
30428          */
onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)30429         void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
30430     }
30431 
30432     /**
30433      * Interface definition for a callback to be invoked when the status bar changes
30434      * visibility.  This reports <strong>global</strong> changes to the system UI
30435      * state, not what the application is requesting.
30436      *
30437      * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
30438      *
30439      * @deprecated Use {@link WindowInsets#isVisible(int)} to find out about system bar visibilities
30440      * by setting a {@link OnApplyWindowInsetsListener} on this view.
30441      */
30442     @Deprecated
30443     public interface OnSystemUiVisibilityChangeListener {
30444         /**
30445          * Called when the status bar changes visibility because of a call to
30446          * {@link View#setSystemUiVisibility(int)}.
30447          *
30448          * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
30449          * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
30450          * This tells you the <strong>global</strong> state of these UI visibility
30451          * flags, not what your app is currently applying.
30452          */
onSystemUiVisibilityChange(int visibility)30453         public void onSystemUiVisibilityChange(int visibility);
30454     }
30455 
30456     /**
30457      * Interface definition for a callback to be invoked when this view is attached
30458      * or detached from its window.
30459      */
30460     public interface OnAttachStateChangeListener {
30461         /**
30462          * Called when the view is attached to a window.
30463          * @param v The view that was attached
30464          */
onViewAttachedToWindow(@onNull View v)30465         public void onViewAttachedToWindow(@NonNull View v);
30466         /**
30467          * Called when the view is detached from a window.
30468          * @param v The view that was detached
30469          */
onViewDetachedFromWindow(@onNull View v)30470         public void onViewDetachedFromWindow(@NonNull View v);
30471     }
30472 
30473     /**
30474      * Listener for applying window insets on a view in a custom way.
30475      *
30476      * <p>Apps may choose to implement this interface if they want to apply custom policy
30477      * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
30478      * is set, its
30479      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
30480      * method will be called instead of the View's own
30481      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
30482      * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
30483      * the View's normal behavior as part of its own.</p>
30484      */
30485     public interface OnApplyWindowInsetsListener {
30486         /**
30487          * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
30488          * on a View, this listener method will be called instead of the view's own
30489          * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
30490          *
30491          * @param v The view applying window insets
30492          * @param insets The insets to apply
30493          * @return The insets supplied, minus any insets that were consumed
30494          */
onApplyWindowInsets(@onNull View v, @NonNull WindowInsets insets)30495         public @NonNull WindowInsets onApplyWindowInsets(@NonNull View v,
30496                 @NonNull WindowInsets insets);
30497     }
30498 
30499     private final class UnsetPressedState implements Runnable {
30500         @Override
run()30501         public void run() {
30502             setPressed(false);
30503         }
30504     }
30505 
30506     /**
30507      * When a view becomes invisible checks if autofill considers the view invisible too. This
30508      * happens after the regular removal operation to make sure the operation is finished by the
30509      * time this is called.
30510      */
30511     private static class VisibilityChangeForAutofillHandler extends Handler {
30512         private final AutofillManager mAfm;
30513         private final View mView;
30514 
VisibilityChangeForAutofillHandler(@onNull AutofillManager afm, @NonNull View view)30515         private VisibilityChangeForAutofillHandler(@NonNull AutofillManager afm,
30516                 @NonNull View view) {
30517             mAfm = afm;
30518             mView = view;
30519         }
30520 
30521         @Override
handleMessage(Message msg)30522         public void handleMessage(Message msg) {
30523             mAfm.notifyViewVisibilityChanged(mView, mView.isShown());
30524         }
30525     }
30526 
30527     /**
30528      * Base class for derived classes that want to save and restore their own
30529      * state in {@link android.view.View#onSaveInstanceState()}.
30530      */
30531     public static class BaseSavedState extends AbsSavedState {
30532         static final int START_ACTIVITY_REQUESTED_WHO_SAVED = 0b1;
30533         static final int IS_AUTOFILLED = 0b10;
30534         static final int AUTOFILL_ID = 0b100;
30535 
30536         // Flags that describe what data in this state is valid
30537         int mSavedData;
30538         String mStartActivityRequestWhoSaved;
30539         boolean mIsAutofilled;
30540         boolean mHideHighlight;
30541         int mAutofillViewId;
30542 
30543         /**
30544          * Constructor used when reading from a parcel. Reads the state of the superclass.
30545          *
30546          * @param source parcel to read from
30547          */
BaseSavedState(Parcel source)30548         public BaseSavedState(Parcel source) {
30549             this(source, null);
30550         }
30551 
30552         /**
30553          * Constructor used when reading from a parcel using a given class loader.
30554          * Reads the state of the superclass.
30555          *
30556          * @param source parcel to read from
30557          * @param loader ClassLoader to use for reading
30558          */
BaseSavedState(Parcel source, ClassLoader loader)30559         public BaseSavedState(Parcel source, ClassLoader loader) {
30560             super(source, loader);
30561             mSavedData = source.readInt();
30562             mStartActivityRequestWhoSaved = source.readString();
30563             mIsAutofilled = source.readBoolean();
30564             mHideHighlight = source.readBoolean();
30565             mAutofillViewId = source.readInt();
30566         }
30567 
30568         /**
30569          * Constructor called by derived classes when creating their SavedState objects
30570          *
30571          * @param superState The state of the superclass of this view
30572          */
BaseSavedState(Parcelable superState)30573         public BaseSavedState(Parcelable superState) {
30574             super(superState);
30575         }
30576 
30577         @Override
writeToParcel(Parcel out, int flags)30578         public void writeToParcel(Parcel out, int flags) {
30579             super.writeToParcel(out, flags);
30580 
30581             out.writeInt(mSavedData);
30582             out.writeString(mStartActivityRequestWhoSaved);
30583             out.writeBoolean(mIsAutofilled);
30584             out.writeBoolean(mHideHighlight);
30585             out.writeInt(mAutofillViewId);
30586         }
30587 
30588         public static final @android.annotation.NonNull Parcelable.Creator<BaseSavedState> CREATOR
30589                 = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
30590             @Override
30591             public BaseSavedState createFromParcel(Parcel in) {
30592                 return new BaseSavedState(in);
30593             }
30594 
30595             @Override
30596             public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
30597                 return new BaseSavedState(in, loader);
30598             }
30599 
30600             @Override
30601             public BaseSavedState[] newArray(int size) {
30602                 return new BaseSavedState[size];
30603             }
30604         };
30605     }
30606 
30607     /**
30608      * A set of information given to a view when it is attached to its parent
30609      * window.
30610      */
30611     final static class AttachInfo {
30612 
30613         interface Callbacks {
playSoundEffect(int effectId)30614             void playSoundEffect(int effectId);
performHapticFeedback(int effectId, boolean always)30615             boolean performHapticFeedback(int effectId, boolean always);
30616         }
30617 
30618         /**
30619          * InvalidateInfo is used to post invalidate(int, int, int, int) messages
30620          * to a Handler. This class contains the target (View) to invalidate and
30621          * the coordinates of the dirty rectangle.
30622          *
30623          * For performance purposes, this class also implements a pool of up to
30624          * POOL_LIMIT objects that get reused. This reduces memory allocations
30625          * whenever possible.
30626          */
30627         static class InvalidateInfo {
30628 
30629             @UnsupportedAppUsage
InvalidateInfo()30630             InvalidateInfo() {
30631             }
30632 
30633             private static final int POOL_LIMIT = 10;
30634 
30635             private static final SynchronizedPool<InvalidateInfo> sPool =
30636                     new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
30637 
30638             @UnsupportedAppUsage
30639             View target;
30640 
30641             @UnsupportedAppUsage
30642             int left;
30643             @UnsupportedAppUsage
30644             int top;
30645             @UnsupportedAppUsage
30646             int right;
30647             @UnsupportedAppUsage
30648             int bottom;
30649 
obtain()30650             public static InvalidateInfo obtain() {
30651                 InvalidateInfo instance = sPool.acquire();
30652                 return (instance != null) ? instance : new InvalidateInfo();
30653             }
30654 
recycle()30655             public void recycle() {
30656                 target = null;
30657                 sPool.release(this);
30658             }
30659         }
30660 
30661         @UnsupportedAppUsage
30662         final IWindowSession mSession;
30663 
30664         @UnsupportedAppUsage
30665         final IWindow mWindow;
30666 
30667         final IBinder mWindowToken;
30668 
30669         Display mDisplay;
30670 
30671         final Callbacks mRootCallbacks;
30672 
30673         IWindowId mIWindowId;
30674         WindowId mWindowId;
30675 
30676         /**
30677          * The top view of the hierarchy.
30678          */
30679         View mRootView;
30680 
30681         IBinder mPanelParentWindowToken;
30682 
30683         boolean mHardwareAccelerated;
30684         boolean mHardwareAccelerationRequested;
30685         ThreadedRenderer mThreadedRenderer;
30686         List<RenderNode> mPendingAnimatingRenderNodes;
30687 
30688         /**
30689          * The state of the display to which the window is attached, as reported
30690          * by {@link Display#getState()}.  Note that the display state constants
30691          * declared by {@link Display} do not exactly line up with the screen state
30692          * constants declared by {@link View} (there are more display states than
30693          * screen states).
30694          */
30695         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
30696         int mDisplayState = Display.STATE_UNKNOWN;
30697 
30698         /**
30699          * Scale factor used by the compatibility mode
30700          */
30701         @UnsupportedAppUsage
30702         float mApplicationScale;
30703 
30704         /**
30705          * Indicates whether the application is in compatibility mode
30706          */
30707         @UnsupportedAppUsage
30708         boolean mScalingRequired;
30709 
30710         /**
30711          * Left position of this view's window
30712          */
30713         int mWindowLeft;
30714 
30715         /**
30716          * Top position of this view's window
30717          */
30718         int mWindowTop;
30719 
30720         /**
30721          * Indicates whether views need to use 32-bit drawing caches
30722          */
30723         boolean mUse32BitDrawingCache;
30724 
30725         /**
30726          * For windows that are full-screen but using insets to layout inside
30727          * of the screen decorations, these are the current insets for the
30728          * content of the window.
30729          */
30730         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
30731                 publicAlternatives = "Use {@link WindowInsets#getInsets(int)}")
30732         final Rect mContentInsets = new Rect();
30733 
30734         /**
30735          * For windows that are full-screen but using insets to layout inside
30736          * of the screen decorations, these are the current insets for the
30737          * actual visible parts of the window.
30738          */
30739         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
30740                 publicAlternatives = "Use {@link WindowInsets#getInsets(int)}")
30741         final Rect mVisibleInsets = new Rect();
30742 
30743         /**
30744          * For windows that are full-screen but using insets to layout inside
30745          * of the screen decorations, these are the current insets for the
30746          * stable system windows.
30747          */
30748         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
30749                 publicAlternatives = "Use {@link WindowInsets#getInsets(int)}")
30750         final Rect mStableInsets = new Rect();
30751 
30752         /**
30753          * Current caption insets to the display coordinate.
30754          */
30755         final Rect mCaptionInsets = new Rect();
30756 
30757         /**
30758          * In multi-window we force show the system bars. Because we don't want that the surface
30759          * size changes in this mode, we instead have a flag whether the system bars sizes should
30760          * always be consumed, so the app is treated like there are no virtual system bars at all.
30761          */
30762         boolean mAlwaysConsumeSystemBars;
30763 
30764         /**
30765          * The internal insets given by this window.  This value is
30766          * supplied by the client (through
30767          * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
30768          * be given to the window manager when changed to be used in laying
30769          * out windows behind it.
30770          */
30771         @UnsupportedAppUsage
30772         final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
30773                 = new ViewTreeObserver.InternalInsetsInfo();
30774 
30775         /**
30776          * Set to true when mGivenInternalInsets is non-empty.
30777          */
30778         boolean mHasNonEmptyGivenInternalInsets;
30779 
30780         /**
30781          * All views in the window's hierarchy that serve as scroll containers,
30782          * used to determine if the window can be resized or must be panned
30783          * to adjust for a soft input area.
30784          */
30785         @UnsupportedAppUsage
30786         final ArrayList<View> mScrollContainers = new ArrayList<View>();
30787 
30788         @UnsupportedAppUsage
30789         final KeyEvent.DispatcherState mKeyDispatchState
30790                 = new KeyEvent.DispatcherState();
30791 
30792         /**
30793          * Indicates whether the view's window currently has the focus.
30794          */
30795         @UnsupportedAppUsage
30796         boolean mHasWindowFocus;
30797 
30798         /**
30799          * The current visibility of the window.
30800          */
30801         int mWindowVisibility;
30802 
30803         /**
30804          * Indicates the time at which drawing started to occur.
30805          */
30806         @UnsupportedAppUsage
30807         long mDrawingTime;
30808 
30809         /**
30810          * Indicates whether the view's window is currently in touch mode.
30811          */
30812         @UnsupportedAppUsage
30813         boolean mInTouchMode;
30814 
30815         /**
30816          * Indicates whether the view has requested unbuffered input dispatching for the current
30817          * event stream.
30818          */
30819         boolean mUnbufferedDispatchRequested;
30820 
30821         /**
30822          * Indicates that ViewAncestor should trigger a global layout change
30823          * the next time it performs a traversal
30824          */
30825         @UnsupportedAppUsage
30826         boolean mRecomputeGlobalAttributes;
30827 
30828         /**
30829          * Always report new attributes at next traversal.
30830          */
30831         boolean mForceReportNewAttributes;
30832 
30833         /**
30834          * Set during a traveral if any views want to keep the screen on.
30835          */
30836         @UnsupportedAppUsage
30837         boolean mKeepScreenOn;
30838 
30839         /**
30840          * Set during a traveral if the light center needs to be updated.
30841          */
30842         boolean mNeedsUpdateLightCenter;
30843 
30844         /**
30845          * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
30846          */
30847         int mSystemUiVisibility;
30848 
30849         /**
30850          * Hack to force certain system UI visibility flags to be cleared.
30851          */
30852         int mDisabledSystemUiVisibility;
30853 
30854         /**
30855          * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
30856          * attached.
30857          */
30858         boolean mHasSystemUiListeners;
30859 
30860         /**
30861          * Set if the visibility of any views has changed.
30862          */
30863         @UnsupportedAppUsage
30864         boolean mViewVisibilityChanged;
30865 
30866         /**
30867          * Set to true if a view has been scrolled.
30868          */
30869         @UnsupportedAppUsage
30870         boolean mViewScrollChanged;
30871 
30872         /**
30873          * Set to true if a pointer event is currently being handled.
30874          */
30875         boolean mHandlingPointerEvent;
30876 
30877         /**
30878          * The window matrix of this view when it's on a {@link SurfaceControlViewHost} that is
30879          * embedded within a SurfaceView.
30880          */
30881         Matrix mWindowMatrixInEmbeddedHierarchy;
30882 
30883         /**
30884          * Global to the view hierarchy used as a temporary for dealing with
30885          * x/y points in the transparent region computations.
30886          */
30887         final int[] mTransparentLocation = new int[2];
30888 
30889         /**
30890          * Global to the view hierarchy used as a temporary for dealing with
30891          * x/y points in the ViewGroup.invalidateChild implementation.
30892          */
30893         final int[] mInvalidateChildLocation = new int[2];
30894 
30895         /**
30896          * Global to the view hierarchy used as a temporary for dealing with
30897          * computing absolute on-screen location.
30898          */
30899         final int[] mTmpLocation = new int[2];
30900 
30901         /**
30902          * Global to the view hierarchy used as a temporary for dealing with
30903          * x/y location when view is transformed.
30904          */
30905         final float[] mTmpTransformLocation = new float[2];
30906 
30907         /**
30908          * The view tree observer used to dispatch global events like
30909          * layout, pre-draw, touch mode change, etc.
30910          */
30911         @UnsupportedAppUsage
30912         final ViewTreeObserver mTreeObserver;
30913 
30914         /**
30915          * A Canvas used by the view hierarchy to perform bitmap caching.
30916          */
30917         Canvas mCanvas;
30918 
30919         /**
30920          * The view root impl.
30921          */
30922         final ViewRootImpl mViewRootImpl;
30923 
30924         /**
30925          * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
30926          * handler can be used to pump events in the UI events queue.
30927          */
30928         @UnsupportedAppUsage
30929         final Handler mHandler;
30930 
30931         /**
30932          * Temporary for use in computing invalidate rectangles while
30933          * calling up the hierarchy.
30934          */
30935         final Rect mTmpInvalRect = new Rect();
30936 
30937         /**
30938          * Temporary for use in computing hit areas with transformed views
30939          */
30940         final RectF mTmpTransformRect = new RectF();
30941 
30942         /**
30943          * Temporary for use in computing hit areas with transformed views
30944          */
30945         final RectF mTmpTransformRect1 = new RectF();
30946 
30947         /**
30948          * Temporary list of rectanges.
30949          */
30950         final List<RectF> mTmpRectList = new ArrayList<>();
30951 
30952         /**
30953          * Temporary for use in transforming invalidation rect
30954          */
30955         final Matrix mTmpMatrix = new Matrix();
30956 
30957         /**
30958          * Temporary for use in transforming invalidation rect
30959          */
30960         final Transformation mTmpTransformation = new Transformation();
30961 
30962         /**
30963          * Temporary for use in querying outlines from OutlineProviders
30964          */
30965         final Outline mTmpOutline = new Outline();
30966 
30967         /**
30968          * Temporary list for use in collecting focusable descendents of a view.
30969          */
30970         final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
30971 
30972         /**
30973          * The id of the window for accessibility purposes.
30974          */
30975         int mAccessibilityWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
30976 
30977         /**
30978          * Flags related to accessibility processing.
30979          *
30980          * @see AccessibilityNodeInfo#FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS
30981          * @see AccessibilityNodeInfo#FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS
30982          */
30983         int mAccessibilityFetchFlags;
30984 
30985         /**
30986          * The drawable for highlighting accessibility focus.
30987          */
30988         Drawable mAccessibilityFocusDrawable;
30989 
30990         /**
30991          * The drawable for highlighting autofilled views.
30992          *
30993          * @see #isAutofilled()
30994          */
30995         Drawable mAutofilledDrawable;
30996 
30997         /**
30998          * Show where the margins, bounds and layout bounds are for each view.
30999          */
31000         boolean mDebugLayout = DisplayProperties.debug_layout().orElse(false);
31001 
31002         /**
31003          * Point used to compute visible regions.
31004          */
31005         final Point mPoint = new Point();
31006 
31007         /**
31008          * Used to track which View originated a requestLayout() call, used when
31009          * requestLayout() is called during layout.
31010          */
31011         View mViewRequestingLayout;
31012 
31013         /**
31014          * Used to track the identity of the current drag operation.
31015          */
31016         IBinder mDragToken;
31017 
31018         /**
31019          * The drag shadow surface for the current drag operation.
31020          */
31021         public Surface mDragSurface;
31022 
31023 
31024         /**
31025          * The view that currently has a tooltip displayed.
31026          */
31027         View mTooltipHost;
31028 
31029         /**
31030          * The initial structure has been reported so the view is ready to report updates.
31031          */
31032         boolean mReadyForContentCaptureUpdates;
31033 
31034         /**
31035          * Map(keyed by session) of content capture events that need to be notified after the view
31036          * hierarchy is traversed: value is either the view itself for appearead events, or its
31037          * autofill id for disappeared.
31038          */
31039         SparseArray<ArrayList<Object>> mContentCaptureEvents;
31040 
31041         /**
31042          * Cached reference to the {@link ContentCaptureManager}.
31043          */
31044         ContentCaptureManager mContentCaptureManager;
31045 
31046         /**
31047          * Listener used to fit content on window level.
31048          */
31049         OnContentApplyWindowInsetsListener mContentOnApplyWindowInsetsListener;
31050 
31051         /**
31052          * The leash token of this view's parent when it's in an embedded hierarchy that is
31053          * re-parented to another window.
31054          */
31055         IBinder mLeashedParentToken;
31056 
31057         /**
31058          * The accessibility view id of this view's parent when it's in an embedded
31059          * hierarchy that is re-parented to another window.
31060          */
31061         int mLeashedParentAccessibilityViewId;
31062 
31063         /**
31064          *
31065          */
31066         ScrollCaptureInternal mScrollCaptureInternal;
31067 
31068         /**
31069          * Creates a new set of attachment information with the specified
31070          * events handler and thread.
31071          *
31072          * @param handler the events handler the view must use
31073          */
AttachInfo(IWindowSession session, IWindow window, Display display, ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer, Context context)31074         AttachInfo(IWindowSession session, IWindow window, Display display,
31075                 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer,
31076                 Context context) {
31077             mSession = session;
31078             mWindow = window;
31079             mWindowToken = window.asBinder();
31080             mDisplay = display;
31081             mViewRootImpl = viewRootImpl;
31082             mHandler = handler;
31083             mRootCallbacks = effectPlayer;
31084             mTreeObserver = new ViewTreeObserver(context);
31085         }
31086 
31087         @Nullable
getContentCaptureManager(@onNull Context context)31088         ContentCaptureManager getContentCaptureManager(@NonNull Context context) {
31089             if (mContentCaptureManager != null) {
31090                 return mContentCaptureManager;
31091             }
31092             mContentCaptureManager = context.getSystemService(ContentCaptureManager.class);
31093             return mContentCaptureManager;
31094         }
31095 
delayNotifyContentCaptureInsetsEvent(@onNull Insets insets)31096         void delayNotifyContentCaptureInsetsEvent(@NonNull Insets insets) {
31097             if (mContentCaptureManager == null) {
31098                 return;
31099             }
31100 
31101             ArrayList<Object> events = ensureEvents(
31102                         mContentCaptureManager.getMainContentCaptureSession());
31103             events.add(insets);
31104         }
31105 
delayNotifyContentCaptureEvent(@onNull ContentCaptureSession session, @NonNull View view, boolean appeared)31106         private void delayNotifyContentCaptureEvent(@NonNull ContentCaptureSession session,
31107                 @NonNull View view, boolean appeared) {
31108             ArrayList<Object> events = ensureEvents(session);
31109             events.add(appeared ? view : view.getAutofillId());
31110         }
31111 
31112         @NonNull
ensureEvents(@onNull ContentCaptureSession session)31113         private ArrayList<Object> ensureEvents(@NonNull ContentCaptureSession session) {
31114             if (mContentCaptureEvents == null) {
31115                 // Most of the time there will be just one session, so intial capacity is 1
31116                 mContentCaptureEvents = new SparseArray<>(1);
31117             }
31118             int sessionId = session.getId();
31119             // TODO: life would be much easier if we provided a MultiMap implementation somwhere...
31120             ArrayList<Object> events = mContentCaptureEvents.get(sessionId);
31121             if (events == null) {
31122                 events = new ArrayList<>();
31123                 mContentCaptureEvents.put(sessionId, events);
31124             }
31125 
31126             return events;
31127         }
31128 
31129         @Nullable
getScrollCaptureInternal()31130         ScrollCaptureInternal getScrollCaptureInternal() {
31131             if (mScrollCaptureInternal != null) {
31132                 mScrollCaptureInternal = new ScrollCaptureInternal();
31133             }
31134             return mScrollCaptureInternal;
31135         }
31136 
getRootSurfaceControl()31137         AttachedSurfaceControl getRootSurfaceControl() {
31138             return mViewRootImpl;
31139         }
31140 
dump(String prefix, PrintWriter writer)31141         public void dump(String prefix, PrintWriter writer) {
31142             String innerPrefix = prefix + "  ";
31143             writer.println(prefix + "AttachInfo:");
31144             writer.println(innerPrefix + "mHasWindowFocus=" + mHasWindowFocus);
31145             writer.println(innerPrefix + "mWindowVisibility=" + mWindowVisibility);
31146             writer.println(innerPrefix + "mInTouchMode=" + mInTouchMode);
31147             writer.println(innerPrefix + "mUnbufferedDispatchRequested="
31148                     + mUnbufferedDispatchRequested);
31149         }
31150     }
31151 
31152     /**
31153      * <p>ScrollabilityCache holds various fields used by a View when scrolling
31154      * is supported. This avoids keeping too many unused fields in most
31155      * instances of View.</p>
31156      */
31157     private static class ScrollabilityCache implements Runnable {
31158 
31159         /**
31160          * Scrollbars are not visible
31161          */
31162         public static final int OFF = 0;
31163 
31164         /**
31165          * Scrollbars are visible
31166          */
31167         public static final int ON = 1;
31168 
31169         /**
31170          * Scrollbars are fading away
31171          */
31172         public static final int FADING = 2;
31173 
31174         public boolean fadeScrollBars;
31175 
31176         public int fadingEdgeLength;
31177         public int scrollBarDefaultDelayBeforeFade;
31178         public int scrollBarFadeDuration;
31179 
31180         public int scrollBarSize;
31181         public int scrollBarMinTouchTarget;
31182         @UnsupportedAppUsage
31183         public ScrollBarDrawable scrollBar;
31184         public float[] interpolatorValues;
31185         @UnsupportedAppUsage
31186         public View host;
31187 
31188         public final Paint paint;
31189         public final Matrix matrix;
31190         public Shader shader;
31191 
31192         public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
31193 
31194         private static final float[] OPAQUE = { 255 };
31195         private static final float[] TRANSPARENT = { 0.0f };
31196 
31197         /**
31198          * When fading should start. This time moves into the future every time
31199          * a new scroll happens. Measured based on SystemClock.uptimeMillis()
31200          */
31201         public long fadeStartTime;
31202 
31203 
31204         /**
31205          * The current state of the scrollbars: ON, OFF, or FADING
31206          */
31207         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
31208         public int state = OFF;
31209 
31210         private int mLastColor;
31211 
31212         public final Rect mScrollBarBounds = new Rect();
31213         public final Rect mScrollBarTouchBounds = new Rect();
31214 
31215         public static final int NOT_DRAGGING = 0;
31216         public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
31217         public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
31218         public int mScrollBarDraggingState = NOT_DRAGGING;
31219 
31220         public float mScrollBarDraggingPos = 0;
31221 
ScrollabilityCache(ViewConfiguration configuration, View host)31222         public ScrollabilityCache(ViewConfiguration configuration, View host) {
31223             fadingEdgeLength = configuration.getScaledFadingEdgeLength();
31224             scrollBarSize = configuration.getScaledScrollBarSize();
31225             scrollBarMinTouchTarget = configuration.getScaledMinScrollbarTouchTarget();
31226             scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
31227             scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
31228 
31229             paint = new Paint();
31230             matrix = new Matrix();
31231             // use use a height of 1, and then wack the matrix each time we
31232             // actually use it.
31233             shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
31234             paint.setShader(shader);
31235             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
31236 
31237             this.host = host;
31238         }
31239 
setFadeColor(int color)31240         public void setFadeColor(int color) {
31241             if (color != mLastColor) {
31242                 mLastColor = color;
31243 
31244                 if (color != 0) {
31245                     shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
31246                             color & 0x00FFFFFF, Shader.TileMode.CLAMP);
31247                     paint.setShader(shader);
31248                     // Restore the default transfer mode (src_over)
31249                     paint.setXfermode(null);
31250                 } else {
31251                     shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
31252                     paint.setShader(shader);
31253                     paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
31254                 }
31255             }
31256         }
31257 
run()31258         public void run() {
31259             long now = AnimationUtils.currentAnimationTimeMillis();
31260             if (now >= fadeStartTime) {
31261 
31262                 // the animation fades the scrollbars out by changing
31263                 // the opacity (alpha) from fully opaque to fully
31264                 // transparent
31265                 int nextFrame = (int) now;
31266                 int framesCount = 0;
31267 
31268                 Interpolator interpolator = scrollBarInterpolator;
31269 
31270                 // Start opaque
31271                 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
31272 
31273                 // End transparent
31274                 nextFrame += scrollBarFadeDuration;
31275                 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
31276 
31277                 state = FADING;
31278 
31279                 // Kick off the fade animation
31280                 host.invalidate(true);
31281             }
31282         }
31283     }
31284 
31285     private class SendAccessibilityEventThrottle implements Runnable {
31286         public volatile boolean mIsPending;
31287         private AccessibilityEvent mAccessibilityEvent;
31288 
post(AccessibilityEvent accessibilityEvent)31289         public void post(AccessibilityEvent accessibilityEvent) {
31290             updateWithAccessibilityEvent(accessibilityEvent);
31291             if (!mIsPending) {
31292                 mIsPending = true;
31293                 postDelayed(this,
31294                         ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
31295             }
31296         }
31297 
31298         @Override
run()31299         public void run() {
31300             if (AccessibilityManager.getInstance(mContext).isEnabled() && isShown()) {
31301                 requestParentSendAccessibilityEvent(mAccessibilityEvent);
31302             }
31303             reset();
31304         }
31305 
updateWithAccessibilityEvent(AccessibilityEvent accessibilityEvent)31306         public void updateWithAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
31307             mAccessibilityEvent = accessibilityEvent;
31308         }
31309 
reset()31310         public void reset() {
31311             mIsPending = false;
31312             mAccessibilityEvent = null;
31313         }
31314 
31315     }
31316 
31317     /**
31318      * Resuable callback for sending
31319      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
31320      */
31321     private class SendViewScrolledAccessibilityEvent extends SendAccessibilityEventThrottle {
31322         public int mDeltaX;
31323         public int mDeltaY;
31324 
31325         @Override
updateWithAccessibilityEvent(AccessibilityEvent accessibilityEvent)31326         public void updateWithAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
31327             super.updateWithAccessibilityEvent(accessibilityEvent);
31328             mDeltaX += accessibilityEvent.getScrollDeltaX();
31329             mDeltaY += accessibilityEvent.getScrollDeltaY();
31330             accessibilityEvent.setScrollDeltaX(mDeltaX);
31331             accessibilityEvent.setScrollDeltaY(mDeltaY);
31332         }
31333 
31334         @Override
reset()31335         public void reset() {
31336             super.reset();
31337             mDeltaX = 0;
31338             mDeltaY = 0;
31339         }
31340     }
31341     /**
31342      * Remove the pending callback for sending a throttled accessibility event.
31343      */
31344     @UnsupportedAppUsage
cancel(@ullable SendAccessibilityEventThrottle callback)31345     private void cancel(@Nullable SendAccessibilityEventThrottle callback) {
31346         if (callback == null || !callback.mIsPending) return;
31347         removeCallbacks(callback);
31348         callback.reset();
31349     }
31350 
31351     /**
31352      * <p>
31353      * This class represents a delegate that can be registered in a {@link View}
31354      * to enhance accessibility support via composition rather via inheritance.
31355      * It is specifically targeted to widget developers that extend basic View
31356      * classes i.e. classes in package android.view, that would like their
31357      * applications to be backwards compatible.
31358      * </p>
31359      * <div class="special reference">
31360      * <h3>Developer Guides</h3>
31361      * <p>For more information about making applications accessible, read the
31362      * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
31363      * developer guide.</p>
31364      * </div>
31365      * <p>
31366      * A scenario in which a developer would like to use an accessibility delegate
31367      * is overriding a method introduced in a later API version than the minimal API
31368      * version supported by the application. For example, the method
31369      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
31370      * in API version 4 when the accessibility APIs were first introduced. If a
31371      * developer would like their application to run on API version 4 devices (assuming
31372      * all other APIs used by the application are version 4 or lower) and take advantage
31373      * of this method, instead of overriding the method which would break the application's
31374      * backwards compatibility, they can override the corresponding method in this
31375      * delegate and register the delegate in the target View if the API version of
31376      * the system is high enough, i.e. the API version is the same as or higher than the API
31377      * version that introduced
31378      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
31379      * </p>
31380      * <p>
31381      * Here is an example implementation:
31382      * </p>
31383      * <code><pre><p>
31384      * if (Build.VERSION.SDK_INT >= 14) {
31385      *     // If the API version is equal of higher than the version in
31386      *     // which onInitializeAccessibilityNodeInfo was introduced we
31387      *     // register a delegate with a customized implementation.
31388      *     View view = findViewById(R.id.view_id);
31389      *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
31390      *         public void onInitializeAccessibilityNodeInfo(View host,
31391      *                 AccessibilityNodeInfo info) {
31392      *             // Let the default implementation populate the info.
31393      *             super.onInitializeAccessibilityNodeInfo(host, info);
31394      *             // Set some other information.
31395      *             info.setEnabled(host.isEnabled());
31396      *         }
31397      *     });
31398      * }
31399      * </code></pre></p>
31400      * <p>
31401      * This delegate contains methods that correspond to the accessibility methods
31402      * in View. If a delegate has been specified the implementation in View hands
31403      * off handling to the corresponding method in this delegate. The default
31404      * implementation the delegate methods behaves exactly as the corresponding
31405      * method in View for the case of no accessibility delegate been set. Hence,
31406      * to customize the behavior of a View method, clients can override only the
31407      * corresponding delegate method without altering the behavior of the rest
31408      * accessibility related methods of the host view.
31409      * </p>
31410      * <p>
31411      * <strong>Note:</strong> On platform versions prior to
31412      * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
31413      * views in the {@code android.widget.*} package are called <i>before</i>
31414      * host methods. This prevents certain properties such as class name from
31415      * being modified by overriding
31416      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
31417      * as any changes will be overwritten by the host class.
31418      * <p>
31419      * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
31420      * methods are called <i>after</i> host methods, which all properties to be
31421      * modified without being overwritten by the host class.
31422      */
31423     public static class AccessibilityDelegate {
31424 
31425         /**
31426          * Sends an accessibility event of the given type. If accessibility is not
31427          * enabled this method has no effect.
31428          * <p>
31429          * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
31430          *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
31431          * been set.
31432          * </p>
31433          *
31434          * @param host The View hosting the delegate.
31435          * @param eventType The type of the event to send.
31436          *
31437          * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
31438          */
sendAccessibilityEvent(@onNull View host, int eventType)31439         public void sendAccessibilityEvent(@NonNull View host, int eventType) {
31440             host.sendAccessibilityEventInternal(eventType);
31441         }
31442 
31443         /**
31444          * Performs the specified accessibility action on the view. For
31445          * possible accessibility actions look at {@link AccessibilityNodeInfo}.
31446          * <p>
31447          * The default implementation behaves as
31448          * {@link View#performAccessibilityAction(int, Bundle)
31449          *  View#performAccessibilityAction(int, Bundle)} for the case of
31450          *  no accessibility delegate been set.
31451          * </p>
31452          *
31453          * @param action The action to perform.
31454          * @return Whether the action was performed.
31455          *
31456          * @see View#performAccessibilityAction(int, Bundle)
31457          *      View#performAccessibilityAction(int, Bundle)
31458          */
performAccessibilityAction(@onNull View host, int action, @Nullable Bundle args)31459         public boolean performAccessibilityAction(@NonNull View host, int action,
31460                 @Nullable Bundle args) {
31461             return host.performAccessibilityActionInternal(action, args);
31462         }
31463 
31464         /**
31465          * Sends an accessibility event. This method behaves exactly as
31466          * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
31467          * empty {@link AccessibilityEvent} and does not perform a check whether
31468          * accessibility is enabled.
31469          * <p>
31470          * The default implementation behaves as
31471          * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
31472          *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
31473          * the case of no accessibility delegate been set.
31474          * </p>
31475          *
31476          * @param host The View hosting the delegate.
31477          * @param event The event to send.
31478          *
31479          * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
31480          *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
31481          */
sendAccessibilityEventUnchecked(@onNull View host, @NonNull AccessibilityEvent event)31482         public void sendAccessibilityEventUnchecked(@NonNull View host,
31483                 @NonNull AccessibilityEvent event) {
31484             host.sendAccessibilityEventUncheckedInternal(event);
31485         }
31486 
31487         /**
31488          * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
31489          * to its children for adding their text content to the event.
31490          * <p>
31491          * The default implementation behaves as
31492          * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
31493          *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
31494          * the case of no accessibility delegate been set.
31495          * </p>
31496          *
31497          * @param host The View hosting the delegate.
31498          * @param event The event.
31499          * @return True if the event population was completed.
31500          *
31501          * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
31502          *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
31503          */
dispatchPopulateAccessibilityEvent(@onNull View host, @NonNull AccessibilityEvent event)31504         public boolean dispatchPopulateAccessibilityEvent(@NonNull View host,
31505                 @NonNull AccessibilityEvent event) {
31506             return host.dispatchPopulateAccessibilityEventInternal(event);
31507         }
31508 
31509         /**
31510          * Gives a chance to the host View to populate the accessibility event with its
31511          * text content.
31512          * <p>
31513          * The default implementation behaves as
31514          * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
31515          *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
31516          * the case of no accessibility delegate been set.
31517          * </p>
31518          *
31519          * @param host The View hosting the delegate.
31520          * @param event The accessibility event which to populate.
31521          *
31522          * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
31523          *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
31524          */
onPopulateAccessibilityEvent(@onNull View host, @NonNull AccessibilityEvent event)31525         public void onPopulateAccessibilityEvent(@NonNull View host,
31526                 @NonNull AccessibilityEvent event) {
31527             host.onPopulateAccessibilityEventInternal(event);
31528         }
31529 
31530         /**
31531          * Initializes an {@link AccessibilityEvent} with information about the
31532          * the host View which is the event source.
31533          * <p>
31534          * The default implementation behaves as
31535          * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
31536          *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
31537          * the case of no accessibility delegate been set.
31538          * </p>
31539          *
31540          * @param host The View hosting the delegate.
31541          * @param event The event to initialize.
31542          *
31543          * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
31544          *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
31545          */
onInitializeAccessibilityEvent(@onNull View host, @NonNull AccessibilityEvent event)31546         public void onInitializeAccessibilityEvent(@NonNull View host,
31547                 @NonNull AccessibilityEvent event) {
31548             host.onInitializeAccessibilityEventInternal(event);
31549         }
31550 
31551         /**
31552          * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
31553          * <p>
31554          * The default implementation behaves as
31555          * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
31556          *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
31557          * the case of no accessibility delegate been set.
31558          * </p>
31559          *
31560          * @param host The View hosting the delegate.
31561          * @param info The instance to initialize.
31562          *
31563          * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
31564          *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
31565          */
onInitializeAccessibilityNodeInfo(@onNull View host, @NonNull AccessibilityNodeInfo info)31566         public void onInitializeAccessibilityNodeInfo(@NonNull View host,
31567                 @NonNull AccessibilityNodeInfo info) {
31568             host.onInitializeAccessibilityNodeInfoInternal(info);
31569         }
31570 
31571         /**
31572          * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
31573          * additional data.
31574          * <p>
31575          * This method only needs to be implemented if the View offers to provide additional data.
31576          * </p>
31577          * <p>
31578          * The default implementation behaves as
31579          * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, String, Bundle)
31580          * for the case where no accessibility delegate is set.
31581          * </p>
31582          *
31583          * @param host The View hosting the delegate. Never {@code null}.
31584          * @param info The info to which to add the extra data. Never {@code null}.
31585          * @param extraDataKey A key specifying the type of extra data to add to the info. The
31586          *                     extra data should be added to the {@link Bundle} returned by
31587          *                     the info's {@link AccessibilityNodeInfo#getExtras} method.  Never
31588          *                     {@code null}.
31589          * @param arguments A {@link Bundle} holding any arguments relevant for this request.
31590          *                  May be {@code null} if the if the service provided no arguments.
31591          *
31592          * @see AccessibilityNodeInfo#setAvailableExtraData(List)
31593          */
addExtraDataToAccessibilityNodeInfo(@onNull View host, @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey, @Nullable Bundle arguments)31594         public void addExtraDataToAccessibilityNodeInfo(@NonNull View host,
31595                 @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
31596                 @Nullable Bundle arguments) {
31597             host.addExtraDataToAccessibilityNodeInfo(info, extraDataKey, arguments);
31598         }
31599 
31600         /**
31601          * Called when a child of the host View has requested sending an
31602          * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
31603          * to augment the event.
31604          * <p>
31605          * The default implementation behaves as
31606          * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
31607          *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
31608          * the case of no accessibility delegate been set.
31609          * </p>
31610          *
31611          * @param host The View hosting the delegate.
31612          * @param child The child which requests sending the event.
31613          * @param event The event to be sent.
31614          * @return True if the event should be sent
31615          *
31616          * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
31617          *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
31618          */
onRequestSendAccessibilityEvent(@onNull ViewGroup host, @NonNull View child, @NonNull AccessibilityEvent event)31619         public boolean onRequestSendAccessibilityEvent(@NonNull ViewGroup host, @NonNull View child,
31620                 @NonNull AccessibilityEvent event) {
31621             return host.onRequestSendAccessibilityEventInternal(child, event);
31622         }
31623 
31624         /**
31625          * Gets the provider for managing a virtual view hierarchy rooted at this View
31626          * and reported to {@link android.accessibilityservice.AccessibilityService}s
31627          * that explore the window content.
31628          * <p>
31629          * The default implementation behaves as
31630          * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
31631          * the case of no accessibility delegate been set.
31632          * </p>
31633          *
31634          * @return The provider.
31635          *
31636          * @see AccessibilityNodeProvider
31637          */
getAccessibilityNodeProvider( @onNull View host)31638         public @Nullable AccessibilityNodeProvider getAccessibilityNodeProvider(
31639                 @NonNull View host) {
31640             return null;
31641         }
31642 
31643         /**
31644          * Returns an {@link AccessibilityNodeInfo} representing the host view from the
31645          * point of view of an {@link android.accessibilityservice.AccessibilityService}.
31646          * This method is responsible for obtaining an accessibility node info from a
31647          * pool of reusable instances and calling
31648          * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
31649          * view to initialize the former.
31650          * <p>
31651          * <strong>Note:</strong> The client is responsible for recycling the obtained
31652          * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
31653          * creation.
31654          * </p>
31655          * <p>
31656          * The default implementation behaves as
31657          * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
31658          * the case of no accessibility delegate been set.
31659          * </p>
31660          * @return A populated {@link AccessibilityNodeInfo}.
31661          *
31662          * @see AccessibilityNodeInfo
31663          *
31664          * @hide
31665          */
31666         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
createAccessibilityNodeInfo(@onNull View host)31667         public AccessibilityNodeInfo createAccessibilityNodeInfo(@NonNull View host) {
31668             return host.createAccessibilityNodeInfoInternal();
31669         }
31670     }
31671 
31672     private static class MatchIdPredicate implements Predicate<View> {
31673         public int mId;
31674 
31675         @Override
test(View view)31676         public boolean test(View view) {
31677             return (view.mID == mId);
31678         }
31679     }
31680 
31681     private static class MatchLabelForPredicate implements Predicate<View> {
31682         private int mLabeledId;
31683 
31684         @Override
test(View view)31685         public boolean test(View view) {
31686             return (view.mLabelForId == mLabeledId);
31687         }
31688     }
31689 
31690 
31691     /**
31692      * Returns the current scroll capture hint for this view.
31693      *
31694      * @return the current scroll capture hint
31695      */
31696     @ScrollCaptureHint
getScrollCaptureHint()31697     public int getScrollCaptureHint() {
31698         return (mPrivateFlags4 & PFLAG4_SCROLL_CAPTURE_HINT_MASK)
31699                 >> PFLAG4_SCROLL_CAPTURE_HINT_SHIFT;
31700     }
31701 
31702     /**
31703      * Sets the scroll capture hint for this View. These flags affect the search for a potential
31704      * scroll capture targets.
31705      *
31706      * @param hint the scrollCaptureHint flags value to set
31707      */
setScrollCaptureHint(@crollCaptureHint int hint)31708     public void setScrollCaptureHint(@ScrollCaptureHint int hint) {
31709         mPrivateFlags4 &= ~PFLAG4_SCROLL_CAPTURE_HINT_MASK;
31710         // Since include/exclude are mutually exclusive, exclude takes precedence.
31711         if ((hint & SCROLL_CAPTURE_HINT_EXCLUDE) != 0) {
31712             hint &= ~SCROLL_CAPTURE_HINT_INCLUDE;
31713         }
31714         mPrivateFlags4 |= ((hint << PFLAG4_SCROLL_CAPTURE_HINT_SHIFT)
31715                 & PFLAG4_SCROLL_CAPTURE_HINT_MASK);
31716     }
31717 
31718     /**
31719      * Sets the callback to receive scroll capture requests. This component is the adapter between
31720      * the scroll capture API and application UI code. If no callback is set, the system may provide
31721      * an implementation. Any value provided here will take precedence over a system version.
31722      * <p>
31723      * This view will be ignored when {@link #SCROLL_CAPTURE_HINT_EXCLUDE} is set in its {@link
31724      * #setScrollCaptureHint(int) scrollCaptureHint}, regardless whether a callback has been set.
31725      * <p>
31726      * It is recommended to set the scroll capture hint {@link #SCROLL_CAPTURE_HINT_INCLUDE} when
31727      * setting a custom callback to help ensure it is selected as the target.
31728      *
31729      * @param callback the new callback to assign
31730      */
setScrollCaptureCallback(@ullable ScrollCaptureCallback callback)31731     public final void setScrollCaptureCallback(@Nullable ScrollCaptureCallback callback) {
31732         getListenerInfo().mScrollCaptureCallback = callback;
31733     }
31734 
31735     /** {@hide} */
31736     @Nullable
createScrollCaptureCallbackInternal(@onNull Rect localVisibleRect, @NonNull Point windowOffset)31737     public ScrollCaptureCallback createScrollCaptureCallbackInternal(@NonNull Rect localVisibleRect,
31738             @NonNull Point windowOffset) {
31739         if (mAttachInfo == null) {
31740             return null;
31741         }
31742         if (mAttachInfo.mScrollCaptureInternal == null) {
31743             mAttachInfo.mScrollCaptureInternal = new ScrollCaptureInternal();
31744         }
31745         return mAttachInfo.mScrollCaptureInternal.requestCallback(this, localVisibleRect,
31746                 windowOffset);
31747     }
31748 
31749     /**
31750      * Dispatch a scroll capture search request down the view hierarchy.
31751      *
31752      * @param localVisibleRect the visible area of this ViewGroup in local coordinates, according to
31753      *                         the parent
31754      * @param windowOffset     the offset of this view within the window
31755      * @param targets          accepts potential scroll capture targets; {@link Consumer#accept
31756      *                         results.accept} may be called zero or more times on the calling
31757      *                         thread before onScrollCaptureSearch returns
31758      */
dispatchScrollCaptureSearch( @onNull Rect localVisibleRect, @NonNull Point windowOffset, @NonNull Consumer<ScrollCaptureTarget> targets)31759     public void dispatchScrollCaptureSearch(
31760             @NonNull Rect localVisibleRect, @NonNull Point windowOffset,
31761             @NonNull Consumer<ScrollCaptureTarget> targets) {
31762         onScrollCaptureSearch(localVisibleRect, windowOffset, targets);
31763     }
31764 
31765     /**
31766      * Called when scroll capture is requested, to search for appropriate content to scroll. If
31767      * applicable, this view adds itself to the provided list for consideration, subject to the
31768      * flags set by {@link #setScrollCaptureHint}.
31769      *
31770      * @param localVisibleRect the local visible rect of this view
31771      * @param windowOffset     the offset of localVisibleRect within the window
31772      * @param targets          accepts potential scroll capture targets; {@link Consumer#accept
31773      *                         results.accept} may be called zero or more times on the calling
31774      *                         thread before onScrollCaptureSearch returns
31775      * @throws IllegalStateException if this view is not attached to a window
31776      */
onScrollCaptureSearch(@onNull Rect localVisibleRect, @NonNull Point windowOffset, @NonNull Consumer<ScrollCaptureTarget> targets)31777     public void onScrollCaptureSearch(@NonNull Rect localVisibleRect,
31778             @NonNull Point windowOffset, @NonNull Consumer<ScrollCaptureTarget> targets) {
31779         int hint = getScrollCaptureHint();
31780         if ((hint & SCROLL_CAPTURE_HINT_EXCLUDE) != 0) {
31781             return;
31782         }
31783         boolean rectIsVisible = true;
31784 
31785         // Apply clipBounds if present.
31786         if (mClipBounds != null) {
31787             rectIsVisible = localVisibleRect.intersect(mClipBounds);
31788         }
31789         if (!rectIsVisible) {
31790             return;
31791         }
31792 
31793         // Get a callback provided by the framework, library or application.
31794         ScrollCaptureCallback callback =
31795                 (mListenerInfo == null) ? null : mListenerInfo.mScrollCaptureCallback;
31796 
31797         // Try framework support for standard scrolling containers.
31798         if (callback == null) {
31799             callback = createScrollCaptureCallbackInternal(localVisibleRect, windowOffset);
31800         }
31801 
31802         // If found, then add it to the list.
31803         if (callback != null) {
31804             // Add to the list for consideration
31805             Point offset = new Point(windowOffset.x, windowOffset.y);
31806             Rect rect = new Rect(localVisibleRect);
31807             targets.accept(new ScrollCaptureTarget(this, rect, offset, callback));
31808         }
31809     }
31810 
31811     /**
31812      * Dump all private flags in readable format, useful for documentation and
31813      * consistency checking.
31814      */
dumpFlags()31815     private static void dumpFlags() {
31816         final HashMap<String, String> found = Maps.newHashMap();
31817         try {
31818             for (Field field : View.class.getDeclaredFields()) {
31819                 final int modifiers = field.getModifiers();
31820                 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
31821                     if (field.getType().equals(int.class)) {
31822                         final int value = field.getInt(null);
31823                         dumpFlag(found, field.getName(), value);
31824                     } else if (field.getType().equals(int[].class)) {
31825                         final int[] values = (int[]) field.get(null);
31826                         for (int i = 0; i < values.length; i++) {
31827                             dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
31828                         }
31829                     }
31830                 }
31831             }
31832         } catch (IllegalAccessException e) {
31833             throw new RuntimeException(e);
31834         }
31835 
31836         final ArrayList<String> keys = Lists.newArrayList();
31837         keys.addAll(found.keySet());
31838         Collections.sort(keys);
31839         for (String key : keys) {
31840             Log.d(VIEW_LOG_TAG, found.get(key));
31841         }
31842     }
31843 
dumpFlag(HashMap<String, String> found, String name, int value)31844     private static void dumpFlag(HashMap<String, String> found, String name, int value) {
31845         // Sort flags by prefix, then by bits, always keeping unique keys
31846         final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
31847         final int prefix = name.indexOf('_');
31848         final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
31849         final String output = bits + " " + name;
31850         found.put(key, output);
31851     }
31852 
31853     /** {@hide} */
encode(@onNull ViewHierarchyEncoder stream)31854     public void encode(@NonNull ViewHierarchyEncoder stream) {
31855         stream.beginObject(this);
31856         encodeProperties(stream);
31857         stream.endObject();
31858     }
31859 
31860     /** {@hide} */
31861     @CallSuper
encodeProperties(@onNull ViewHierarchyEncoder stream)31862     protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
31863         Object resolveId = ViewDebug.resolveId(getContext(), mID);
31864         if (resolveId instanceof String) {
31865             stream.addProperty("id", (String) resolveId);
31866         } else {
31867             stream.addProperty("id", mID);
31868         }
31869 
31870         stream.addProperty("misc:transformation.alpha",
31871                 mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
31872         stream.addProperty("misc:transitionName", getTransitionName());
31873 
31874         // layout
31875         stream.addProperty("layout:left", mLeft);
31876         stream.addProperty("layout:right", mRight);
31877         stream.addProperty("layout:top", mTop);
31878         stream.addProperty("layout:bottom", mBottom);
31879         stream.addProperty("layout:width", getWidth());
31880         stream.addProperty("layout:height", getHeight());
31881         stream.addProperty("layout:layoutDirection", getLayoutDirection());
31882         stream.addProperty("layout:layoutRtl", isLayoutRtl());
31883         stream.addProperty("layout:hasTransientState", hasTransientState());
31884         stream.addProperty("layout:baseline", getBaseline());
31885 
31886         // layout params
31887         ViewGroup.LayoutParams layoutParams = getLayoutParams();
31888         if (layoutParams != null) {
31889             stream.addPropertyKey("layoutParams");
31890             layoutParams.encode(stream);
31891         }
31892 
31893         // scrolling
31894         stream.addProperty("scrolling:scrollX", mScrollX);
31895         stream.addProperty("scrolling:scrollY", mScrollY);
31896 
31897         // padding
31898         stream.addProperty("padding:paddingLeft", mPaddingLeft);
31899         stream.addProperty("padding:paddingRight", mPaddingRight);
31900         stream.addProperty("padding:paddingTop", mPaddingTop);
31901         stream.addProperty("padding:paddingBottom", mPaddingBottom);
31902         stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
31903         stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
31904         stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
31905         stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
31906         stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
31907 
31908         // measurement
31909         stream.addProperty("measurement:minHeight", mMinHeight);
31910         stream.addProperty("measurement:minWidth", mMinWidth);
31911         stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
31912         stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
31913 
31914         // drawing
31915         stream.addProperty("drawing:elevation", getElevation());
31916         stream.addProperty("drawing:translationX", getTranslationX());
31917         stream.addProperty("drawing:translationY", getTranslationY());
31918         stream.addProperty("drawing:translationZ", getTranslationZ());
31919         stream.addProperty("drawing:rotation", getRotation());
31920         stream.addProperty("drawing:rotationX", getRotationX());
31921         stream.addProperty("drawing:rotationY", getRotationY());
31922         stream.addProperty("drawing:scaleX", getScaleX());
31923         stream.addProperty("drawing:scaleY", getScaleY());
31924         stream.addProperty("drawing:pivotX", getPivotX());
31925         stream.addProperty("drawing:pivotY", getPivotY());
31926         stream.addProperty("drawing:clipBounds",
31927                 mClipBounds == null ? null : mClipBounds.toString());
31928         stream.addProperty("drawing:opaque", isOpaque());
31929         stream.addProperty("drawing:alpha", getAlpha());
31930         stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
31931         stream.addProperty("drawing:shadow", hasShadow());
31932         stream.addProperty("drawing:solidColor", getSolidColor());
31933         stream.addProperty("drawing:layerType", mLayerType);
31934         stream.addProperty("drawing:willNotDraw", willNotDraw());
31935         stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
31936         stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
31937         stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
31938         stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
31939         stream.addProperty("drawing:outlineAmbientShadowColor", getOutlineAmbientShadowColor());
31940         stream.addProperty("drawing:outlineSpotShadowColor", getOutlineSpotShadowColor());
31941 
31942         // focus
31943         stream.addProperty("focus:hasFocus", hasFocus());
31944         stream.addProperty("focus:isFocused", isFocused());
31945         stream.addProperty("focus:focusable", getFocusable());
31946         stream.addProperty("focus:isFocusable", isFocusable());
31947         stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
31948 
31949         stream.addProperty("misc:clickable", isClickable());
31950         stream.addProperty("misc:pressed", isPressed());
31951         stream.addProperty("misc:selected", isSelected());
31952         stream.addProperty("misc:touchMode", isInTouchMode());
31953         stream.addProperty("misc:hovered", isHovered());
31954         stream.addProperty("misc:activated", isActivated());
31955 
31956         stream.addProperty("misc:visibility", getVisibility());
31957         stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
31958         stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
31959 
31960         stream.addProperty("misc:enabled", isEnabled());
31961         stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
31962         stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
31963 
31964         // theme attributes
31965         Resources.Theme theme = getContext().getTheme();
31966         if (theme != null) {
31967             stream.addPropertyKey("theme");
31968             theme.encode(stream);
31969         }
31970 
31971         // view attribute information
31972         int n = mAttributes != null ? mAttributes.length : 0;
31973         stream.addProperty("meta:__attrCount__", n/2);
31974         for (int i = 0; i < n; i += 2) {
31975             stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
31976         }
31977 
31978         stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
31979 
31980         // text
31981         stream.addProperty("text:textDirection", getTextDirection());
31982         stream.addProperty("text:textAlignment", getTextAlignment());
31983 
31984         // accessibility
31985         CharSequence contentDescription = getContentDescription();
31986         stream.addUserProperty("accessibility:contentDescription",
31987                 contentDescription == null ? "" : contentDescription.toString());
31988         stream.addProperty("accessibility:labelFor", getLabelFor());
31989         stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
31990     }
31991 
31992     /**
31993      * Determine if this view is rendered on a round wearable device and is the main view
31994      * on the screen.
31995      */
shouldDrawRoundScrollbar()31996     boolean shouldDrawRoundScrollbar() {
31997         if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
31998             return false;
31999         }
32000 
32001         final View rootView = getRootView();
32002         final WindowInsets insets = getRootWindowInsets();
32003 
32004         int height = getHeight();
32005         int width = getWidth();
32006         int displayHeight = rootView.getHeight();
32007         int displayWidth = rootView.getWidth();
32008 
32009         if (height != displayHeight || width != displayWidth) {
32010             return false;
32011         }
32012 
32013         getLocationInWindow(mAttachInfo.mTmpLocation);
32014         return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
32015                 && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
32016     }
32017 
32018     /**
32019      * Sets the tooltip text which will be displayed in a small popup next to the view.
32020      * <p>
32021      * The tooltip will be displayed:
32022      * <ul>
32023      * <li>On long click, unless it is handled otherwise (by OnLongClickListener or a context
32024      * menu). </li>
32025      * <li>On hover, after a brief delay since the pointer has stopped moving </li>
32026      * </ul>
32027      * <p>
32028      * <strong>Note:</strong> Do not override this method, as it will have no
32029      * effect on the text displayed in the tooltip.
32030      *
32031      * @param tooltipText the tooltip text, or null if no tooltip is required
32032      * @see #getTooltipText()
32033      * @attr ref android.R.styleable#View_tooltipText
32034      */
setTooltipText(@ullable CharSequence tooltipText)32035     public void setTooltipText(@Nullable CharSequence tooltipText) {
32036         if (TextUtils.isEmpty(tooltipText)) {
32037             setFlags(0, TOOLTIP);
32038             hideTooltip();
32039             mTooltipInfo = null;
32040         } else {
32041             setFlags(TOOLTIP, TOOLTIP);
32042             if (mTooltipInfo == null) {
32043                 mTooltipInfo = new TooltipInfo();
32044                 mTooltipInfo.mShowTooltipRunnable = this::showHoverTooltip;
32045                 mTooltipInfo.mHideTooltipRunnable = this::hideTooltip;
32046                 mTooltipInfo.mHoverSlop = ViewConfiguration.get(mContext).getScaledHoverSlop();
32047                 mTooltipInfo.clearAnchorPos();
32048             }
32049             mTooltipInfo.mTooltipText = tooltipText;
32050         }
32051     }
32052 
32053     /**
32054      * @hide Binary compatibility stub. To be removed when we finalize O APIs.
32055      */
32056     @UnsupportedAppUsage
setTooltip(@ullable CharSequence tooltipText)32057     public void setTooltip(@Nullable CharSequence tooltipText) {
32058         setTooltipText(tooltipText);
32059     }
32060 
32061     /**
32062      * Returns the view's tooltip text.
32063      *
32064      * <strong>Note:</strong> Do not override this method, as it will have no
32065      * effect on the text displayed in the tooltip. You must call
32066      * {@link #setTooltipText(CharSequence)} to modify the tooltip text.
32067      *
32068      * @return the tooltip text
32069      * @see #setTooltipText(CharSequence)
32070      * @attr ref android.R.styleable#View_tooltipText
32071      */
32072     @InspectableProperty
32073     @Nullable
getTooltipText()32074     public CharSequence getTooltipText() {
32075         return mTooltipInfo != null ? mTooltipInfo.mTooltipText : null;
32076     }
32077 
32078     /**
32079      * @hide Binary compatibility stub. To be removed when we finalize O APIs.
32080      */
32081     @Nullable
getTooltip()32082     public CharSequence getTooltip() {
32083         return getTooltipText();
32084     }
32085 
showTooltip(int x, int y, boolean fromLongClick)32086     private boolean showTooltip(int x, int y, boolean fromLongClick) {
32087         if (mAttachInfo == null || mTooltipInfo == null) {
32088             return false;
32089         }
32090         if (fromLongClick && (mViewFlags & ENABLED_MASK) != ENABLED) {
32091             return false;
32092         }
32093         if (TextUtils.isEmpty(mTooltipInfo.mTooltipText)) {
32094             return false;
32095         }
32096         hideTooltip();
32097         mTooltipInfo.mTooltipFromLongClick = fromLongClick;
32098         mTooltipInfo.mTooltipPopup = new TooltipPopup(getContext());
32099         final boolean fromTouch = (mPrivateFlags3 & PFLAG3_FINGER_DOWN) == PFLAG3_FINGER_DOWN;
32100         mTooltipInfo.mTooltipPopup.show(this, x, y, fromTouch, mTooltipInfo.mTooltipText);
32101         mAttachInfo.mTooltipHost = this;
32102         // The available accessibility actions have changed
32103         notifyViewAccessibilityStateChangedIfNeeded(CONTENT_CHANGE_TYPE_UNDEFINED);
32104         return true;
32105     }
32106 
32107     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
hideTooltip()32108     void hideTooltip() {
32109         if (mTooltipInfo == null) {
32110             return;
32111         }
32112         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
32113         if (mTooltipInfo.mTooltipPopup == null) {
32114             return;
32115         }
32116         mTooltipInfo.mTooltipPopup.hide();
32117         mTooltipInfo.mTooltipPopup = null;
32118         mTooltipInfo.mTooltipFromLongClick = false;
32119         mTooltipInfo.clearAnchorPos();
32120         if (mAttachInfo != null) {
32121             mAttachInfo.mTooltipHost = null;
32122         }
32123         // The available accessibility actions have changed
32124         notifyViewAccessibilityStateChangedIfNeeded(CONTENT_CHANGE_TYPE_UNDEFINED);
32125     }
32126 
showLongClickTooltip(int x, int y)32127     private boolean showLongClickTooltip(int x, int y) {
32128         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
32129         removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
32130         return showTooltip(x, y, true);
32131     }
32132 
showHoverTooltip()32133     private boolean showHoverTooltip() {
32134         return showTooltip(mTooltipInfo.mAnchorX, mTooltipInfo.mAnchorY, false);
32135     }
32136 
dispatchTooltipHoverEvent(MotionEvent event)32137     boolean dispatchTooltipHoverEvent(MotionEvent event) {
32138         if (mTooltipInfo == null) {
32139             return false;
32140         }
32141         switch(event.getAction()) {
32142             case MotionEvent.ACTION_HOVER_MOVE:
32143                 if ((mViewFlags & TOOLTIP) != TOOLTIP) {
32144                     break;
32145                 }
32146                 if (!mTooltipInfo.mTooltipFromLongClick && mTooltipInfo.updateAnchorPos(event)) {
32147                     if (mTooltipInfo.mTooltipPopup == null) {
32148                         // Schedule showing the tooltip after a timeout.
32149                         removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
32150                         postDelayed(mTooltipInfo.mShowTooltipRunnable,
32151                                 ViewConfiguration.getHoverTooltipShowTimeout());
32152                     }
32153 
32154                     // Hide hover-triggered tooltip after a period of inactivity.
32155                     // Match the timeout used by NativeInputManager to hide the mouse pointer
32156                     // (depends on SYSTEM_UI_FLAG_LOW_PROFILE being set).
32157                     final int timeout;
32158                     if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LOW_PROFILE)
32159                             == SYSTEM_UI_FLAG_LOW_PROFILE) {
32160                         timeout = ViewConfiguration.getHoverTooltipHideShortTimeout();
32161                     } else {
32162                         timeout = ViewConfiguration.getHoverTooltipHideTimeout();
32163                     }
32164                     removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
32165                     postDelayed(mTooltipInfo.mHideTooltipRunnable, timeout);
32166                 }
32167                 return true;
32168 
32169             case MotionEvent.ACTION_HOVER_EXIT:
32170                 mTooltipInfo.clearAnchorPos();
32171                 if (!mTooltipInfo.mTooltipFromLongClick) {
32172                     hideTooltip();
32173                 }
32174                 break;
32175         }
32176         return false;
32177     }
32178 
handleTooltipKey(KeyEvent event)32179     void handleTooltipKey(KeyEvent event) {
32180         switch (event.getAction()) {
32181             case KeyEvent.ACTION_DOWN:
32182                 if (event.getRepeatCount() == 0) {
32183                     hideTooltip();
32184                 }
32185                 break;
32186 
32187             case KeyEvent.ACTION_UP:
32188                 handleTooltipUp();
32189                 break;
32190         }
32191     }
32192 
handleTooltipUp()32193     private void handleTooltipUp() {
32194         if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
32195             return;
32196         }
32197         removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
32198         postDelayed(mTooltipInfo.mHideTooltipRunnable,
32199                 ViewConfiguration.getLongPressTooltipHideTimeout());
32200     }
32201 
getFocusableAttribute(TypedArray attributes)32202     private int getFocusableAttribute(TypedArray attributes) {
32203         TypedValue val = new TypedValue();
32204         if (attributes.getValue(com.android.internal.R.styleable.View_focusable, val)) {
32205             if (val.type == TypedValue.TYPE_INT_BOOLEAN) {
32206                 return (val.data == 0 ? NOT_FOCUSABLE : FOCUSABLE);
32207             } else {
32208                 return val.data;
32209             }
32210         } else {
32211             return FOCUSABLE_AUTO;
32212         }
32213     }
32214 
32215     /**
32216      * @return The content view of the tooltip popup currently being shown, or null if the tooltip
32217      * is not showing.
32218      * @hide
32219      */
32220     @TestApi
getTooltipView()32221     public View getTooltipView() {
32222         if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
32223             return null;
32224         }
32225         return mTooltipInfo.mTooltipPopup.getContentView();
32226     }
32227 
32228     /**
32229      * @return {@code true} if the default focus highlight is enabled, {@code false} otherwies.
32230      * @hide
32231      */
32232     @TestApi
isDefaultFocusHighlightEnabled()32233     public static boolean isDefaultFocusHighlightEnabled() {
32234         return sUseDefaultFocusHighlight;
32235     }
32236 
32237     /**
32238      * Dispatch a previously unhandled {@link KeyEvent} to this view. Unlike normal key dispatch,
32239      * this dispatches to ALL child views until it is consumed. The dispatch order is z-order
32240      * (visually on-top views first).
32241      *
32242      * @param evt the previously unhandled {@link KeyEvent}.
32243      * @return the {@link View} which consumed the event or {@code null} if not consumed.
32244      */
dispatchUnhandledKeyEvent(KeyEvent evt)32245     View dispatchUnhandledKeyEvent(KeyEvent evt) {
32246         if (onUnhandledKeyEvent(evt)) {
32247             return this;
32248         }
32249         return null;
32250     }
32251 
32252     /**
32253      * Allows this view to handle {@link KeyEvent}s which weren't handled by normal dispatch. This
32254      * occurs after the normal view hierarchy dispatch, but before the window callback. By default,
32255      * this will dispatch into all the listeners registered via
32256      * {@link #addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener)} in last-in-first-out
32257      * order (most recently added will receive events first).
32258      *
32259      * @param event An unhandled event.
32260      * @return {@code true} if the event was handled, {@code false} otherwise.
32261      * @see #addOnUnhandledKeyEventListener
32262      */
onUnhandledKeyEvent(@onNull KeyEvent event)32263     boolean onUnhandledKeyEvent(@NonNull KeyEvent event) {
32264         if (mListenerInfo != null && mListenerInfo.mUnhandledKeyListeners != null) {
32265             for (int i = mListenerInfo.mUnhandledKeyListeners.size() - 1; i >= 0; --i) {
32266                 if (mListenerInfo.mUnhandledKeyListeners.get(i).onUnhandledKeyEvent(this, event)) {
32267                     return true;
32268                 }
32269             }
32270         }
32271         return false;
32272     }
32273 
hasUnhandledKeyListener()32274     boolean hasUnhandledKeyListener() {
32275         return (mListenerInfo != null && mListenerInfo.mUnhandledKeyListeners != null
32276                 && !mListenerInfo.mUnhandledKeyListeners.isEmpty());
32277     }
32278 
32279     /**
32280      * Adds a listener which will receive unhandled {@link KeyEvent}s. This must be called on the
32281      * UI thread.
32282      *
32283      * @param listener a receiver of unhandled {@link KeyEvent}s.
32284      * @see #removeOnUnhandledKeyEventListener
32285      */
addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener)32286     public void addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener) {
32287         ArrayList<OnUnhandledKeyEventListener> listeners = getListenerInfo().mUnhandledKeyListeners;
32288         if (listeners == null) {
32289             listeners = new ArrayList<>();
32290             getListenerInfo().mUnhandledKeyListeners = listeners;
32291         }
32292         listeners.add(listener);
32293         if (listeners.size() == 1 && mParent instanceof ViewGroup) {
32294             ((ViewGroup) mParent).incrementChildUnhandledKeyListeners();
32295         }
32296     }
32297 
32298     /**
32299      * Removes a listener which will receive unhandled {@link KeyEvent}s. This must be called on the
32300      * UI thread.
32301      *
32302      * @param listener a receiver of unhandled {@link KeyEvent}s.
32303      * @see #addOnUnhandledKeyEventListener
32304      */
removeOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener)32305     public void removeOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener) {
32306         if (mListenerInfo != null) {
32307             if (mListenerInfo.mUnhandledKeyListeners != null
32308                     && !mListenerInfo.mUnhandledKeyListeners.isEmpty()) {
32309                 mListenerInfo.mUnhandledKeyListeners.remove(listener);
32310                 if (mListenerInfo.mUnhandledKeyListeners.isEmpty()) {
32311                     mListenerInfo.mUnhandledKeyListeners = null;
32312                     if (mParent instanceof ViewGroup) {
32313                         ((ViewGroup) mParent).decrementChildUnhandledKeyListeners();
32314                     }
32315                 }
32316             }
32317         }
32318     }
32319 
32320     /**
32321      * Set the view to be detached or not detached.
32322      *
32323      * @param detached Whether the view is detached.
32324      *
32325      * @hide
32326      */
setDetached(boolean detached)32327     protected void setDetached(boolean detached) {
32328         if (detached) {
32329             mPrivateFlags4 |= PFLAG4_DETACHED;
32330         } else {
32331             mPrivateFlags4 &= ~PFLAG4_DETACHED;
32332         }
32333     }
32334 
32335     /**
32336      * Sets whether this view is a credential for Credential Manager purposes.
32337      *
32338      * <p>See {@link #isCredential()}.
32339      *
32340      * @param isCredential Whether the view is a credential.
32341      *
32342      * @attr ref android.R.styleable#View_isCredential
32343      */
setIsCredential(boolean isCredential)32344     public void setIsCredential(boolean isCredential) {
32345         if (isCredential) {
32346             mPrivateFlags4 |= PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER;
32347         } else {
32348             mPrivateFlags4 &= ~PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER;
32349         }
32350     }
32351 
32352     /**
32353      * Gets the mode for determining whether this view is a credential.
32354      *
32355      * <p>See {@link #setIsCredential(boolean)}.
32356      *
32357      * @return false by default, or value passed to {@link #setIsCredential(boolean)}.
32358      *
32359      * @attr ref android.R.styleable#View_isCredential
32360      */
isCredential()32361     public boolean isCredential() {
32362         return ((mPrivateFlags4 & PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER)
32363                 == PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER);
32364     }
32365 
32366     /**
32367      * Set whether this view enables automatic handwriting initiation.
32368      *
32369      * For a view with an active {@link InputConnection}, if auto handwriting is enabled then
32370      * stylus movement within its view boundary will automatically trigger the handwriting mode.
32371      * Check {@link android.view.inputmethod.InputMethodManager#startStylusHandwriting(View)} for
32372      * more details about handwriting mode.
32373      *
32374      * If the View wants to initiate handwriting mode by itself, it can set this field to
32375      * {@code false} and call
32376      * {@link android.view.inputmethod.InputMethodManager#startStylusHandwriting(View)} when there
32377      * is stylus movement detected.
32378      *
32379      * Note that this attribute has no effect on the View's children. For example, if a
32380      * {@link ViewGroup} disables auto handwriting but its children set auto handwriting to true,
32381      * auto handwriting will still work for the children, and vice versa.
32382      *
32383      * @see #onCreateInputConnection(EditorInfo)
32384      * @see android.view.inputmethod.InputMethodManager#startStylusHandwriting(View)
32385      * @param enabled whether auto handwriting initiation is enabled for this view.
32386      * @attr ref android.R.styleable#View_autoHandwritingEnabled
32387      */
setAutoHandwritingEnabled(boolean enabled)32388     public void setAutoHandwritingEnabled(boolean enabled) {
32389         if (enabled) {
32390             mPrivateFlags4 |= PFLAG4_AUTO_HANDWRITING_ENABLED;
32391         } else {
32392             mPrivateFlags4 &= ~PFLAG4_AUTO_HANDWRITING_ENABLED;
32393         }
32394         updatePositionUpdateListener();
32395         postUpdate(this::updateHandwritingArea);
32396     }
32397 
32398     /**
32399      * Return whether the View allows automatic handwriting initiation. Returns true if automatic
32400      * handwriting initiation is enabled, and verse visa.
32401      * @see #setAutoHandwritingEnabled(boolean)
32402      */
isAutoHandwritingEnabled()32403     public boolean isAutoHandwritingEnabled() {
32404         return (mPrivateFlags4 & PFLAG4_AUTO_HANDWRITING_ENABLED)
32405                 == PFLAG4_AUTO_HANDWRITING_ENABLED;
32406     }
32407 
32408     /**
32409      * Return whether the stylus handwriting is available for this View.
32410      * @hide
32411      */
isStylusHandwritingAvailable()32412     public boolean isStylusHandwritingAvailable() {
32413         return getContext().getSystemService(InputMethodManager.class)
32414                 .isStylusHandwritingAvailable();
32415     }
32416 
setTraversalTracingEnabled(boolean enabled)32417     private void setTraversalTracingEnabled(boolean enabled) {
32418         if (enabled) {
32419             if (mTracingStrings == null) {
32420                 mTracingStrings = new ViewTraversalTracingStrings(this);
32421             }
32422             mPrivateFlags4 |= PFLAG4_TRAVERSAL_TRACING_ENABLED;
32423         } else {
32424             mPrivateFlags4 &= ~PFLAG4_TRAVERSAL_TRACING_ENABLED;
32425         }
32426     }
32427 
isTraversalTracingEnabled()32428     private boolean isTraversalTracingEnabled() {
32429         return (mPrivateFlags4 & PFLAG4_TRAVERSAL_TRACING_ENABLED)
32430                 == PFLAG4_TRAVERSAL_TRACING_ENABLED;
32431     }
32432 
setRelayoutTracingEnabled(boolean enabled)32433     private void setRelayoutTracingEnabled(boolean enabled) {
32434         if (enabled) {
32435             if (mTracingStrings == null) {
32436                 mTracingStrings = new ViewTraversalTracingStrings(this);
32437             }
32438             mPrivateFlags4 |= PFLAG4_RELAYOUT_TRACING_ENABLED;
32439         } else {
32440             mPrivateFlags4 &= ~PFLAG4_RELAYOUT_TRACING_ENABLED;
32441         }
32442     }
32443 
isRelayoutTracingEnabled()32444     private boolean isRelayoutTracingEnabled() {
32445         return (mPrivateFlags4 & PFLAG4_RELAYOUT_TRACING_ENABLED)
32446                 == PFLAG4_RELAYOUT_TRACING_ENABLED;
32447     }
32448 
32449     /**
32450      * Collects a {@link ViewTranslationRequest} which represents the content to be translated in
32451      * the view.
32452      *
32453      * <p>The default implementation does nothing.</p>
32454      *
32455      * @param supportedFormats the supported translation formats. For now, the only possible value
32456      * is the {@link android.view.translation.TranslationSpec#DATA_FORMAT_TEXT}.
32457      * @param requestsCollector a {@link ViewTranslationRequest} collector that can be used to
32458      * collect the information to be translated in the view. The {@code requestsCollector} only
32459      * accepts one request; an IllegalStateException is thrown if more than one
32460      * {@link ViewTranslationRequest} is submitted to it. The {@link AutofillId} must be set on the
32461      * {@link ViewTranslationRequest}.
32462      */
onCreateViewTranslationRequest(@onNull @ataFormat int[] supportedFormats, @NonNull Consumer<ViewTranslationRequest> requestsCollector)32463     public void onCreateViewTranslationRequest(@NonNull @DataFormat int[] supportedFormats,
32464             @NonNull Consumer<ViewTranslationRequest> requestsCollector) {
32465     }
32466 
32467     /**
32468      * Collects {@link ViewTranslationRequest}s which represents the content to be translated
32469      * for the virtual views in the host view. This is called if this view returned a virtual
32470      * view structure from {@link #onProvideContentCaptureStructure} and the system determined that
32471      * those virtual views were relevant for translation.
32472      *
32473      * <p>The default implementation does nothing.</p>
32474      *
32475      * @param virtualIds the virtual view ids which represents the virtual views in the host
32476      * view.
32477      * @param supportedFormats the supported translation formats. For now, the only possible value
32478      * is the {@link android.view.translation.TranslationSpec#DATA_FORMAT_TEXT}.
32479      * @param requestsCollector a {@link ViewTranslationRequest} collector that can be called
32480      * multiple times to collect the information to be translated in the host view. One
32481      * {@link ViewTranslationRequest} per virtual child. The {@link ViewTranslationRequest} must
32482      * contains the {@link AutofillId} corresponding to the virtualChildIds. Do not keep this
32483      * Consumer after the method returns.
32484      */
32485     @SuppressLint("NullableCollection")
onCreateVirtualViewTranslationRequests(@onNull long[] virtualIds, @NonNull @DataFormat int[] supportedFormats, @NonNull Consumer<ViewTranslationRequest> requestsCollector)32486     public void onCreateVirtualViewTranslationRequests(@NonNull long[] virtualIds,
32487             @NonNull @DataFormat int[] supportedFormats,
32488             @NonNull Consumer<ViewTranslationRequest> requestsCollector) {
32489         // no-op
32490     }
32491 
32492     /**
32493      * Returns a {@link ViewTranslationCallback} that is used to display the translated information
32494      * or {@code null} if this View doesn't support translation.
32495      *
32496      * @hide
32497      */
32498     @Nullable
getViewTranslationCallback()32499     public ViewTranslationCallback getViewTranslationCallback() {
32500         return mViewTranslationCallback;
32501     }
32502 
32503     /**
32504      * Sets a {@link ViewTranslationCallback} that is used to display/hide the translated
32505      * information. Developers can provide the customized implementation for show/hide translated
32506      * information.
32507      *
32508      * @param callback a {@link ViewTranslationCallback} that is used to control how to display the
32509      * translated information
32510      */
setViewTranslationCallback(@onNull ViewTranslationCallback callback)32511     public void setViewTranslationCallback(@NonNull ViewTranslationCallback callback) {
32512         mViewTranslationCallback = callback;
32513     }
32514 
32515     /**
32516      * Clear the {@link ViewTranslationCallback} from this view.
32517      */
clearViewTranslationCallback()32518     public void clearViewTranslationCallback() {
32519         mViewTranslationCallback = null;
32520     }
32521 
32522     /**
32523      * Returns the {@link ViewTranslationResponse} associated with this view. The response will be
32524      * set when the translation is done then {@link #onViewTranslationResponse} is called. The
32525      * {@link ViewTranslationCallback} can use to get {@link ViewTranslationResponse} to display the
32526      * translated information.
32527      *
32528      * @return a {@link ViewTranslationResponse} that contains the translated information associated
32529      * with this view or {@code null} if this View doesn't have the translation.
32530      */
32531     @Nullable
getViewTranslationResponse()32532     public ViewTranslationResponse getViewTranslationResponse() {
32533         return mViewTranslationResponse;
32534     }
32535 
32536     /**
32537      * Called when the content from {@link View#onCreateViewTranslationRequest} had been translated
32538      * by the TranslationService. The {@link ViewTranslationResponse} should be saved here so that
32539      * the {@link ViewTranslationResponse} can be used to display the translation when the system
32540      * calls {@link ViewTranslationCallback#onShowTranslation}.
32541      *
32542      * <p> The default implementation will set the ViewTranslationResponse that can be get from
32543      * {@link View#getViewTranslationResponse}. </p>
32544      *
32545      * @param response a {@link ViewTranslationResponse} that contains the translated information
32546      * which can be shown in the view.
32547      */
onViewTranslationResponse(@onNull ViewTranslationResponse response)32548     public void onViewTranslationResponse(@NonNull ViewTranslationResponse response) {
32549         mViewTranslationResponse = response;
32550     }
32551 
32552     /**
32553      * Clears the ViewTranslationResponse stored by the default implementation of {@link
32554      * #onViewTranslationResponse}.
32555      *
32556      * @hide
32557      */
clearViewTranslationResponse()32558     public void clearViewTranslationResponse() {
32559         mViewTranslationResponse = null;
32560     }
32561 
32562     /**
32563      * Called when the content from {@link View#onCreateVirtualViewTranslationRequests} had been
32564      * translated by the TranslationService.
32565      *
32566      * <p> The default implementation does nothing.</p>
32567      *
32568      * @param response a {@link ViewTranslationResponse} SparseArray for the request that send by
32569      * {@link View#onCreateVirtualViewTranslationRequests} that contains the translated information
32570      * which can be shown in the view. The key of SparseArray is the virtual child ids.
32571      */
onVirtualViewTranslationResponses( @onNull LongSparseArray<ViewTranslationResponse> response)32572     public void onVirtualViewTranslationResponses(
32573             @NonNull LongSparseArray<ViewTranslationResponse> response) {
32574         // no-op
32575     }
32576 
32577     /**
32578      * Dispatch to collect the {@link ViewTranslationRequest}s for translation purpose by traversing
32579      * the hierarchy when the app requests ui translation. Typically, this method should only be
32580      * overridden by subclasses that provide a view hierarchy (such as {@link ViewGroup}). Other
32581      * classes should override {@link View#onCreateViewTranslationRequest} for normal view or
32582      * override {@link View#onVirtualViewTranslationResponses} for view contains virtual children.
32583      * When requested to start the ui translation, the system will call this method to traverse the
32584      * view hierarchy to collect {@link ViewTranslationRequest}s and create a
32585      * {@link android.view.translation.Translator} to translate the requests. All the
32586      * {@link ViewTranslationRequest}s must be added when the traversal is done.
32587      *
32588      * <p> The default implementation calls {@link View#onCreateViewTranslationRequest} for normal
32589      * view or calls {@link View#onVirtualViewTranslationResponses} for view contains virtual
32590      * children to build {@link ViewTranslationRequest} if the view should be translated.
32591      * The view is marked as having {@link #setHasTransientState(boolean) transient state} so that
32592      * recycling of views doesn't prevent the system from attaching the response to it. Therefore,
32593      * if overriding this method, you should set or reset the transient state. </p>
32594      *
32595      * @param viewIds a map for the view's {@link AutofillId} and its virtual child ids or
32596      * {@code null} if the view doesn't have virtual child that should be translated. The virtual
32597      * child ids are the same virtual ids provided by ContentCapture.
32598      * @param supportedFormats the supported translation formats. For now, the only possible value
32599      * is the {@link android.view.translation.TranslationSpec#DATA_FORMAT_TEXT}.
32600      * @param capability a {@link TranslationCapability} that holds translation capability.
32601      * information, e.g. source spec, target spec.
32602      * @param requests fill in with {@link ViewTranslationRequest}s for translation purpose.
32603      */
dispatchCreateViewTranslationRequest(@onNull Map<AutofillId, long[]> viewIds, @NonNull @DataFormat int[] supportedFormats, @NonNull TranslationCapability capability, @NonNull List<ViewTranslationRequest> requests)32604     public void dispatchCreateViewTranslationRequest(@NonNull Map<AutofillId, long[]> viewIds,
32605             @NonNull @DataFormat int[] supportedFormats,
32606             @NonNull TranslationCapability capability,
32607             @NonNull List<ViewTranslationRequest> requests) {
32608         AutofillId autofillId = getAutofillId();
32609         if (viewIds.containsKey(autofillId)) {
32610             if (viewIds.get(autofillId) == null) {
32611                 // TODO: avoiding the allocation per view
32612                 onCreateViewTranslationRequest(supportedFormats,
32613                         new ViewTranslationRequestConsumer(requests));
32614             } else {
32615                 onCreateVirtualViewTranslationRequests(viewIds.get(autofillId), supportedFormats,
32616                         request -> {
32617                             requests.add(request);
32618                         });
32619             }
32620         }
32621     }
32622 
32623     private class ViewTranslationRequestConsumer implements Consumer<ViewTranslationRequest> {
32624         private final List<ViewTranslationRequest> mRequests;
32625         private boolean mCalled;
32626 
ViewTranslationRequestConsumer(List<ViewTranslationRequest> requests)32627         ViewTranslationRequestConsumer(List<ViewTranslationRequest> requests) {
32628             mRequests = requests;
32629         }
32630 
32631         @Override
accept(ViewTranslationRequest request)32632         public void accept(ViewTranslationRequest request) {
32633             if (mCalled) {
32634                 throw new IllegalStateException("The translation Consumer is not reusable.");
32635             }
32636             mCalled = true;
32637             if (request != null && request.getKeys().size() > 0) {
32638                 mRequests.add(request);
32639                 if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
32640                     Log.v(CONTENT_CAPTURE_LOG_TAG, "Calling setHasTransientState(true) for "
32641                             + getAutofillId());
32642                 }
32643                 setHasTransientState(true);
32644                 setHasTranslationTransientState(true);
32645             }
32646         }
32647     }
32648 
32649     /**
32650      * Called to generate a {@link DisplayHash} for this view.
32651      *
32652      * @param hashAlgorithm The hash algorithm to use when hashing the display. Must be one of
32653      *                      the values returned from
32654      *                      {@link DisplayHashManager#getSupportedHashAlgorithms()}
32655      * @param bounds The bounds for the content within the View to generate the hash for. If
32656      *               bounds are null, the entire View's bounds will be used. If empty, it will
32657      *               invoke the callback
32658      *               {@link DisplayHashResultCallback#onDisplayHashError} with error
32659      *               {@link DisplayHashResultCallback#DISPLAY_HASH_ERROR_INVALID_BOUNDS}
32660      * @param executor The executor that the callback should be invoked on.
32661      * @param callback The callback to handle the results of generating the display hash
32662      */
generateDisplayHash(@onNull String hashAlgorithm, @Nullable Rect bounds, @NonNull Executor executor, @NonNull DisplayHashResultCallback callback)32663     public void generateDisplayHash(@NonNull String hashAlgorithm,
32664             @Nullable Rect bounds, @NonNull Executor executor,
32665             @NonNull DisplayHashResultCallback callback) {
32666         IWindowSession session = getWindowSession();
32667         if (session == null) {
32668             callback.onDisplayHashError(DISPLAY_HASH_ERROR_MISSING_WINDOW);
32669             return;
32670         }
32671         IWindow window = getWindow();
32672         if (window == null) {
32673             callback.onDisplayHashError(DISPLAY_HASH_ERROR_MISSING_WINDOW);
32674             return;
32675         }
32676 
32677         Rect visibleBounds = new Rect();
32678         getGlobalVisibleRect(visibleBounds);
32679 
32680         if (bounds != null && bounds.isEmpty()) {
32681             callback.onDisplayHashError(DISPLAY_HASH_ERROR_INVALID_BOUNDS);
32682             return;
32683         }
32684 
32685         if (bounds != null) {
32686             bounds.offset(visibleBounds.left, visibleBounds.top);
32687             visibleBounds.intersectUnchecked(bounds);
32688         }
32689 
32690         if (visibleBounds.isEmpty()) {
32691             callback.onDisplayHashError(DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN);
32692             return;
32693         }
32694 
32695         RemoteCallback remoteCallback = new RemoteCallback(result ->
32696                 executor.execute(() -> {
32697                     DisplayHash displayHash = result.getParcelable(EXTRA_DISPLAY_HASH, android.view.displayhash.DisplayHash.class);
32698                     int errorCode = result.getInt(EXTRA_DISPLAY_HASH_ERROR_CODE,
32699                             DISPLAY_HASH_ERROR_UNKNOWN);
32700                     if (displayHash != null) {
32701                         callback.onDisplayHashResult(displayHash);
32702                     } else {
32703                         callback.onDisplayHashError(errorCode);
32704                     }
32705                 }));
32706 
32707         try {
32708             session.generateDisplayHash(window, visibleBounds, hashAlgorithm, remoteCallback);
32709         } catch (RemoteException e) {
32710             Log.e(VIEW_LOG_TAG, "Failed to call generateDisplayHash");
32711             callback.onDisplayHashError(DISPLAY_HASH_ERROR_UNKNOWN);
32712         }
32713     }
32714 
32715     /**
32716      * The AttachedSurfaceControl itself is not a View, it is just the interface to the
32717      * windowing-system object that contains the entire view hierarchy.
32718      * For the root View of a given hierarchy see {@link #getRootView}.
32719 
32720      * @return The {@link android.view.AttachedSurfaceControl} interface for this View.
32721      * This will only return a non-null value when called between {@link #onAttachedToWindow}
32722      * and {@link #onDetachedFromWindow}.
32723      */
getRootSurfaceControl()32724     public @Nullable AttachedSurfaceControl getRootSurfaceControl() {
32725         if (mAttachInfo != null) {
32726           return mAttachInfo.getRootSurfaceControl();
32727         }
32728         return null;
32729     }
32730 }
32731